Add comment about yaz_srw_decode hack
[yaz-moved-to-github.git] / src / srwutil.c
index 38ee0d0..2b6e099 100644 (file)
@@ -269,11 +269,12 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             const char *p0 = hreq->path, *p1;
             int ret = -1;
 
-            static Z_SOAP_Handler soap_handlers[4] = {
+            static Z_SOAP_Handler soap_handlers[5] = {
 #if YAZ_HAVE_XML2
                 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
                 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
                 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
+                { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
 #endif
                 {0, 0, 0}
             };
@@ -295,6 +296,10 @@ int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
                 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
 
+                /* last entry in handlers - SRU 2.0 - is turned into
+                   offset 0.. due to other pieces relying on it */
+                if ((*soap_package)->u.generic->no == 3)
+                    (*soap_package)->u.generic->no = 0;
                 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
                     (*srw_pdu)->u.request->database == 0)
                     (*srw_pdu)->u.request->database = db;
@@ -378,16 +383,16 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
         const char *operation = 0;
         char *version = 0;
         char *query = 0;
-        char *pQuery = 0;
+        char *queryType = "cql";
         char *username = 0;
         char *password = 0;
         char *sortKeys = 0;
         char *stylesheet = 0;
         char *scanClause = 0;
-        char *pScanClause = 0;
         char *recordXPath = 0;
         char *recordSchema = 0;
-        char *recordPacking = "xml";  /* xml packing is default for SRU */
+        char *recordXMLEscaping = 0;
+        char *recordPacking = 0;
         char *maximumRecords = 0;
         char *startRecord = 0;
         char *maximumTerms = 0;
@@ -422,7 +427,12 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                 if (!strcmp(n, "query"))
                     query = v;
                 else if (!strcmp(n, "x-pquery"))
-                    pQuery = v;
+                {
+                    query = v;
+                    queryType = "pqf";
+                }
+                else if (!strcmp(n, "queryType"))
+                    queryType = v;
                 else if (!strcmp(n, "x-username"))
                     username = v;
                 else if (!strcmp(n, "x-password"))
@@ -439,12 +449,17 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                     recordSchema = v;
                 else if (!strcmp(n, "recordPacking"))
                     recordPacking = v;
+                else if (!strcmp(n, "recordXMLEscaping"))
+                    recordXMLEscaping = v;
                 else if (!strcmp(n, "version"))
                     version = v;
                 else if (!strcmp(n, "scanClause"))
                     scanClause = v;
                 else if (!strcmp(n, "x-pScanClause"))
-                    pScanClause = v;
+                {
+                    scanClause = v;
+                    queryType = "pqf";
+                }
                 else if (!strcmp(n, "maximumRecords"))
                     maximumRecords = v;
                 else if (!strcmp(n, "startRecord"))
@@ -473,24 +488,16 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                 }
             }
         }
-        if (!version)
-        {
-            if (uri_name)
-                yaz_add_srw_diagnostic(
-                    decode, diag, num_diag,
-                    YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "version");
-            version = "1.1";
-        }
-
+        if (!operation && query)
+            operation = "searchRetrieve";
         version = yaz_negotiate_sru_version(version);
 
         if (!version)
         {   /* negotiation failed. */
             yaz_add_srw_diagnostic(decode, diag, num_diag,
-                                   YAZ_SRW_UNSUPP_VERSION, "1.2");
-            version = "1.2";
+                                   YAZ_SRW_UNSUPP_VERSION, "2.0");
+            version = "2.0";
         }
-
         if (!operation)
         {
             if (uri_name)
@@ -499,6 +506,20 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
                     YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
             operation = "explain";
         }
