Allow Content-Type application/sru+xml YAZ-840
[yaz-moved-to-github.git] / src / srwutil.c
index 7be212a..1de920d 100644 (file)
 
 #define MAX_SRU_PARAMETERS 30
 
+static Z_SRW_extra_arg **append_extra_arg(ODR odr, Z_SRW_extra_arg **l,
+                                          const char *n, const char *v)
+{
+    if (n && v && *v != '\0')
+    {
+        while (*l)
+            l = &(*l)->next;
+        *l = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**l));
+        (*l)->name = odr_strdup(odr, n);
+        (*l)->value = odr_strdup(odr, v);
+        (*l)->next = 0;
+        l = &(*l)->next;
+    }
+    return l;
+}
+
+static Z_SRW_extra_arg **append_extra_arg_int(ODR odr, Z_SRW_extra_arg **l,
+                                              const char *n, Odr_int *v)
+{
+    if (v)
+    {
+        char str[32];
+        sprintf(str, ODR_INT_PRINTF, *v);
+        l = append_extra_arg(odr, l, n, str);
+    }
+    return l;
+}
+
 static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
 {
     return odr_strdupn(n, uri, len);
@@ -39,33 +67,6 @@ char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
     return dst;
 }
 
-Z_AttributeList *yaz_use_attribute_create(ODR o, const char *name)
-{
-    Z_AttributeList *attributes= (Z_AttributeList *)
-        odr_malloc(o, sizeof(*attributes));
-    Z_AttributeElement ** elements;
-    attributes->num_attributes = 1;
-    elements = (Z_AttributeElement**)
-        odr_malloc(o, attributes->num_attributes * sizeof(*elements));
-    elements[0] = (Z_AttributeElement*) odr_malloc(o,sizeof(**elements));
-    elements[0]->attributeType = odr_intdup(o, 1);
-    elements[0]->attributeSet = odr_nullval();
-    elements[0]->which = Z_AttributeValue_complex;
-    elements[0]->value.complex = (Z_ComplexAttribute *)
-        odr_malloc(o, sizeof(Z_ComplexAttribute));
-    elements[0]->value.complex->num_list = 1;
-    elements[0]->value.complex->list = (Z_StringOrNumeric **)
-        odr_malloc(o, 1 * sizeof(Z_StringOrNumeric *));
-    elements[0]->value.complex->list[0] = (Z_StringOrNumeric *)
-        odr_malloc(o, sizeof(Z_StringOrNumeric));
-    elements[0]->value.complex->list[0]->which = Z_StringOrNumeric_string;
-    elements[0]->value.complex->list[0]->u.string = odr_strdup(o, name);
-    elements[0]->value.complex->semanticAction = 0;
-    elements[0]->value.complex->num_semanticAction = 0;
-    attributes->attributes = elements;
-    return attributes;
-}
-
 #if YAZ_HAVE_XML2
 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
                                             const char *node_name,
@@ -96,6 +97,8 @@ int yaz_srw_check_content_type(Z_HTTP_Response *hres)
             return 1;
         if (!yaz_strcmp_del("application/xml", content_type, "; "))
             return 1;
+        if (!yaz_strcmp_del("application/sru+xml", content_type, "; "))
+            return 1;
     }
     return 0;
 }
@@ -415,7 +418,7 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             p1 = p0 + strlen(p0);
         if (p1 != p0)
             db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
-        if (!strcmp(hreq->method, "POST"))
+        if (!strcmp(hreq->method, "POST") && hreq->content_buf)
             p1 = hreq->content_buf;
         yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
 #if YAZ_HAVE_XML2
@@ -480,13 +483,7 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                     ; /* ignoring extraRequestData */
                 else if (n[0] == 'x' && n[1] == '-')
                 {
-                    Z_SRW_extra_arg **l = &extra_args;
-                    while (*l)
-                        l = &(*l)->next;
-                    *l = (Z_SRW_extra_arg *) odr_malloc(decode, sizeof(**l));
-                    (*l)->name = odr_strdup(decode, n);
-                    (*l)->value = odr_strdup(decode, v);
-                    (*l)->next = 0;
+                    append_extra_arg(decode, &extra_args, n, v);
                 }
                 else
                 {
@@ -502,6 +499,8 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                 operation = "searchRetrieve";
             else if (scanClause)
                 operation = "scan";
+            else
+                operation = "explain";
         }
         version = yaz_negotiate_sru_version(version);
 
