Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/yaz
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 25 Jan 2010 10:59:29 +0000 (11:59 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 25 Jan 2010 10:59:29 +0000 (11:59 +0100)
20 files changed:
NEWS
client/client.c
configure.ac
doc/zoom.xml
include/yaz/Makefile.am
include/yaz/xml_include.h [new file with mode: 0644]
src/Makefile.am
src/json.c
src/xml_include.c [new file with mode: 0644]
src/zoom-c.c
src/zoom-p.h
test/.gitignore
test/Makefile.am
test/tst_comstack.c
test/tst_json.c
test/tst_xml_include.c [new file with mode: 0644]
test/tst_xml_include.xml [new file with mode: 0644]
test/tstcomstack.c [deleted file]
win/makefile
win/yaz.nsi

diff --git a/NEWS b/NEWS
index 3ac49d6..b5853d3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+ZOOM_record_get supports new parameter "format" which makes it format
+XML record content.
+
 --- 4.0.0 2010/01/20
 
 Windows binaries for YAZ now compiled with Visual Studio 2008 (VC9).
index cb783b2..9717d29 100644 (file)
@@ -4965,7 +4965,10 @@ static void client(void)
         {
             line_in=readline(C_PROMPT);
             if (!line_in)
+            {
+                putchar('\n');
                 break;
+            }
 #if HAVE_READLINE_HISTORY_H
             if (*line_in)
                 add_history(line_in);
index ce9e760..01f0835 100644 (file)
@@ -21,7 +21,7 @@ dnl
 YAZ_DOC
 dnl 
 dnl
-AC_CHECK_HEADERS([dirent.h fnmatch.h wchar.h locale.h langinfo.h pwd.h unistd.h sys/select.h sys/socket.h sys/stat.h sys/time.h sys/times.h sys/types.h sys/un.h sys/wait.h netdb.h arpa/inet.h netinet/tcp.h netinet/in_systm.h],[],[],[])
+AC_CHECK_HEADERS([dirent.h fnmatch.h wchar.h locale.h langinfo.h pwd.h unistd.h sys/select.h sys/socket.h sys/stat.h sys/time.h sys/times.h sys/types.h glob.h sys/un.h sys/wait.h netdb.h arpa/inet.h netinet/tcp.h netinet/in_systm.h],[],[],[])
 AC_CHECK_HEADERS([net/if.h netinet/in.h netinet/if_ether.h],[],[],[
  #if HAVE_SYS_TYPES_H
  #include <sys/types.h>
index ebf09ee..041949a 100644 (file)
@@ -726,7 +726,7 @@ ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
     The <parameter>type</parameter> is a string of the format:
    </para>
    <para>
-    <replaceable>form</replaceable>[; charset=<replaceable>from</replaceable>[,<replaceable>to</replaceable>]]
+    <replaceable>form</replaceable>[;charset=<replaceable>from</replaceable>[,<replaceable>to</replaceable>]][;format=<replaceable>v</replaceable>]
    </para>
    <para>
     where <replaceable>form</replaceable> specifies the format of the
@@ -739,6 +739,12 @@ ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
     If <replaceable>to</replaceable> is omitted UTF-8 is assumed.
    </para>
    <para>
+    The format argument controls whether record data should be XML
+    pretty-printed (post process operation).
+    It is enabled only if format value <replaceable>v</replaceable> is 
+    <literal>1</literal> and the record content is XML well-formed.
+   </para>
+   <para>
     In addition, for certain types, the length
     <literal>len</literal> passed will be set to the size in bytes of
     the returned information. 
index 246dbd8..d40777d 100644 (file)
@@ -12,7 +12,7 @@ pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h rpn2cql.h comstack.h \
  yaz-ccl.h yaz-iconv.h yaz-util.h yaz-version.h yconfig.h proto.h \
  xmlquery.h xmltypes.h snprintf.h query-charset.h \
  mutex.h oid_db.h oid_util.h oid_std.h tokenizer.h copy_types.h \
- icu.h match_glob.h poll.h daemon.h sc.h \
+ icu.h match_glob.h poll.h daemon.h sc.h xml_include.h \
  \
  ill.h ill-core.h item-req.h oclc-ill-req-ext.h z-accdes1.h z-accform1.h \
  z-acckrb1.h z-core.h z-date.h z-diag1.h z-espec1.h z-estask.h z-exp.h \
diff --git a/include/yaz/xml_include.h b/include/yaz/xml_include.h
new file mode 100644 (file)
index 0000000..6840dd9
--- /dev/null
@@ -0,0 +1,69 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2010 Index Data.
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Index Data nor the names of its contributors
+ *       may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file 
+    \brief XML Include (not to be confused with W3C XInclude)
+*/
+
+#ifndef YAZ_XML_INCLUDE_H
+#define YAZ_XML_INCLUDE_H
+
+#include <yaz/yconfig.h>
+#include <yaz/xmltypes.h>
+
+YAZ_BEGIN_CDECL
+
+#if YAZ_HAVE_XML2
+
+/** \brief substitute include nodes in a tree
+    \param n node where include is peformed
+    \param base_path base_path - for relative file specs
+    \retval 0 OK
+    \retval -1 FAILURE
+
+    Nodes of the form <include src="glob-pattern"/> are substituted with
+    contents of files matching glob-pattern. Do not use this function
+    on XML from untrusted sources -- from the net from example -- local
+    trusted XML configuration ONLY.
+*/
+YAZ_EXPORT
+int yaz_xml_include_simple(xmlNode *n, const char *base_path);
+
+#endif
+YAZ_END_CDECL
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 23eeeef..7cff54e 100644 (file)
@@ -103,7 +103,7 @@ libyaz_la_SOURCES=version.c options.c log.c \
   copy_types.c match_glob.c poll.c daemon.c \
   iconv_encode_marc8.c iconv_encode_iso_8859_1.c iconv_encode_wchar.c \
   iconv_decode_marc8.c iconv_decode_iso5426.c iconv_decode_danmarc.c sc.c \
-  json.c
+  json.c xml_include.c
 
 libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO)
 
index 4c41613..6c34fcb 100644 (file)
@@ -420,7 +420,7 @@ struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
     p->buf = json_str;
     p->cp = p->buf;
 
-    n = json_parse_object(p);
+    n = json_parse_value(p);
     if (!n)
         return 0;
     c = look_ch(p);
diff --git a/src/xml_include.c b/src/xml_include.c
new file mode 100644 (file)
index 0000000..add66d9
--- /dev/null
@@ -0,0 +1,183 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2010 Index Data
+ * See the file LICENSE for details.
+ */
+
+/** \file 
+    \brief XML Include (not to be confused with W3C XInclude)
+*/
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if HAVE_GLOB_H
+#define USE_POSIX_GLOB 1
+#else
+#define USE_POSIX_GLOB 0
+#endif
+
+#if USE_POSIX_GLOB
+#include <glob.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <yaz/wrbuf.h>
+#include <yaz/tpath.h>
+#include <yaz/log.h>
+#include <yaz/xml_include.h>
+
+#if YAZ_HAVE_XML2
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+struct yaz_xml_include_s {
+    const char *confdir;
+};
+
+typedef struct yaz_xml_include_s *yaz_xml_include_t;
+
+static int process_config_includes(yaz_xml_include_t config, xmlNode *n);
+
+static void conf_dir_path(yaz_xml_include_t config, WRBUF w, const char *src)
+{
+    if (config->confdir && *config->confdir > 0 &&
+        !yaz_is_abspath(src))
+    {
+        wrbuf_printf(w, "%s/%s", config->confdir, src);
+    }
+    else
+        wrbuf_puts(w, src);
+}
+
+static int config_include_one(yaz_xml_include_t config, xmlNode **sib,
+                              const char *path)
+{
+    struct stat st;
+    if (stat(path, &st) < 0)
+    {
+        yaz_log(YLOG_FATAL|YLOG_ERRNO, "stat %s", path);
+        return -1;
+    }
+    else
+    {
+        if ((st.st_mode & S_IFMT) == S_IFREG)
+        {
+            xmlDoc *doc = xmlParseFile(path);
+            if (doc)
+            {
+                xmlNodePtr t = xmlDocGetRootElement(doc);
+                int ret = process_config_includes(config, t);
+                *sib = xmlAddNextSibling(*sib, xmlCopyNode(t, 1));
+                xmlFreeDoc(doc);
+                if (ret)
+                    return -1;
+            }
+            else
+            {
+                yaz_log(YLOG_FATAL, "Could not parse %s", path);
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+static int config_include_src(yaz_xml_include_t config, xmlNode **np,
+                              const char *src)
+{
+    int ret = 0; /* return code. OK so far */
+    WRBUF w = wrbuf_alloc();
+    xmlNodePtr sib; /* our sibling that we append */
+    xmlNodePtr c; /* tmp node */
+
+    wrbuf_printf(w, " begin include src=\"%s\" ", src);
+
+    /* replace include element with a 'begin' comment */
+    sib = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
+    xmlReplaceNode(*np, sib);
+
+    xmlFreeNode(*np);
+
+    wrbuf_rewind(w);
+    conf_dir_path(config, w, src);
+#if USE_POSIX_GLOB
+    {
+        size_t i;
+        glob_t glob_res;
+        glob(wrbuf_cstr(w), 0 /* flags */, 0 /* errfunc */, &glob_res);
+        
+        for (i = 0; ret == 0 && i < glob_res.gl_pathc; i++)
+        {
+            const char *path = glob_res.gl_pathv[i];
+            ret = config_include_one(config, &sib, path);
+        }
+        globfree(&glob_res);
+    }
+#else
+    ret = config_include_one(config, &sib, wrbuf_cstr(w));
+#endif
+    wrbuf_rewind(w);
+    wrbuf_printf(w, " end include src=\"%s\" ", src);
+    c = xmlNewComment((const xmlChar *) wrbuf_cstr(w));
+    sib = xmlAddNextSibling(sib, c);
+    
+    *np = sib;
+    wrbuf_destroy(w);
+    return ret;
+}
+
+static int process_config_includes(yaz_xml_include_t config, xmlNode *n)
+{
+    for (n = n->children; n; n = n->next)
+    {
+        if (n->type == XML_ELEMENT_NODE)
+        {
+            if (!strcmp((const char *) n->name, "include"))
+            {
+                xmlChar *src = xmlGetProp(n, (xmlChar *) "src");
+                if (src)
+                {
+                    int ret = config_include_src(config, &n,
+                                                 (const char *) src);
+                    xmlFree(src);
+                    if (ret)
+                        return ret;
+                        
+                }
+            }
+            else
+            {
+                if (process_config_includes(config, n))
+                    return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+int yaz_xml_include_simple(xmlNode *n, const char *base_path)
+{
+    struct yaz_xml_include_s s;
+
+    s.confdir = base_path;
+    process_config_includes(&s, n);
+    return 0;
+}
+
+/* YAZ_HAVE_XML2 */
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index cb6144e..14922ac 100644 (file)
@@ -1011,6 +1011,20 @@ ZOOM_API(int)
     return 0;
 }
 
+static void ZOOM_record_release(ZOOM_record rec)
+{
+    if (!rec)
+        return;
+    if (rec->wrbuf)
+        wrbuf_destroy(rec->wrbuf);
+#if YAZ_HAVE_XML2
+    if (rec->xml_mem)
+        xmlFree(rec->xml_mem);
+#endif
+    if (rec->odr)
+        odr_destroy(rec->odr);
+}
+
 ZOOM_API(void)
     ZOOM_resultset_cache_reset(ZOOM_resultset r)
 {
@@ -1020,8 +1034,7 @@ ZOOM_API(void)
         ZOOM_record_cache rc;
         for (rc = r->record_hash[i]; rc; rc = rc->next)
         {
-            if (rc->rec.wrbuf)
-                wrbuf_destroy(rc->rec.wrbuf);
+            ZOOM_record_release(&rc->rec);
         }
         r->record_hash[i] = 0;
     }
@@ -1780,6 +1793,10 @@ ZOOM_API(ZOOM_record)
     nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
     nrec->odr = odr_createmem(ODR_DECODE);
     nrec->wrbuf = 0;
+#if YAZ_HAVE_XML2
+    nrec->xml_mem = 0;
+    nrec->xml_size = 0;
+#endif
     odr_setbuf(nrec->odr, buf, size, 0);
     z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
     
@@ -1827,11 +1844,7 @@ ZOOM_API(ZOOM_record)
 ZOOM_API(void)
     ZOOM_record_destroy(ZOOM_record rec)
 {
-    if (!rec)
-        return;
-    if (rec->wrbuf)
-        wrbuf_destroy(rec->wrbuf);
-    odr_destroy(rec->odr);
+    ZOOM_record_release(rec);
     xfree(rec);
 }
 
@@ -2058,12 +2071,40 @@ ZOOM_API(int)
     return 0;
 }
 
+static const char *get_record_format(ZOOM_record rec, int *len,
+                                     Z_NamePlusRecord *npr,
+                                     int marctype, const char *charset,
+                                     const char *format)
+{
+    const char *res = return_record(rec, len, npr, marctype, charset);
+#if YAZ_HAVE_XML2
+    if (*format == '1' && len)
+    {
+        /* try to XML format res */
+        xmlDocPtr doc;
+        xmlKeepBlanksDefault(0); /* get get xmlDocFormatMemory to work! */
+        doc = xmlParseMemory(res, *len);
+        if (doc)
+        {
+            if (rec->xml_mem)
+                xmlFree(rec->xml_mem);
+            xmlDocDumpFormatMemory(doc, &rec->xml_mem, &rec->xml_size, 1);
+            xmlFreeDoc(doc);
+            res = (char *) rec->xml_mem;
+            *len = rec->xml_size;
+        } 
+    }
+#endif
+    return res;
+}
+
+
 ZOOM_API(const char *)
     ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
 {
     char type[40];
     char charset[40];
-    char xpath[512];
+    char format[3];
     const char *cp;
     size_t i;
     Z_NamePlusRecord *npr;
@@ -2078,41 +2119,43 @@ ZOOM_API(const char *)
         return 0;
 
     cp = type_spec;
-    for (i = 0; cp[i] && i < sizeof(type)-1; i++)
-    {
-        if (cp[i] == ';' || cp[i] == ' ')
-            break;
+    for (i = 0; cp[i] && cp[i] != ';' && cp[i] != ' ' && i < sizeof(type)-1;
+         i++)
         type[i] = cp[i];
-    }
     type[i] = '\0';
     charset[0] = '\0';
-    while (type_spec[i] == ';')
+    format[0] = '\0';
+    while (1)
     {
+        while (cp[i] == ' ')
+            i++;
+        if (cp[i] != ';')
+            break;
         i++;
-        while (type_spec[i] == ' ')
+        while (cp[i] == ' ')
             i++;
-        if (!strncmp(type_spec+i, "charset=", 8))
+        if (!strncmp(cp + i, "charset=", 8))
         {
             size_t j = 0;
             i = i + 8; /* skip charset= */
-            for (j = 0; type_spec[i]  && j < sizeof(charset)-1; i++, j++)
+            for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++)
             {
-                if (type_spec[i] == ';' || type_spec[i] == ' ')
-                    break;
-                charset[j] = cp[i];
+                if (j < sizeof(charset)-1)
+                    charset[j++] = cp[i];
             }
             charset[j] = '\0';
         }
-        else if (!strncmp(type_spec+i, "xpath=", 6))
+        else if (!strncmp(cp + i, "format=", 7))
         {
             size_t j = 0; 
-            i = i + 6;
-            for (j = 0; type_spec[i] && j < sizeof(xpath)-1; i++, j++)
-                xpath[j] = cp[i];
-            xpath[j] = '\0';
+            i = i + 7;
+            for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++)
+            {
+                if (j < sizeof(format)-1)
+                    format[j++] = cp[i];
+            }
+            format[j] = '\0';
         } 
-        while (type_spec[i] == ' ')
-            i++;
     }
     if (!strcmp(type, "database"))
     {
@@ -2146,15 +2189,17 @@ ZOOM_API(const char *)
     /* from now on - we have a database record .. */
     if (!strcmp(type, "render"))
     {
-        return return_record(rec, len, npr, YAZ_MARC_LINE, charset);
+        return get_record_format(rec, len, npr, YAZ_MARC_LINE, charset, format);
     }
     else if (!strcmp(type, "xml"))
     {
-        return return_record(rec, len, npr, YAZ_MARC_MARCXML, charset);
+        return get_record_format(rec, len, npr, YAZ_MARC_MARCXML, charset,
+                                 format);
     }
     else if (!strcmp(type, "raw"))
     {
-        return return_record(rec, len, npr, YAZ_MARC_ISO2709, charset);
+        return get_record_format(rec, len, npr, YAZ_MARC_ISO2709, charset,
+            format);
     }
     else if (!strcmp(type, "ext"))
     {
@@ -2164,7 +2209,8 @@ ZOOM_API(const char *)
     else if (!strcmp(type, "opac"))
     {
         if (npr->u.databaseRecord->which == Z_External_OPAC)
-            return return_record(rec, len, npr, YAZ_MARC_MARCXML, charset);
+            return get_record_format(rec, len, npr, YAZ_MARC_MARCXML, charset,
+                format);
     }
     return 0;
 }
@@ -2209,6 +2255,9 @@ static void record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
         rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
         rc->rec.odr = 0;
         rc->rec.wrbuf = 0;
+#if YAZ_HAVE_XML2
+        rc->rec.xml_mem = 0;
+#endif
         rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
         
         rc->syntax = odr_strdup_null(r->odr, syntax);
index bde6b55..a464f29 100644 (file)
@@ -150,6 +150,11 @@ struct ZOOM_record_p {
     Z_NamePlusRecord *npr;
     const char *schema;
 
+#if YAZ_HAVE_XML2
+    xmlChar *xml_mem;
+    int xml_size;
+#endif
+
     const char *diag_uri;
     const char *diag_message;
     const char *diag_details;
index dabacdc..0ffa500 100644 (file)
@@ -29,6 +29,7 @@ tst_icu_I18N
 tst_match_glob
 tst_rpn2cql
 tst_json
+tst_xml_include
 nfatest1
 nfaxmltest1
 tst_oid
index a381d77..e813f65 100644 (file)
@@ -2,11 +2,11 @@
 ## Copyright (C) 1995-2010 Index Data
 
 check_PROGRAMS = tstxmalloc tsticonv tstnmem tstmatchstr tstwrbuf tstodr \
- tstccl tstlog tstcomstack \
+ tstccl tstlog \
  tstsoap1 tstsoap2 tstodrstack tstlogthread tstxmlquery tstpquery \
  tst_comstack tst_filepath tst_record_conv tst_retrieval tst_tpath \
  tst_timing tst_query_charset tst_oid tst_icu_I18N tst_match_glob \
- tst_rpn2cql tst_json
+ tst_rpn2cql tst_json tst_xml_include
 
 check_SCRIPTS = tstmarc.sh tstmarccol.sh tstcql2xcql.sh tstcql2pqf.sh tsticu.sh
 
@@ -31,7 +31,7 @@ EXTRA_DIST = tstodr.asn tstodrcodec.c tstodrcodec.h cql2xcqlsample \
  marccol5.u8.marc marccol5.u8.1.lst marccol5.u8.2.lst \
  tsticu-0.xml tsticu-0.input tsticu-0.output \
  tsticu-1.xml tsticu-1.input tsticu-1.output \
- tst_record_conv.xsl 
+ tst_record_conv.xsl tst_xml_include.xml
 
 YAZCOMP = ../util/yaz-asncomp
 YAZCOMPLINE = $(YAZCOMP) -d z.tcl -i yaz -I../include $(YCFLAGS)
@@ -62,7 +62,6 @@ tstodr_SOURCES = tstodrcodec.c tstodrcodec.h tstodr.c
 tstodrstack_SOURCES = tstodrstack.c
 tstccl_SOURCES = tstccl.c
 tstlog_SOURCES = tstlog.c
-tstcomstack_SOURCES = tstcomstack.c
 tstsoap1_SOURCES = tstsoap1.c
 tstsoap2_SOURCES = tstsoap2.c
 tstlogthread_SOURCES = tstlogthread.c
@@ -80,3 +79,4 @@ tst_icu_I18N_SOURCES = tst_icu_I18N.c
 tst_match_glob_SOURCES = tst_match_glob.c
 tst_rpn2cql_SOURCES = tst_rpn2cql.c
 tst_json_SOURCES = tst_json.c
+tst_xml_include_SOURCES = tst_xml_include.c
index e75653f..eee72f8 100644 (file)
@@ -4,10 +4,12 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <stdio.h>
 
 #include <yaz/test.h>
 #include <yaz/comstack.h>
+#include <yaz/tcpip.h>
 
 static void tst_http_request(void)
 {
@@ -185,11 +187,71 @@ static void tst_http_response(void)
     }
 }
 
+/** \brief COMSTACK synopsis from manual, doc/comstack.xml */
+static int comstack_example(const char *server_address_str)
+{    
+    COMSTACK stack;
+    char *buf = 0;
+    int size = 0, length_incoming;
+    void *server_address_ip;
+    int status;
+
+    char *protocol_package = "GET / HTTP/1.0\r\n\r\n";
+    int protocol_package_length = strlen(protocol_package);
+
+    stack = cs_create(tcpip_type, 1, PROTO_HTTP);
+    if (!stack) {
+        perror("cs_create");  /* use perror() here since we have no stack yet */
+        return -1;
+    }
+    
+    server_address_ip = cs_straddr(stack, server_address_str);
+    if (!server_address_ip)
+    {
+        fprintf(stderr, "cs_straddr: address could not be resolved\n");
+        return -1;
+    }
+    
+    status = cs_connect(stack, server_address_ip);
+    if (status != 0) {
+        fprintf(stderr, "cs_connect: %s\n", cs_strerror(stack));
+        return -1;
+    }
+    
+    status = cs_put(stack, protocol_package, protocol_package_length);
+    if (status) {
+        fprintf(stderr, "cs_put: %s\n", cs_strerror(stack));
+        return -1;
+    }
+    
+    /* Now get a response */
+    
+    length_incoming = cs_get(stack, &buf, &size);
+    if (!length_incoming) {
+        fprintf(stderr, "Connection closed\n");
+        return -1;
+    } else if (length_incoming < 0) {
+        fprintf(stderr, "cs_get: %s\n", cs_strerror(stack));
+        return -1;
+    }
+    
+    /* Print result */
+    fwrite(buf, length_incoming, 1, stdout);
+    
+    /* clean up */
+    cs_close(stack);
+    if (buf)
+        free(buf);
+    return 0;
+}
+
 
 int main (int argc, char **argv)
 {
     YAZ_CHECK_INIT(argc, argv);
     YAZ_CHECK_LOG();
+    if (argc == 2)
+       comstack_example(argv[1]);
     tst_http_request();
     tst_http_response();
     YAZ_CHECK_TERM;
index 8720290..eace27e 100644 (file)
@@ -49,9 +49,9 @@ static void tst1(void)
 
     YAZ_CHECK(expect(p, "", 0));
 
-    YAZ_CHECK(expect(p, "1234", 0));
+    YAZ_CHECK(expect(p, "1234", "1234"));
 
-    YAZ_CHECK(expect(p, "[ 1234 ]", 0));
+    YAZ_CHECK(expect(p, "[ 1234 ]", "[1234]"));
 
     YAZ_CHECK(expect(p, "{\"k\":tru}", 0));
 
diff --git a/test/tst_xml_include.c b/test/tst_xml_include.c
new file mode 100644 (file)
index 0000000..235cbbe
--- /dev/null
@@ -0,0 +1,78 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2010 Index Data
+ * See the file LICENSE for details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <yaz/xml_include.h>
+#include <yaz/test.h>
+
+static void tst_xml_include(void)
+{
+    const char *srcdir = getenv("srcdir");
+    xmlDocPtr doc;
+    xmlNodePtr node;
+    const char *xml_in = "<x><include src=\"tst_xml_include.xml\"/></x>";
+
+    if (srcdir == 0)
+        srcdir = ".";
+
+    doc = xmlParseMemory(xml_in, strlen(xml_in));
+    YAZ_CHECK(doc);
+    if (!doc)
+        return;
+    node = xmlDocGetRootElement(doc);
+    YAZ_CHECK(node);
+    if (node)
+    {
+        const char *expect =
+            "<?xml version=\"1.0\"?>\n"
+            "<x><!-- begin include src=\"tst_xml_include.xml\" -->"
+            "<y>some</y>"
+            "<!-- end include src=\"tst_xml_include.xml\" --></x>\n";
+
+        xmlChar *xml_out;
+        int len_out;
+        int ret = yaz_xml_include_simple(node, srcdir);
+        YAZ_CHECK(ret == 0);
+        xmlDocDumpMemory(doc, &xml_out, &len_out);
+        YAZ_CHECK(xml_out && len_out > 0);
+        if (xml_out && len_out > 0)
+        {
+            YAZ_CHECK(strlen(expect) == len_out);
+            if (strlen(expect) == len_out)
+            {
+                YAZ_CHECK(memcmp(expect, xml_out, len_out) == 0);
+            }
+            else
+            {
+                fwrite(xml_out, 1, len_out, stdout);
+                fflush(stdout);
+            }
+            xmlFree(xml_out);
+        }
+    }
+    xmlFreeDoc(doc);
+}
+
+
+int main (int argc, char **argv)
+{
+    YAZ_CHECK_INIT(argc, argv);
+    YAZ_CHECK_LOG();
+    tst_xml_include();
+    YAZ_CHECK_TERM;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/test/tst_xml_include.xml b/test/tst_xml_include.xml
new file mode 100644 (file)
index 0000000..da253be
--- /dev/null
@@ -0,0 +1 @@
+<y>some</y>
diff --git a/test/tstcomstack.c b/test/tstcomstack.c
deleted file mode 100644 (file)
index 9ced280..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2010 Index Data
- * See the file LICENSE for details.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <yaz/test.h>
-#include <yaz/comstack.h>
-#include <yaz/tcpip.h>
-
-static int comstack_example(const char *server_address_str)
-{    
-    COMSTACK stack;
-    char *buf = 0;
-    int size = 0, length_incoming;
-    void *server_address_ip;
-    int status;
-
-    char *protocol_package = "GET / HTTP/1.0\r\n\r\n";
-    int protocol_package_length = strlen(protocol_package);
-
-    stack = cs_create(tcpip_type, 1, PROTO_HTTP);
-    if (!stack) {
-        perror("cs_create");  /* use perror() here since we have no stack yet */
-        return -1;
-    }
-    
-    server_address_ip = cs_straddr(stack, server_address_str);
-    if (!server_address_ip)
-    {
-        fprintf(stderr, "cs_straddr: address could not be resolved\n");
-        return -1;
-    }
-    
-    status = cs_connect(stack, server_address_ip);
-    if (status != 0) {
-        fprintf(stderr, "cs_connect: %s\n", cs_strerror(stack));
-        return -1;
-    }
-    
-    status = cs_put(stack, protocol_package, protocol_package_length);
-    if (status) {
-        fprintf(stderr, "cs_put: %s\n", cs_strerror(stack));
-        return -1;
-    }
-    
-    /* Now get a response */
-    
-    length_incoming = cs_get(stack, &buf, &size);
-    if (!length_incoming) {
-        fprintf(stderr, "Connection closed\n");
-        return -1;
-    } else if (length_incoming < 0) {
-        fprintf(stderr, "cs_get: %s\n", cs_strerror(stack));
-        return -1;
-    }
-    
-    /* Print result */
-    fwrite(buf, length_incoming, 1, stdout);
-    
-    /* clean up */
-    cs_close(stack);
-    if (buf)
-        free(buf);
-    return 0;
-}
-
-
-int main(int argc, char **argv)
-{
-    YAZ_CHECK_INIT(argc, argv);
-    if (argc == 2)
-       comstack_example(argv[1]);
-    YAZ_CHECK_TERM;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 4
- * c-file-style: "Stroustrup"
- * indent-tabs-mode: nil
- * End:
- * vim: shiftwidth=4 tabstop=8 expandtab
- */
-
index e4e9b6d..e430cb9 100644 (file)
@@ -496,7 +496,8 @@ MISC_OBJS= \
    $(OBJDIR)\iconv_decode_danmarc.obj \
    $(OBJDIR)\mutex.obj \
    $(OBJDIR)\json.obj \
-   $(OBJDIR)\sc.obj
+   $(OBJDIR)\sc.obj \
+   $(OBJDIR)\xml_include.obj
 
 Z3950_OBJS= \
    $(OBJDIR)\z-date.obj\
index 397ed6e..fa33e89 100644 (file)
@@ -4,7 +4,7 @@
 !include version.nsi
 
 ; Microsoft runtime CRT 
-; Uncomment exactly ONE section of the three below
+; Uncomment exactly ONE of the sections below
 ; 1: MSVC 6
 ; !define VS_RUNTIME_DLL ""
 ; !define VS_RUNTIME_MANIFEST ""