+        if (strcmp(version, "2.0"))
+        {
+            if (recordXMLEscaping)
+            {
+                yaz_add_srw_diagnostic(decode, diag, num_diag,
+                                       YAZ_SRW_UNSUPP_PARAMETER,
+                                       "recordXMLEscaping");
+
+            }
+            recordXMLEscaping = recordPacking;
+            recordPacking = "packed";
+        }
+        if (!recordXMLEscaping)
+            recordXMLEscaping = "xml";
         if (!strcmp(operation, "searchRetrieve"))
         {
             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
@@ -507,17 +528,11 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             sr->extra_args = extra_args;
             *srw_pdu = sr;
             yaz_srw_decodeauth(sr, hreq, username, password, decode);
-            if (query)
-            {
-                sr->u.request->query_type = Z_SRW_query_type_cql;
-                sr->u.request->query.cql = query;
-            }
-            else if (pQuery)
-            {
-                sr->u.request->query_type = Z_SRW_query_type_pqf;
-                sr->u.request->query.pqf = pQuery;
-            }
-            else
+
+            sr->u.request->queryType = queryType;
+            sr->u.request->query = query;
+
+            if (!query)
                 yaz_add_srw_diagnostic(
                     decode, diag, num_diag,
                     YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
@@ -529,7 +544,8 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             }
             sr->u.request->recordXPath = recordXPath;
             sr->u.request->recordSchema = recordSchema;
-            sr->u.request->recordPacking = recordPacking;
+            sr->u.request->recordPacking = recordXMLEscaping;
+            sr->u.request->packing = recordPacking;
             sr->u.request->stylesheet = stylesheet;
 
             yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
@@ -567,7 +583,8 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             sr->extra_args = extra_args;
             yaz_srw_decodeauth(sr, hreq, username, password, decode);
             *srw_pdu = sr;
-            sr->u.explain_request->recordPacking = recordPacking;
+            sr->u.explain_request->recordPacking = recordXMLEscaping;
+            sr->u.explain_request->packing = recordPacking;
             sr->u.explain_request->database = db;
 
             sr->u.explain_request->stylesheet = stylesheet;
@@ -598,17 +615,10 @@ int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
             *srw_pdu = sr;
             yaz_srw_decodeauth(sr, hreq, username, password, decode);
 
-            if (scanClause)
-            {
-                sr->u.scan_request->query_type = Z_SRW_query_type_cql;
-                sr->u.scan_request->scanClause.cql = scanClause;
-            }
-            else if (pScanClause)
-            {
-                sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
-                sr->u.scan_request->scanClause.pqf = pScanClause;
-            }
-            else
+            sr->u.scan_request->queryType = queryType;
+            sr->u.scan_request->scanClause = scanClause;
+
+            if (!scanClause)
                 yaz_add_srw_diagnostic(
                     decode, diag, num_diag,
                     YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
@@ -724,14 +734,14 @@ static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
     return p;
 }
 
-Z_SRW_PDU *yaz_srw_get_core_v_1_1(ODR o)
+Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
 {
-    return yaz_srw_get_core_ver(o, "1.1");
+    return yaz_srw_get_core_ver(o, "2.0");
 }
 
 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
 {
-    return yaz_srw_get_pdu(o, which, "1.1");
+    return yaz_srw_get_pdu(o, which, "2.0");
 }
 
 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
@@ -744,14 +754,15 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
     case Z_SRW_searchRetrieve_request:
         sr->u.request = (Z_SRW_searchRetrieveRequest *)
             odr_malloc(o, sizeof(*sr->u.request));
-        sr->u.request->query_type = Z_SRW_query_type_cql;
-        sr->u.request->query.cql = 0;
+        sr->u.request->queryType = "cql";
+        sr->u.request->query = 0;
         sr->u.request->sort_type = Z_SRW_sort_type_none;
         sr->u.request->sort.none = 0;
         sr->u.request->startRecord = 0;
         sr->u.request->maximumRecords = 0;
         sr->u.request->recordSchema = 0;
         sr->u.request->recordPacking = 0;
+        sr->u.request->packing = 0;
         sr->u.request->recordXPath = 0;
         sr->u.request->database = 0;
         sr->u.request->resultSetTTL = 0;
@@ -777,6 +788,7 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
         sr->u.explain_request = (Z_SRW_explainRequest *)
             odr_malloc(o, sizeof(*sr->u.explain_request));
         sr->u.explain_request->recordPacking = 0;
+        sr->u.explain_request->packing = 0;
         sr->u.explain_request->database = 0;
         sr->u.explain_request->stylesheet = 0;
         break;
@@ -800,8 +812,8 @@ Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
         sr->u.scan_request->stylesheet = 0;
         sr->u.scan_request->maximumTerms = 0;
         sr->u.scan_request->responsePosition = 0;
-        sr->u.scan_request->query_type = Z_SRW_query_type_cql;
-        sr->u.scan_request->scanClause.cql = 0;
+        sr->u.scan_request->queryType = "cql";
+        sr->u.scan_request->scanClause = 0;
         break;
     case Z_SRW_scan_response:
         sr->u.scan_response = (Z_SRW_scanResponse *)
@@ -868,29 +880,44 @@ void yaz_add_name_value_str(ODR o, char **name, char **value,  int *i,
 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
                              char **name, char **value, int max_names)
 {
+    int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
     int i = 0;
-    yaz_add_name_value_str(encode, name, value, &i, "version", srw_pdu->srw_version);
+    char *queryType;
+    if (!version2)
+        yaz_add_name_value_str(encode, name, value, &i, "version", srw_pdu->srw_version);
     name[i] = "operation";
-    switch(srw_pdu->which)
+    switch (srw_pdu->which)
     {
     case Z_SRW_searchRetrieve_request:
-        value[i++] = "searchRetrieve";
-        switch(srw_pdu->u.request->query_type)
+        if (!version2)
+            value[i++] = "searchRetrieve";
+        queryType = srw_pdu->u.request->queryType;
+        if (version2)
         {
-        case Z_SRW_query_type_cql:
+            yaz_add_name_value_str(encode, name, value, &i, "queryType",
+                                   queryType);
             yaz_add_name_value_str(encode, name, value, &i, "query",
-                                   srw_pdu->u.request->query.cql);
-            break;
-        case Z_SRW_query_type_pqf:
-            yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
-                                   srw_pdu->u.request->query.pqf);
-            break;
-        case Z_SRW_query_type_xcql:
-            yaz_add_name_value_str(encode, name, value, &i, "x-cql",
-                                   srw_pdu->u.request->query.xcql);
-            break;
+                                   srw_pdu->u.request->query);
         }
-        switch(srw_pdu->u.request->sort_type)
+        else
+        {
+            if (!strcmp(queryType, "cql"))
+            {
+                yaz_add_name_value_str(encode, name, value, &i, "query",
+                                       srw_pdu->u.request->query);
+            }
+            else if (!strcmp(queryType, "pqf"))
+            {
+                yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
+                                       srw_pdu->u.request->query);
+            }
+            else if (!strcmp(queryType, "xcql"))
+            {
+                yaz_add_name_value_str(encode, name, value, &i, "x-cql",
+                                       srw_pdu->u.request->query);
+            }
+        }
+        switch (srw_pdu->u.request->sort_type)
         {
         case Z_SRW_sort_type_none:
             break;
@@ -905,8 +932,16 @@ static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
                                srw_pdu->u.request->maximumRecords);
         yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
                                srw_pdu->u.request->recordSchema);