@@ -759,12 +758,68 @@ Z_SRW_PDU *yaz_srw_get(ODR o, int which)
     return yaz_srw_get_pdu(o, which, "2.0");
 }
 
+/* http://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/schemas/sruResponse.xsd */
+Z_SRW_PDU *yaz_srw_get_pdu_e(ODR o, int which, Z_SRW_PDU *req)
+{
+    int version2 = !req->srw_version || strcmp(req->srw_version, "2.") > 0;
+    Z_SRW_PDU *res = yaz_srw_get_pdu(o, which, req->srw_version);
+    Z_SRW_extra_arg **l = &res->extra_args, *ea;
+    l = append_extra_arg(o, l, "version", req->srw_version);
+    if (req->which == Z_SRW_searchRetrieve_request &&
+        which == Z_SRW_searchRetrieve_response)
+    {
+        if (req->u.request->queryType &&
+            strcmp(req->u.request->queryType, "cql"))
+            l = append_extra_arg(o, l, "queryType", req->u.request->queryType);
+        l = append_extra_arg(o, l, "query", req->u.request->query);
+        l = append_extra_arg_int(o, l, "startRecord",
+                                 req->u.request->startRecord);
+        l = append_extra_arg_int(o, l, "maximumRecords",
+                                 req->u.request->maximumRecords);
+        if (version2)
+        {
+            l = append_extra_arg(o, l, "recordXMLEscaping",
+                                 req->u.request->recordPacking);
+            l = append_extra_arg(o, l, "recordPacking",
+                                 req->u.request->packing);
+        }
+        else
+            l = append_extra_arg(o, l, "recordPacking",
+                                 req->u.request->recordPacking);
+        l = append_extra_arg(o, l, "recordSchema",
+                             req->u.request->recordSchema);
+        if (req->u.request->sort_type == Z_SRW_sort_type_sort)
+            l = append_extra_arg(o, l, "sortKeys",
+                                 req->u.request->sort.sortKeys);
+        l = append_extra_arg(o, l, "stylesheet", req->u.request->stylesheet);
+    }
+    if (req->which == Z_SRW_explain_request &&
+        which == Z_SRW_explain_response)
+    {
+        if (version2)
+        {
+            l = append_extra_arg(o, l, "recordXMLEscaping",
+                                 req->u.explain_request->recordPacking);
+            l = append_extra_arg(o, l, "recordPacking",
+                                 req->u.explain_request->packing);
+        }
+        else
+            l = append_extra_arg(o, l, "recordPacking",
+                                 req->u.explain_request->recordPacking);
+        l = append_extra_arg(o, l, "stylesheet",
+                             req->u.explain_request->stylesheet);
+    }
+    for (ea = req->extra_args; ea; ea = ea->next)
+        l = append_extra_arg(o, l, ea->name, ea->value);
+    return res;
+}
+
 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
 {
     Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
 
     sr->which = which;
-    switch(which)
+    switch (which)
     {
     case Z_SRW_searchRetrieve_request:
         sr->u.request = (Z_SRW_searchRetrieveRequest *)
@@ -1052,6 +1107,7 @@ int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
     char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
     char *uri_args;
     char *path;
+    char *cp;
 
     z_HTTP_header_add_basic_auth(encode, &hreq->headers,
                                  srw_pdu->username, srw_pdu->password);
@@ -1061,10 +1117,15 @@ int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
 
     hreq->method = "GET";
 
+    cp = strchr(hreq->path, '#');
+    if (cp)
+        *cp = '\0';
+
     path = (char *)
         odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
 
-    sprintf(path, "%s?%s", hreq->path, uri_args);
+    sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?', 
+            uri_args);
     hreq->path = path;
 
     z_HTTP_header_add_content_type(encode, &hreq->headers,
@@ -1181,19 +1242,12 @@ void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
         Z_SRW_extra_arg **ea = &sr->extra_args;
         yaz_uri_to_array(extra_args, odr, &name, &val);
 
-        /** append rather than override */
-        while (*ea)
-            ea = &(*ea)->next;
         while (*name)
         {
-            *ea = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**ea));
-            (*ea)->name = *name;
-            (*ea)->value = *val;
-            ea = &(*ea)->next;
+            ea = append_extra_arg(odr, ea, *name, *val);
             val++;
             name++;
         }
-        *ea = 0;
     }
 }