1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file srwutil.c
7  * \brief Implements SRW/SRU utilities.
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <yaz/srw.h>
16 #include <yaz/matchstr.h>
17 #include <yaz/base64.h>
18 #include <yaz/yaz-iconv.h>
19 #include "sru-p.h"
20 
21 #define MAX_SRU_PARAMETERS 30
22 
append_extra_arg(ODR odr,Z_SRW_extra_arg ** l,const char * n,const char * v)23 static Z_SRW_extra_arg **append_extra_arg(ODR odr, Z_SRW_extra_arg **l,
24                                           const char *n, const char *v)
25 {
26     if (n && v && *v != '\0')
27     {
28         while (*l)
29             l = &(*l)->next;
30         *l = (Z_SRW_extra_arg *) odr_malloc(odr, sizeof(**l));
31         (*l)->name = odr_strdup(odr, n);
32         (*l)->value = odr_strdup(odr, v);
33         (*l)->next = 0;
34         l = &(*l)->next;
35     }
36     return l;
37 }
38 
append_extra_arg_int(ODR odr,Z_SRW_extra_arg ** l,const char * n,Odr_int * v)39 static Z_SRW_extra_arg **append_extra_arg_int(ODR odr, Z_SRW_extra_arg **l,
40                                               const char *n, Odr_int *v)
41 {
42     if (v)
43     {
44         char str[32];
45         sprintf(str, ODR_INT_PRINTF, *v);
46         l = append_extra_arg(odr, l, n, str);
47     }
48     return l;
49 }
50 
yaz_decode_sru_dbpath_odr(ODR n,const char * uri,size_t len)51 static char *yaz_decode_sru_dbpath_odr(ODR n, const char *uri, size_t len)
52 {
53     return odr_strdupn(n, uri, len);
54 }
55 
yaz_encode_sru_dbpath_buf(char * dst,const char * db)56 void yaz_encode_sru_dbpath_buf(char *dst, const char *db)
57 {
58     assert(db);
59     *dst = '/';
60     strcpy(dst+1, db);
61 }
62 
yaz_encode_sru_dbpath_odr(ODR out,const char * db)63 char *yaz_encode_sru_dbpath_odr(ODR out, const char *db)
64 {
65     char *dst = odr_malloc(out, 3 * strlen(db) + 2);
66     yaz_encode_sru_dbpath_buf(dst, db);
67     return dst;
68 }
69 
70 #if YAZ_HAVE_XML2
yaz_element_attribute_value_get(xmlNodePtr ptr,const char * node_name,const char * attribute_name)71 const char *yaz_element_attribute_value_get(xmlNodePtr ptr,
72                                             const char *node_name,
73                                             const char *attribute_name)
74 {
75     struct _xmlAttr *attr;
76     // check if the node name matches
77     if (strcmp((const char*) ptr->name, node_name))
78         return 0;
79     // check if the attribute name and return the value
80     for (attr = ptr->properties; attr; attr = attr->next)
81         if (attr->children && attr->children->type == XML_TEXT_NODE)
82         {
83             if (!strcmp((const char *) attr->name, attribute_name))
84                 return (const char *) attr->children->content;
85         }
86     return 0;
87 }
88 #endif
89 
yaz_srw_check_content_type(Z_HTTP_Response * hres)90 int yaz_srw_check_content_type(Z_HTTP_Response *hres)
91 {
92     const char *content_type = z_HTTP_header_lookup(hres->headers,
93                                                     "Content-Type");
94     if (content_type)
95     {
96         if (!yaz_strcmp_del("text/xml", content_type, "; "))
97             return 1;
98         if (!yaz_strcmp_del("application/xml", content_type, "; "))
99             return 1;
100         if (!yaz_strcmp_del("application/sru+xml", content_type, "; "))
101             return 1;
102     }
103     return 0;
104 }
105 
106 /**
107  * Look for authentication tokens in HTTP Basic parameters or in x-username/x-password
108  * parameters. Added by SH.
109  */
yaz_srw_decodeauth(Z_SRW_PDU * sr,Z_HTTP_Request * hreq,char * username,char * password,ODR decode)110 static void yaz_srw_decodeauth(Z_SRW_PDU *sr, Z_HTTP_Request *hreq,
111                                char *username, char *password, ODR decode)
112 {
113     const char *basic = z_HTTP_header_lookup(hreq->headers, "Authorization");
114 
115     if (username)
116         sr->username = username;
117     if (password)
118         sr->password = password;
119 
120     if (basic)
121     {
122         int len;
123         char out[256];
124         char ubuf[256] = "", pbuf[256] = "", *p;
125         if (strncmp(basic, "Basic ", 6))
126             return;
127         basic += 6;
128         len = strlen(basic);
129         if (!len || len > 256)
130             return;
131         yaz_base64decode(basic, out);
132         /* Format of out should be username:password at this point */
133         strcpy(ubuf, out);
134         if ((p = strchr(ubuf, ':')))
135         {
136             *(p++) = '\0';
137             if (*p)
138                 strcpy(pbuf, p);
139         }
140         if (*ubuf)
141             sr->username = odr_strdup(decode, ubuf);
142         if (*pbuf)
143             sr->password = odr_strdup(decode, pbuf);
144     }
145 }
146 
yaz_mk_srw_diagnostic(ODR o,Z_SRW_diagnostic * d,const char * uri,const char * message,const char * details)147 void yaz_mk_srw_diagnostic(ODR o, Z_SRW_diagnostic *d,
148                            const char *uri, const char *message,
149                            const char *details)
150 {
151     d->uri = odr_strdup(o, uri);
152     if (message)
153         d->message = odr_strdup(o, message);
154     else
155         d->message = 0;
156     if (details)
157         d->details = odr_strdup(o, details);
158     else
159         d->details = 0;
160 }
161 
yaz_mk_std_diagnostic(ODR o,Z_SRW_diagnostic * d,int code,const char * details)162 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d,
163                            int code, const char *details)
164 {
165     char uri[40];
166 
167     sprintf(uri, "info:srw/diagnostic/1/%d", code);
168     yaz_mk_srw_diagnostic(o, d, uri, 0, details);
169 }
170 
yaz_add_srw_diagnostic_uri(ODR o,Z_SRW_diagnostic ** d,int * num,const char * uri,const char * message,const char * details)171 void yaz_add_srw_diagnostic_uri(ODR o, Z_SRW_diagnostic **d,
172                                 int *num, const char *uri,
173                                 const char *message, const char *details)
174 {
175     Z_SRW_diagnostic *d_new;
176     d_new = (Z_SRW_diagnostic *) odr_malloc(o, (*num + 1)* sizeof(**d));
177     if (*num)
178         memcpy(d_new, *d, *num *sizeof(**d));
179     *d = d_new;
180 
181     yaz_mk_srw_diagnostic(o, *d + *num, uri, message, details);
182     (*num)++;
183 }
184 
yaz_add_srw_diagnostic(ODR o,Z_SRW_diagnostic ** d,int * num,int code,const char * addinfo)185 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
186                             int *num, int code, const char *addinfo)
187 {
188     char uri[40];
189 
190     sprintf(uri, "info:srw/diagnostic/1/%d", code);
191     yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
192 }
193 
194 
yaz_add_sru_update_diagnostic(ODR o,Z_SRW_diagnostic ** d,int * num,int code,const char * addinfo)195 void yaz_add_sru_update_diagnostic(ODR o, Z_SRW_diagnostic **d,
196                                    int *num, int code, const char *addinfo)
197 {
198     char uri[40];
199 
200     sprintf(uri, "info:srw/diagnostic/12/%d", code);
201     yaz_add_srw_diagnostic_uri(o, d, num, uri, 0, addinfo);
202 }
203 
204 
yaz_mk_sru_surrogate(ODR o,Z_SRW_record * record,int pos,int code,const char * details)205 void yaz_mk_sru_surrogate(ODR o, Z_SRW_record *record, int pos,
206                           int code, const char *details)
207 {
208     const char *message = yaz_diag_srw_str(code);
209     int len = 200;
210     if (message)
211         len += strlen(message);
212     if (details)
213         len += strlen(details);
214 
215     record->recordData_buf = (char *) odr_malloc(o, len);
216 
217     sprintf(record->recordData_buf, "<diagnostic "
218             "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
219             " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
220     if (details)
221         sprintf(record->recordData_buf + strlen(record->recordData_buf),
222                 " <details>%s</details>\n", details);
223     if (message)
224         sprintf(record->recordData_buf + strlen(record->recordData_buf),
225                 " <message>%s</message>\n", message);
226     sprintf(record->recordData_buf + strlen(record->recordData_buf),
227             "</diagnostic>\n");
228     record->recordData_len = strlen(record->recordData_buf);
229     record->recordPosition = odr_intdup(o, pos);
230     record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
231 }
232 
grab_charset(ODR o,const char * content_type,char ** charset)233 static void grab_charset(ODR o, const char *content_type, char **charset)
234 {
235     if (charset)
236     {
237         const char *charset_p = 0;
238         if (content_type && (charset_p = strstr(content_type, "; charset=")))
239         {
240             int j = 0, i = 0;
241             int sep = 0;
242             charset_p += 10; /* skip ; charset=  */
243             if (charset_p[i] == '"' || charset_p[i] == '\'')
244                 sep = charset_p[i++];
245             *charset = odr_strdup(o, charset_p);
246             while (charset_p[i] && charset_p[i] != sep)
247             {
248                 if (!sep && strchr("; \n\r", charset_p[i]))
249                     break;
250                 if (charset_p[i] == '\\' && charset_p[i+1])
251                     i++;
252                 (*charset)[j++] = charset_p[i++];
253             }
254             (*charset)[j] = '\0';
255         }
256     }
257 }
258 
yaz_srw_decode(Z_HTTP_Request * hreq,Z_SRW_PDU ** srw_pdu,Z_SOAP ** soap_package,ODR decode,char ** charset)259 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
260                    Z_SOAP **soap_package, ODR decode, char **charset)
261 {
262     if (!strcmp(hreq->method, "POST"))
263     {
264         const char *content_type = z_HTTP_header_lookup(hreq->headers,
265                                                         "Content-Type");
266         if (content_type &&
267             (!yaz_strcmp_del("text/xml", content_type, "; ") ||
268              !yaz_strcmp_del("application/soap+xml", content_type, "; ") ||
269              !yaz_strcmp_del("text/plain", content_type, "; ")))
270         {
271             char *db = "Default";
272             const char *p0 = hreq->path, *p1;
273             int ret = -1;
274 
275             static Z_SOAP_Handler soap_handlers[5] = {
276 #if YAZ_HAVE_XML2
277                 { YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec },
278                 { YAZ_XMLNS_SRU_v1_0, 0, (Z_SOAP_fun) yaz_srw_codec },
279                 { YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec },
280                 { YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec },
281 #endif
282                 {0, 0, 0}
283             };
284 
285             if (*p0 == '/')
286                 p0++;
287             p1 = strchr(p0, '?');
288             if (!p1)
289                 p1 = p0 + strlen(p0);
290             if (p1 != p0)
291                 db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
292 
293             ret = z_soap_codec(decode, soap_package,
294                                &hreq->content_buf, &hreq->content_len,
295                                soap_handlers);
296             if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
297             {
298                 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
299                 yaz_srw_decodeauth(*srw_pdu, hreq, 0, 0, decode);
300 
301                 /* last entry in handlers - SRU 2.0 - is turned into
302                    offset 0.. due to other pieces relying on it */
303                 if ((*soap_package)->u.generic->no == 3)
304                     (*soap_package)->u.generic->no = 0;
305                 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
306                     (*srw_pdu)->u.request->database == 0)
307                     (*srw_pdu)->u.request->database = db;
308 
309                 if ((*srw_pdu)->which == Z_SRW_explain_request &&
310                     (*srw_pdu)->u.explain_request->database == 0)
311                     (*srw_pdu)->u.explain_request->database = db;
312 
313                 if ((*srw_pdu)->which == Z_SRW_scan_request &&
314                     (*srw_pdu)->u.scan_request->database == 0)
315                     (*srw_pdu)->u.scan_request->database = db;
316 
317                 if ((*srw_pdu)->which == Z_SRW_update_request &&
318                     (*srw_pdu)->u.update_request->database == 0)
319                     (*srw_pdu)->u.update_request->database = db;
320 
321                 return 0;
322             }
323             return 1;
324         }
325     }
326     return 2;
327 }
328 
329 #if YAZ_HAVE_XML2
yaz_sru_decode_integer(ODR odr,const char * pname,const char * valstr,Odr_int ** valp,Z_SRW_diagnostic ** diag,int * num_diag,int min_value)330 static int yaz_sru_decode_integer(ODR odr, const char *pname,
331                                   const char *valstr, Odr_int **valp,
332                                   Z_SRW_diagnostic **diag, int *num_diag,
333                                   int min_value)
334 {
335     int ival;
336     if (!valstr)
337         return 0;
338     if (sscanf(valstr, "%d", &ival) != 1)
339     {
340         yaz_add_srw_diagnostic(odr, diag, num_diag,
341                                YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
342         return 0;
343     }
344     if (min_value >= 0 && ival < min_value)
345     {
346         yaz_add_srw_diagnostic(odr, diag, num_diag,
347                                YAZ_SRW_UNSUPP_PARAMETER_VALUE, pname);
348         return 0;
349     }
350     *valp = odr_intdup(odr, ival);
351     return 1;
352 }
353 #endif
354 
355 /**
356    http://www.loc.gov/standards/sru/companionSpecs/srw.html
357 */
yaz_sru_decode(Z_HTTP_Request * hreq,Z_SRW_PDU ** srw_pdu,Z_SOAP ** soap_package,ODR decode,char ** charset,Z_SRW_diagnostic ** diag,int * num_diag)358 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
359                    Z_SOAP **soap_package, ODR decode, char **charset,
360                    Z_SRW_diagnostic **diag, int *num_diag)
361 {
362 #if YAZ_HAVE_XML2
363     static Z_SOAP_Handler soap_handlers[2] = {
364         {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
365         {0, 0, 0}
366     };
367 #endif
368     const char *content_type = z_HTTP_header_lookup(hreq->headers,
369                                                     "Content-Type");
370 
371     /*
372       SRU GET: ignore content type.
373       SRU POST: we support "application/x-www-form-urlencoded";
374       not  "multipart/form-data" .
375     */
376     if (!strcmp(hreq->method, "GET")
377         ||
378         (!strcmp(hreq->method, "POST") && content_type &&
379          !yaz_strcmp_del("application/x-www-form-urlencoded",
380                          content_type, "; ")))
381     {
382         char *db = "Default";
383         const char *p0 = hreq->path, *p1;
384 #if YAZ_HAVE_XML2
385         const char *operation = 0;
386         char *version = 0;
387         char *query = 0;
388         char *queryType = "cql";
389         char *username = 0;
390         char *password = 0;
391         char *sortKeys = 0;
392         char *stylesheet = 0;
393         char *scanClause = 0;
394         char *recordXPath = 0;
395         char *recordSchema = 0;
396         char *recordXMLEscaping = 0;
397         char *recordPacking = 0;
398         char *maximumRecords = 0;
399         char *startRecord = 0;
400         char *maximumTerms = 0;
401         char *responsePosition = 0;
402         const char *facetLimit = 0;
403         const char *facetStart = 0;
404         const char *facetSort = 0;
405         Z_SRW_extra_arg *extra_args = 0;
406 #endif
407         char **uri_name;
408         char **uri_val;
409 
410         grab_charset(decode, content_type, charset);
411         if (charset && *charset == 0 && !strcmp(hreq->method, "GET"))
412             *charset = "UTF-8";
413 
414         if (*p0 == '/')
415             p0++;
416         p1 = strchr(p0, '?');
417         if (!p1)
418             p1 = p0 + strlen(p0);
419         if (p1 != p0)
420             db = yaz_decode_sru_dbpath_odr(decode, p0, p1 - p0);
421         if (!strcmp(hreq->method, "POST") && hreq->content_buf)
422             p1 = hreq->content_buf;
423         yaz_uri_to_array(p1, decode, &uri_name, &uri_val);
424 #if YAZ_HAVE_XML2
425         if (uri_name)
426         {
427             int i;
428             for (i = 0; uri_name[i]; i++)
429             {
430                 char *n = uri_name[i];
431                 char *v = uri_val[i];
432                 if (!strcmp(n, "query"))
433                     query = v;
434                 else if (!strcmp(n, "x-pquery"))
435                 {
436                     query = v;
437                     queryType = "pqf";
438                 }
439                 else if (!strcmp(n, "queryType"))
440                     queryType = v;
441                 else if (!strcmp(n, "x-username"))
442                     username = v;
443                 else if (!strcmp(n, "x-password"))
444                     password = v;
445                 else if (!strcmp(n, "operation"))
446                     operation = v;
447                 else if (!strcmp(n, "stylesheet"))
448                     stylesheet = v;
449                 else if (!strcmp(n, "sortKeys"))
450                     sortKeys = v;
451                 else if (!strcmp(n, "recordXPath"))
452                     recordXPath = v;
453                 else if (!strcmp(n, "recordSchema"))
454                     recordSchema = v;
455                 else if (!strcmp(n, "recordPacking"))
456                     recordPacking = v;
457                 else if (!strcmp(n, "recordXMLEscaping"))
458                     recordXMLEscaping = v;
459                 else if (!strcmp(n, "version"))
460                     version = v;
461                 else if (!strcmp(n, "scanClause"))
462                     scanClause = v;
463                 else if (!strcmp(n, "x-pScanClause"))
464                 {
465                     scanClause = v;
466                     queryType = "pqf";
467                 }
468                 else if (!strcmp(n, "maximumRecords"))
469                     maximumRecords = v;
470                 else if (!strcmp(n, "startRecord"))
471                     startRecord = v;
472                 else if (!strcmp(n, "maximumTerms"))
473                     maximumTerms = v;
474                 else if (!strcmp(n, "responsePosition"))
475                     responsePosition = v;
476                 else if (!strcmp(n, "facetLimit"))
477                     facetLimit = v;
478                 else if (!strcmp(n, "facetStart"))
479                     facetStart = v;
480                 else if (!strcmp(n, "facetSort"))
481                     facetSort = v;
482                 else if (!strcmp(n, "extraRequestData"))
483                     ; /* ignoring extraRequestData */
484                 else if (n[0] == 'x' && n[1] == '-')
485                 {
486                     append_extra_arg(decode, &extra_args, n, v);
487                 }
488                 else
489                 {
490                     if (*num_diag < 10)
491                         yaz_add_srw_diagnostic(decode, diag, num_diag,
492                                                YAZ_SRW_UNSUPP_PARAMETER, n);
493                 }
494             }
495         }
496         if (!operation)
497         {
498             if (query)
499                 operation = "searchRetrieve";
500             else if (scanClause)
501                 operation = "scan";
502             else
503                 operation = "explain";
504         }
505         version = yaz_negotiate_sru_version(version);
506 
507         if (!version)
508         {   /* negotiation failed. */
509             yaz_add_srw_diagnostic(decode, diag, num_diag,
510                                    YAZ_SRW_UNSUPP_VERSION, "2.0");
511             version = "2.0";
512         }
513         if (!operation)
514         {
515             if (uri_name)
516                 yaz_add_srw_diagnostic(
517                     decode, diag, num_diag,
518                     YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "operation");
519             operation = "explain";
520         }
521         if (strcmp(version, "2.0"))
522         {
523             if (recordXMLEscaping)
524             {
525                 yaz_add_srw_diagnostic(decode, diag, num_diag,
526                                        YAZ_SRW_UNSUPP_PARAMETER,
527                                        "recordXMLEscaping");
528 
529             }
530             recordXMLEscaping = recordPacking;
531             recordPacking = "packed";
532         }
533         if (!recordXMLEscaping)
534             recordXMLEscaping = "xml";
535         if (!strcmp(operation, "searchRetrieve"))
536         {
537             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
538 
539             sr->srw_version = version;
540             sr->extra_args = extra_args;
541             *srw_pdu = sr;
542             yaz_srw_decodeauth(sr, hreq, username, password, decode);
543 
544             sr->u.request->queryType = queryType;
545             sr->u.request->query = query;
546 
547             if (!query)
548                 yaz_add_srw_diagnostic(
549                     decode, diag, num_diag,
550                     YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "query");
551 
552             if (sortKeys)
553             {
554                 sr->u.request->sort_type = Z_SRW_sort_type_sort;
555                 sr->u.request->sort.sortKeys = sortKeys;
556             }
557             sr->u.request->recordXPath = recordXPath;
558             sr->u.request->recordSchema = recordSchema;
559             sr->u.request->recordPacking = recordXMLEscaping;
560             sr->u.request->packing = recordPacking;
561             sr->u.request->stylesheet = stylesheet;
562             yaz_sru_facet_request(decode , &sr->u.request->facetList,
563                                   &facetLimit, &facetStart, &facetSort);
564 
565             yaz_sru_decode_integer(decode, "maximumRecords", maximumRecords,
566                                    &sr->u.request->maximumRecords,
567                                    diag, num_diag, 0);
568 
569             yaz_sru_decode_integer(decode, "startRecord", startRecord,
570                                    &sr->u.request->startRecord,
571                                    diag, num_diag, 1);
572 
573             sr->u.request->database = db;
574 
575             (*soap_package) = (Z_SOAP *)
576                 odr_malloc(decode, sizeof(**soap_package));
577             (*soap_package)->which = Z_SOAP_generic;
578 
579             (*soap_package)->u.generic = (Z_SOAP_Generic *)
580                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
581 
582             (*soap_package)->u.generic->p = sr;
583             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
584             (*soap_package)->u.generic->no = 0;
585 
586             (*soap_package)->ns = "SRU";
587 
588             return 0;
589         }
590         else if (!strcmp(operation, "explain"))
591         {
592             /* Transfer SRU explain parameters to common struct */
593             /* http://www.loc.gov/standards/sru/explain/ */
594             /* http://zeerex.z3950.org/overview/ */
595             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
596 
597             sr->srw_version = version;
598             sr->extra_args = extra_args;
599             yaz_srw_decodeauth(sr, hreq, username, password, decode);
600             *srw_pdu = sr;
601             sr->u.explain_request->recordPacking = recordXMLEscaping;
602             sr->u.explain_request->packing = recordPacking;
603             sr->u.explain_request->database = db;
604 
605             sr->u.explain_request->stylesheet = stylesheet;
606 
607             (*soap_package) = (Z_SOAP *)
608                 odr_malloc(decode, sizeof(**soap_package));
609             (*soap_package)->which = Z_SOAP_generic;
610 
611             (*soap_package)->u.generic = (Z_SOAP_Generic *)
612                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
613 
614             (*soap_package)->u.generic->p = sr;
615             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
616             (*soap_package)->u.generic->no = 0;
617 
618             (*soap_package)->ns = "SRU";
619 
620             return 0;
621         }
622         else if (!strcmp(operation, "scan"))
623         {
624             /* Transfer SRU scan parameters to common struct */
625             /* http://www.loc.gov/standards/sru/companionSpecs/scan.html */
626             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
627 
628             sr->srw_version = version;
629             sr->extra_args = extra_args;
630             *srw_pdu = sr;
631             yaz_srw_decodeauth(sr, hreq, username, password, decode);
632 
633             sr->u.scan_request->queryType = queryType;
634             sr->u.scan_request->scanClause = scanClause;
635 
636             if (!scanClause)
637                 yaz_add_srw_diagnostic(
638                     decode, diag, num_diag,
639                     YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED, "scanClause");
640             sr->u.scan_request->database = db;
641 
642             yaz_sru_decode_integer(decode, "maximumTerms",
643                                    maximumTerms,
644                                    &sr->u.scan_request->maximumTerms,
645                                    diag, num_diag, 0);
646 
647             yaz_sru_decode_integer(decode, "responsePosition",
648                                    responsePosition,
649                                    &sr->u.scan_request->responsePosition,
650                                    diag, num_diag, 0);
651 
652             sr->u.scan_request->stylesheet = stylesheet;
653 
654             (*soap_package) = (Z_SOAP *)
655                 odr_malloc(decode, sizeof(**soap_package));
656             (*soap_package)->which = Z_SOAP_generic;
657 
658             (*soap_package)->u.generic = (Z_SOAP_Generic *)
659                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
660 
661             (*soap_package)->u.generic->p = sr;
662             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
663             (*soap_package)->u.generic->no = 0;
664 
665             (*soap_package)->ns = "SRU";
666 
667             return 0;
668         }
669         else
670         {
671             /* unsupported operation ... */
672             /* Act as if we received a explain request and throw diagnostic. */
673 
674             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
675 
676             sr->srw_version = version;
677             *srw_pdu = sr;
678             sr->u.explain_request->recordPacking = recordPacking;
679             sr->u.explain_request->database = db;
680 
681             sr->u.explain_request->stylesheet = stylesheet;
682 
683             (*soap_package) = (Z_SOAP *)
684                 odr_malloc(decode, sizeof(**soap_package));
685             (*soap_package)->which = Z_SOAP_generic;
686 
687             (*soap_package)->u.generic = (Z_SOAP_Generic *)
688                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
689 
690             (*soap_package)->u.generic->p = sr;
691             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
692             (*soap_package)->u.generic->no = 0;
693 
694             (*soap_package)->ns = "SRU";
695 
696             yaz_add_srw_diagnostic(decode, diag, num_diag,
697                                    YAZ_SRW_UNSUPP_OPERATION, operation);
698             return 0;
699         }
700 #else
701         return 1;
702 #endif
703     }
704     return 2;
705 }
706 
yaz_srw_get_extra_record(ODR o)707 Z_SRW_extra_record *yaz_srw_get_extra_record(ODR o)
708 {
709     Z_SRW_extra_record *res = (Z_SRW_extra_record *)
710         odr_malloc(o, sizeof(*res));
711 
712     res->extraRecordData_buf = 0;
713     res->extraRecordData_len = 0;
714     res->recordIdentifier = 0;
715     return res;
716 }
717 
718 
yaz_srw_get_records(ODR o,int n)719 Z_SRW_record *yaz_srw_get_records(ODR o, int n)
720 {
721     Z_SRW_record *res = (Z_SRW_record *) odr_malloc(o, n * sizeof(*res));
722     int i;
723 
724     for (i = 0; i<n; i++)
725     {
726         res[i].recordSchema = 0;
727         res[i].recordPacking = Z_SRW_recordPacking_string;
728         res[i].recordData_buf = 0;
729         res[i].recordData_len = 0;
730         res[i].recordPosition = 0;
731     }
732     return res;
733 }
734 
yaz_srw_get_record(ODR o)735 Z_SRW_record *yaz_srw_get_record(ODR o)
736 {
737     return yaz_srw_get_records(o, 1);
738 }
739 
yaz_srw_get_core_ver(ODR o,const char * version)740 static Z_SRW_PDU *yaz_srw_get_core_ver(ODR o, const char *version)
741 {
742     Z_SRW_PDU *p = (Z_SRW_PDU *) odr_malloc(o, sizeof(*p));
743     p->srw_version = odr_strdup(o, version);
744     p->username = 0;
745     p->password = 0;
746     p->extra_args = 0;
747     p->extraResponseData_buf = 0;
748     p->extraResponseData_len = 0;
749     return p;
750 }
751 
yaz_srw_get_core_v_2_0(ODR o)752 Z_SRW_PDU *yaz_srw_get_core_v_2_0(ODR o)
753 {
754     return yaz_srw_get_core_ver(o, "2.0");
755 }
756 
yaz_srw_get(ODR o,int which)757 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
758 {
759     return yaz_srw_get_pdu(o, which, "2.0");
760 }
761 
762 /* http://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/schemas/sruResponse.xsd */
yaz_srw_get_pdu_e(ODR o,int which,Z_SRW_PDU * req)763 Z_SRW_PDU *yaz_srw_get_pdu_e(ODR o, int which, Z_SRW_PDU *req)
764 {
765     int version2 = !req->srw_version || strcmp(req->srw_version, "2.") > 0;
766     Z_SRW_PDU *res = yaz_srw_get_pdu(o, which, req->srw_version);
767     Z_SRW_extra_arg **l = &res->extra_args, *ea;
768     l = append_extra_arg(o, l, "version", req->srw_version);
769     if (req->which == Z_SRW_searchRetrieve_request &&
770         which == Z_SRW_searchRetrieve_response)
771     {
772         if (req->u.request->queryType &&
773             strcmp(req->u.request->queryType, "cql"))
774             l = append_extra_arg(o, l, "queryType", req->u.request->queryType);
775         l = append_extra_arg(o, l, "query", req->u.request->query);
776         l = append_extra_arg_int(o, l, "startRecord",
777                                  req->u.request->startRecord);
778         l = append_extra_arg_int(o, l, "maximumRecords",
779                                  req->u.request->maximumRecords);
780         if (version2)
781         {
782             l = append_extra_arg(o, l, "recordXMLEscaping",
783                                  req->u.request->recordPacking);
784             l = append_extra_arg(o, l, "recordPacking",
785                                  req->u.request->packing);
786         }
787         else
788             l = append_extra_arg(o, l, "recordPacking",
789                                  req->u.request->recordPacking);
790         l = append_extra_arg(o, l, "recordSchema",
791                              req->u.request->recordSchema);
792         if (req->u.request->sort_type == Z_SRW_sort_type_sort)
793             l = append_extra_arg(o, l, "sortKeys",
794                                  req->u.request->sort.sortKeys);
795         l = append_extra_arg(o, l, "stylesheet", req->u.request->stylesheet);
796     }
797     if (req->which == Z_SRW_explain_request &&
798         which == Z_SRW_explain_response)
799     {
800         if (version2)
801         {
802             l = append_extra_arg(o, l, "recordXMLEscaping",
803                                  req->u.explain_request->recordPacking);
804             l = append_extra_arg(o, l, "recordPacking",
805                                  req->u.explain_request->packing);
806         }
807         else
808             l = append_extra_arg(o, l, "recordPacking",
809                                  req->u.explain_request->recordPacking);
810         l = append_extra_arg(o, l, "stylesheet",
811                              req->u.explain_request->stylesheet);
812     }
813     for (ea = req->extra_args; ea; ea = ea->next)
814         l = append_extra_arg(o, l, ea->name, ea->value);
815     return res;
816 }
817 
yaz_srw_get_pdu(ODR o,int which,const char * version)818 Z_SRW_PDU *yaz_srw_get_pdu(ODR o, int which, const char *version)
819 {
820     Z_SRW_PDU *sr = yaz_srw_get_core_ver(o, version);
821 
822     sr->which = which;
823     switch (which)
824     {
825     case Z_SRW_searchRetrieve_request:
826         sr->u.request = (Z_SRW_searchRetrieveRequest *)
827             odr_malloc(o, sizeof(*sr->u.request));
828         sr->u.request->queryType = "cql";
829         sr->u.request->query = 0;
830         sr->u.request->sort_type = Z_SRW_sort_type_none;
831         sr->u.request->sort.none = 0;
832         sr->u.request->startRecord = 0;
833         sr->u.request->maximumRecords = 0;
834         sr->u.request->recordSchema = 0;
835         sr->u.request->recordPacking = 0;
836         sr->u.request->packing = 0;
837         sr->u.request->recordXPath = 0;
838         sr->u.request->database = 0;
839         sr->u.request->resultSetTTL = 0;
840         sr->u.request->stylesheet = 0;
841         sr->u.request->facetList = 0;
842         break;
843     case Z_SRW_searchRetrieve_response:
844         sr->u.response = (Z_SRW_searchRetrieveResponse *)
845             odr_malloc(o, sizeof(*sr->u.response));
846         sr->u.response->numberOfRecords = 0;
847         sr->u.response->resultCountPrecision = 0;
848         sr->u.response->resultSetId = 0;
849         sr->u.response->resultSetIdleTime = 0;
850         sr->u.response->records = 0;
851         sr->u.response->num_records = 0;
852         sr->u.response->diagnostics = 0;
853         sr->u.response->num_diagnostics = 0;
854         sr->u.response->nextRecordPosition = 0;
855         sr->u.response->extra_records = 0;
856         sr->u.response->facetList = 0;
857         sr->u.response->suggestions = 0;
858         break;
859     case Z_SRW_explain_request:
860         sr->u.explain_request = (Z_SRW_explainRequest *)
861             odr_malloc(o, sizeof(*sr->u.explain_request));
862         sr->u.explain_request->recordPacking = 0;
863         sr->u.explain_request->packing = 0;
864         sr->u.explain_request->database = 0;
865         sr->u.explain_request->stylesheet = 0;
866         break;
867     case Z_SRW_explain_response:
868         sr->u.explain_response = (Z_SRW_explainResponse *)
869             odr_malloc(o, sizeof(*sr->u.explain_response));
870         sr->u.explain_response->record.recordData_buf = 0;
871         sr->u.explain_response->record.recordData_len = 0;
872         sr->u.explain_response->record.recordSchema = 0;
873         sr->u.explain_response->record.recordPosition = 0;
874         sr->u.explain_response->record.recordPacking =
875             Z_SRW_recordPacking_string;
876         sr->u.explain_response->diagnostics = 0;
877         sr->u.explain_response->num_diagnostics = 0;
878         sr->u.explain_response->extra_record = 0;
879         break;
880     case Z_SRW_scan_request:
881         sr->u.scan_request = (Z_SRW_scanRequest *)
882             odr_malloc(o, sizeof(*sr->u.scan_request));
883         sr->u.scan_request->database = 0;
884         sr->u.scan_request->stylesheet = 0;
885         sr->u.scan_request->maximumTerms = 0;
886         sr->u.scan_request->responsePosition = 0;
887         sr->u.scan_request->queryType = "cql";
888         sr->u.scan_request->scanClause = 0;
889         break;
890     case Z_SRW_scan_response:
891         sr->u.scan_response = (Z_SRW_scanResponse *)
892             odr_malloc(o, sizeof(*sr->u.scan_response));
893 	sr->u.scan_response->terms = 0;
894 	sr->u.scan_response->num_terms = 0;
895 	sr->u.scan_response->diagnostics = 0;
896 	sr->u.scan_response->num_diagnostics = 0;
897         break;
898     case Z_SRW_update_request:
899         sr->u.update_request = (Z_SRW_updateRequest *)
900             odr_malloc(o, sizeof(*sr->u.update_request));
901 	sr->u.update_request->database = 0;
902 	sr->u.update_request->stylesheet = 0;
903         sr->u.update_request->record = 0;
904 	sr->u.update_request->recordId = 0;
905 	sr->u.update_request->recordVersions = 0;
906 	sr->u.update_request->num_recordVersions = 0;
907         sr->u.update_request->extra_record = 0;
908         sr->u.update_request->extraRequestData_buf = 0;
909         sr->u.update_request->extraRequestData_len = 0;
910 	sr->u.request->database = 0;
911         break;
912     case Z_SRW_update_response:
913         sr->u.update_response = (Z_SRW_updateResponse *)
914             odr_malloc(o, sizeof(*sr->u.update_response));
915 	sr->u.update_response->operationStatus = 0;
916 	sr->u.update_response->recordId = 0;
917 	sr->u.update_response->recordVersions = 0;
918 	sr->u.update_response->num_recordVersions = 0;
919 	sr->u.update_response->record = 0;
920         sr->u.update_response->extra_record = 0;
921         sr->u.update_response->extraResponseData_buf = 0;
922         sr->u.update_response->extraResponseData_len = 0;
923 	sr->u.update_response->diagnostics = 0;
924 	sr->u.update_response->num_diagnostics = 0;
925     }
926     return sr;
927 }
928 
yaz_add_name_value_int(ODR o,char ** name,char ** value,int * i,char * a_name,Odr_int * val)929 void yaz_add_name_value_int(ODR o, char **name, char **value, int *i,
930                             char *a_name, Odr_int *val)
931 {
932     if (val)
933     {
934         name[*i] = a_name;
935         value[*i] = (char *) odr_malloc(o, 40);
936         sprintf(value[*i], ODR_INT_PRINTF, *val);
937         (*i)++;
938     }
939 }
940 
yaz_add_name_value_str(ODR o,char ** name,char ** value,int * i,char * a_name,char * val)941 void yaz_add_name_value_str(ODR o, char **name, char **value,  int *i,
942                             char *a_name, char *val)
943 {
944     if (val)
945     {
946         name[*i] = a_name;
947         value[*i] = val;
948         (*i)++;
949     }
950 }
951 
yaz_get_sru_parms(const Z_SRW_PDU * srw_pdu,ODR encode,char ** name,char ** value,int max_names)952 static int yaz_get_sru_parms(const Z_SRW_PDU *srw_pdu, ODR encode,
953                              char **name, char **value, int max_names)
954 {
955     int version2 = strcmp(srw_pdu->srw_version, "2.") > 0;
956     int i = 0;
957     char *queryType;
958     yaz_add_name_value_str(encode, name, value, &i, "version",
959                            srw_pdu->srw_version);
960     name[i] = "operation";
961     switch (srw_pdu->which)
962     {
963     case Z_SRW_searchRetrieve_request:
964         value[i++] = "searchRetrieve";
965         queryType = srw_pdu->u.request->queryType;
966         if (version2)
967         {
968             if (queryType && strcmp(queryType, "cql"))
969                 yaz_add_name_value_str(encode, name, value, &i, "queryType",
970                                        queryType);
971             yaz_add_name_value_str(encode, name, value, &i, "query",
972                                    srw_pdu->u.request->query);
973         }
974         else
975         {
976             if (!strcmp(queryType, "cql"))
977             {
978                 yaz_add_name_value_str(encode, name, value, &i, "query",
979                                        srw_pdu->u.request->query);
980             }
981             else if (!strcmp(queryType, "pqf"))
982             {
983                 yaz_add_name_value_str(encode, name, value, &i, "x-pquery",
984                                        srw_pdu->u.request->query);
985             }
986             else if (!strcmp(queryType, "xcql"))
987             {
988                 yaz_add_name_value_str(encode, name, value, &i, "x-cql",
989                                        srw_pdu->u.request->query);
990             }
991         }
992         switch (srw_pdu->u.request->sort_type)
993         {
994         case Z_SRW_sort_type_none:
995             break;
996         case Z_SRW_sort_type_sort:
997             yaz_add_name_value_str(encode, name, value, &i, "sortKeys",
998                                    srw_pdu->u.request->sort.sortKeys);
999             break;
1000         }
1001         yaz_add_name_value_int(encode, name, value, &i, "startRecord",
1002                                srw_pdu->u.request->startRecord);
1003         yaz_add_name_value_int(encode, name, value, &i, "maximumRecords",
1004                                srw_pdu->u.request->maximumRecords);
1005         yaz_add_name_value_str(encode, name, value, &i, "recordSchema",
1006                                srw_pdu->u.request->recordSchema);
1007         if (version2)
1008         {
1009             yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1010                                    srw_pdu->u.request->recordPacking);
1011             yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1012                                    srw_pdu->u.request->packing);
1013         }
1014         else
1015             yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1016                                    srw_pdu->u.request->recordPacking);
1017         yaz_add_name_value_str(encode, name, value, &i, "recordXPath",
1018                                srw_pdu->u.request->recordXPath);
1019         yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1020                                srw_pdu->u.request->stylesheet);
1021         yaz_add_name_value_int(encode, name, value, &i, "resultSetTTL",
1022                                srw_pdu->u.request->resultSetTTL);
1023         {
1024             const char *facetLimit = 0;
1025             const char *facetStart = 0;
1026             const char *facetSort = 0;
1027             yaz_sru_facet_request(encode, &srw_pdu->u.request->facetList,
1028                                   &facetLimit, &facetStart, &facetSort);
1029             yaz_add_name_value_str(encode, name, value, &i, "facetLimit",
1030                                    (char *) facetLimit);
1031             yaz_add_name_value_str(encode, name, value, &i, "facetStart",
1032                                    (char *) facetStart);
1033             yaz_add_name_value_str(encode, name, value, &i, "facetSort",
1034                                    (char *) facetSort);
1035         }
1036         break;
1037     case Z_SRW_explain_request:
1038         value[i++] = "explain";
1039 
1040         if (version2)
1041         {
1042             yaz_add_name_value_str(encode, name, value, &i, "recordXMLEscaping",
1043                                    srw_pdu->u.explain_request->recordPacking);
1044             yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1045                                    srw_pdu->u.explain_request->packing);
1046         }
1047         else
1048             yaz_add_name_value_str(encode, name, value, &i, "recordPacking",
1049                                    srw_pdu->u.explain_request->recordPacking);
1050         yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1051                                srw_pdu->u.explain_request->stylesheet);
1052         break;
1053     case Z_SRW_scan_request:
1054         value[i++] = "scan";
1055         queryType = srw_pdu->u.scan_request->queryType;
1056         if (version2)
1057         {
1058             if (queryType && strcmp(queryType, "cql"))
1059                 yaz_add_name_value_str(encode, name, value, &i, "queryType",
1060                                        queryType);
1061             yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1062                                    srw_pdu->u.scan_request->scanClause);
1063         }
1064         else
1065         {
1066             if (!queryType || !strcmp(queryType, "cql"))
1067                 yaz_add_name_value_str(encode, name, value, &i, "scanClause",
1068                                        srw_pdu->u.scan_request->scanClause);
1069             else if (!strcmp(queryType, "pqf"))
1070                 yaz_add_name_value_str(encode, name, value, &i, "x-pScanClause",
1071                                        srw_pdu->u.scan_request->scanClause);
1072             else if (!strcmp(queryType, "xcql"))
1073                 yaz_add_name_value_str(encode, name, value, &i,
1074                                        "x-cqlScanClause",
1075                                        srw_pdu->u.scan_request->scanClause);
1076         }
1077         yaz_add_name_value_int(encode, name, value, &i, "responsePosition",
1078                                srw_pdu->u.scan_request->responsePosition);
1079         yaz_add_name_value_int(encode, name, value, &i, "maximumTerms",
1080                                srw_pdu->u.scan_request->maximumTerms);
1081         yaz_add_name_value_str(encode, name, value, &i, "stylesheet",
1082                                srw_pdu->u.scan_request->stylesheet);
1083         break;
1084     case Z_SRW_update_request:
1085         value[i++] = "update";
1086         break;
1087     default:
1088         return -1;
1089     }
1090     if (srw_pdu->extra_args)
1091     {
1092         Z_SRW_extra_arg *ea = srw_pdu->extra_args;
1093         for (; ea && i < max_names-1; ea = ea->next)
1094         {
1095             name[i] = ea->name;
1096             value[i] = ea->value;
1097             i++;
1098         }
1099     }
1100     name[i++] = 0;
1101 
1102     return 0;
1103 }
1104 
yaz_sru_get_encode(Z_HTTP_Request * hreq,Z_SRW_PDU * srw_pdu,ODR encode,const char * charset)1105 int yaz_sru_get_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1106                        ODR encode, const char *charset)
1107 {
1108     char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1109     char *uri_args;
1110     char *path;
1111     char *cp;
1112 
1113     z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1114                                  srw_pdu->username, srw_pdu->password);
1115     if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1116         return -1;
1117     yaz_array_to_uri(&uri_args, encode, name, value);
1118 
1119     hreq->method = "GET";
1120 
1121     cp = strchr(hreq->path, '#');
1122     if (cp)
1123         *cp = '\0';
1124 
1125     path = (char *)
1126         odr_malloc(encode, strlen(hreq->path) + strlen(uri_args) + 4);
1127 
1128     sprintf(path, "%s%c%s", hreq->path, strchr(hreq->path, '?') ? '&' : '?',
1129             uri_args);
1130     hreq->path = path;
1131 
1132     z_HTTP_header_add_content_type(encode, &hreq->headers,
1133                                    "text/xml", charset);
1134     return 0;
1135 }
1136 
yaz_sru_post_encode(Z_HTTP_Request * hreq,Z_SRW_PDU * srw_pdu,ODR encode,const char * charset)1137 int yaz_sru_post_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1138                         ODR encode, const char *charset)
1139 {
1140     char *name[MAX_SRU_PARAMETERS], *value[MAX_SRU_PARAMETERS]; /* definite upper limit for SRU params */
1141     char *uri_args;
1142 
1143     z_HTTP_header_add_basic_auth(encode, &hreq->headers,
1144                                  srw_pdu->username, srw_pdu->password);
1145     if (yaz_get_sru_parms(srw_pdu, encode, name, value, MAX_SRU_PARAMETERS))
1146         return -1;
1147 
1148     yaz_array_to_uri(&uri_args, encode, name, value);
1149 
1150     hreq->method = "POST";
1151 
1152     hreq->content_buf = uri_args;
1153     hreq->content_len = strlen(uri_args);
1154 
1155     z_HTTP_header_add_content_type(encode, &hreq->headers,
1156                                    "application/x-www-form-urlencoded",
1157                                    charset);
1158     return 0;
1159 }
1160 
yaz_sru_soap_encode(Z_HTTP_Request * hreq,Z_SRW_PDU * srw_pdu,ODR odr,const char * charset)1161 int yaz_sru_soap_encode(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu,
1162                         ODR odr, const char *charset)
1163 {
1164     Z_SOAP_Handler handlers[3] = {
1165 #if YAZ_HAVE_XML2
1166         {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
1167         {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
1168 #endif
1169         {0, 0, 0}
1170     };
1171     Z_SOAP *p = (Z_SOAP*) odr_malloc(odr, sizeof(*p));
1172 
1173     z_HTTP_header_add_basic_auth(odr, &hreq->headers,
1174                                  srw_pdu->username, srw_pdu->password);
1175     z_HTTP_header_add_content_type(odr,
1176                                    &hreq->headers,
1177                                    "text/xml", 0 /* no charset in MIME */);
1178 
1179     z_HTTP_header_add(odr, &hreq->headers,
1180                       "SOAPAction", "\"\"");
1181     p->which = Z_SOAP_generic;
1182     p->u.generic = (Z_SOAP_Generic *) odr_malloc(odr, sizeof(*p->u.generic));
1183     p->u.generic->no = 0;
1184     p->u.generic->ns = 0;
1185     p->u.generic->p = srw_pdu;
1186     p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
1187 
1188 #if YAZ_HAVE_XML2
1189     if (srw_pdu->which == Z_SRW_update_request ||
1190         srw_pdu->which == Z_SRW_update_response)
1191         p->u.generic->no = 1; /* second handler */
1192 #endif
1193     return z_soap_codec_enc(odr, &p,
1194                             &hreq->content_buf,
1195                             &hreq->content_len, handlers,
1196                             charset);
1197 }
1198 
yaz_srw_get_record_versions(ODR odr,int num)1199 Z_SRW_recordVersion *yaz_srw_get_record_versions(ODR odr, int num)
1200 {
1201     Z_SRW_recordVersion *ver
1202         = (Z_SRW_recordVersion *) odr_malloc(odr,num * sizeof(*ver));
1203     int i;
1204     for (i = 0; i < num; ++i)
1205     {
1206         ver[i].versionType = 0;
1207         ver[i].versionValue = 0;
1208     }
1209     return ver;
1210 }
1211 
yaz_srw_pack_to_str(int pack)1212 const char *yaz_srw_pack_to_str(int pack)
1213 {
1214     switch(pack)
1215     {
1216     case Z_SRW_recordPacking_string:
1217         return "string";
1218     case Z_SRW_recordPacking_XML:
1219         return "xml";
1220     case Z_SRW_recordPacking_URL:
1221         return "url";
1222     }
1223     return 0;
1224 }
1225 
yaz_srw_str_to_pack(const char * str)1226 int yaz_srw_str_to_pack(const char *str)
1227 {
1228     if (!yaz_matchstr(str, "string"))
1229         return Z_SRW_recordPacking_string;
1230     if (!yaz_matchstr(str, "xml"))
1231         return Z_SRW_recordPacking_XML;
1232     if (!yaz_matchstr(str, "url"))
1233         return Z_SRW_recordPacking_URL;
1234     return -1;
1235 }
1236 
yaz_encode_sru_extra(Z_SRW_PDU * sr,ODR odr,const char * extra_args)1237 void yaz_encode_sru_extra(Z_SRW_PDU *sr, ODR odr, const char *extra_args)
1238 {
1239     if (extra_args)
1240     {
1241         char **name;
1242         char **val;
1243         Z_SRW_extra_arg **ea = &sr->extra_args;
1244         yaz_uri_to_array(extra_args, odr, &name, &val);
1245 
1246         while (*name)
1247         {
1248             ea = append_extra_arg(odr, ea, *name, *val);
1249             val++;
1250             name++;
1251         }
1252     }
1253 }
1254 
1255 
1256 /*
1257  * Local variables:
1258  * c-basic-offset: 4
1259  * c-file-style: "Stroustrup"
1260  * indent-tabs-mode: nil
1261  * End:
1262  * vim: shiftwidth=4 tabstop=8 expandtab
1263  */
1264 
1265