-        yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
-                               srw_pdu->u.request->recordPacking);
+        if (version2)
+        {
+            yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
+                                   srw_pdu->u.request->recordPacking);
+            yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
+                                   srw_pdu->u.request->packing);
+        }
+        else
+            yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
+                                   srw_pdu->u.request->recordPacking);
         yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
                                srw_pdu->u.request->recordXPath);
         yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
@@ -916,26 +951,43 @@ static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
         break;
     case Z_SRW_explain_request:
         value[i++] = "explain";
+
+        if (version2)
+        {
+            yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
+                                   srw_pdu->u.explain_request->recordPacking);
+            yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
+                                   srw_pdu->u.explain_request->packing);
+        }
+        else
+            yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
+                                   srw_pdu->u.explain_request->recordPacking);
         yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
                                srw_pdu->u.explain_request->stylesheet);
         break;
     case Z_SRW_scan_request:
         value[i++] = "scan";
-
-        switch(srw_pdu->u.scan_request->query_type)
+        queryType = srw_pdu->u.request->queryType;
+        if (version2)
         {
-        case Z_SRW_query_type_cql:
-            yaz_add_name_value_str(encode, name, value, &i, "scanClause",
-                                   srw_pdu->u.scan_request->scanClause.cql);
-            break;
-        case Z_SRW_query_type_pqf:
-            yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
-                                   srw_pdu->u.scan_request->scanClause.pqf);
-            break;
-        case Z_SRW_query_type_xcql:
-            yaz_add_name_value_str(encode, name, value, &i, "x-cqlScanClause",
-                                   srw_pdu->u.scan_request->scanClause.xcql);
-            break;
+            if (queryType && strcmp(queryType, "cql"))
+                yaz_add_name_value_str(encode, name, value, &i, "queryType",
+                                       queryType);
+            yaz_add_name_value_str(encode, name, value, &i, "query",
+                                   srw_pdu->u.request->query);
+        }
+        else
+        {
+            if (!queryType || !strcmp(queryType, "cql"))
+                yaz_add_name_value_str(encode, name, value, &i, "scanClause",
+                                       srw_pdu->u.scan_request->scanClause);
+            else if (!strcmp(queryType, "pqf"))
+                yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
+                                       srw_pdu->u.scan_request->scanClause);
+            else if (!strcmp(queryType, "xcql"))
+                yaz_add_name_value_str(encode, name, value, &i,
+                                       "x-cqlScanClause",
+                                       srw_pdu->u.scan_request->scanClause);
         }
         yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
                                srw_pdu->u.scan_request->responsePosition);