998deb91cf950933da1513da8691a235a058503b
[yaz-moved-to-github.git] / src / srwutil.c
1 /*
2  * Copyright (c) 2002-2003, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Id: srwutil.c,v 1.2 2003-12-30 00:29:53 adam Exp $
6  */
7
8 #include <yaz/srw.h>
9 #include <yaz/yaz-iconv.h>
10
11 static int hex_digit (int ch)
12 {
13     if (ch >= '0' && ch <= '9')
14         return ch - '0';
15     else if (ch >= 'a' && ch <= 'f')
16         return ch - 'a'+10;
17     else if (ch >= 'A' && ch <= 'F')
18         return ch - 'A'+10;
19     return 0;
20 }
21
22 char *yaz_uri_val(const char *path, const char *name, ODR o)
23 {
24     size_t nlen = strlen(name);
25     if (*path != '?')
26         return 0;
27     path++;
28     while (path && *path)
29     {
30         const char *p1 = strchr(path, '=');
31         if (!p1)
32             break;
33         if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
34         {
35             size_t i = 0;
36             char *ret;
37             
38             path = p1 + 1;
39             p1 = strchr(path, '&');
40             if (!p1)
41                 p1 = strlen(path) + path;
42             ret = odr_malloc(o, p1 - path + 1);
43             while (*path && *path != '&')
44             {
45                 if (*path == '+')
46                 {
47                     ret[i++] = ' ';
48                     path++;
49                 }
50                 else if (*path == '%' && path[1] && path[2])
51                 {
52                     ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
53                     path = path + 3;
54                 }
55                 else
56                     ret[i++] = *path++;
57             }
58             ret[i] = '\0';
59             return ret;
60         }
61         path = strchr(p1, '&');
62         if (path)
63             path++;
64     }
65     return 0;
66 }
67
68 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
69 {
70     const char *v = yaz_uri_val(path, name, o);
71     if (v)
72         *intp = odr_intdup(o, atoi(v));
73 }
74
75 int yaz_check_for_srw(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
76                       char **soap_ns, ODR decode)
77 {
78     if (!strcmp(hreq->method, "POST"))
79     {
80         const char *content_type = z_HTTP_header_lookup(hreq->headers,
81                                                         "Content-Type");
82         if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
83         {
84             char *db = "Default";
85             const char *p0 = hreq->path, *p1;
86             Z_SOAP *soap_package = 0;
87             int ret = -1;
88             const char *charset_p = 0;
89             char *charset = 0;
90             
91             static Z_SOAP_Handler soap_handlers[2] = {
92 #if HAVE_XML2
93                 {"http://www.loc.gov/zing/srw/", 0,
94                  (Z_SOAP_fun) yaz_srw_codec},
95 #endif
96                 {0, 0, 0}
97             };
98             
99             if (*p0 == '/')
100                 p0++;
101             p1 = strchr(p0, '?');
102             if (!p1)
103                 p1 = p0 + strlen(p0);
104             if (p1 != p0)
105             {
106                 db = (char*) odr_malloc(decode, p1 - p0 + 1);
107                 memcpy (db, p0, p1 - p0);
108                 db[p1 - p0] = '\0';
109             }
110
111             if ((charset_p = strstr(content_type, "; charset=")))
112             {
113                 int i = 0;
114                 charset_p += 10;
115                 while (i < 20 && charset_p[i] &&
116                        !strchr("; \n\r", charset_p[i]))
117                     i++;
118                 charset = (char*) odr_malloc(decode, i+1);
119                 memcpy(charset, charset_p, i);
120                 charset[i] = '\0';
121             }
122             ret = z_soap_codec(decode, &soap_package, 
123                                &hreq->content_buf, &hreq->content_len,
124                                soap_handlers);
125             if (!ret && soap_package->which == Z_SOAP_generic &&
126                 soap_package->u.generic->no == 0)
127             {
128                 *srw_pdu = (Z_SRW_PDU*) soap_package->u.generic->p;
129                 
130                 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
131                     (*srw_pdu)->u.request->database == 0)
132                     (*srw_pdu)->u.request->database = db;
133
134                 if ((*srw_pdu)->which == Z_SRW_explain_request &&
135                     (*srw_pdu)->u.explain_request->database == 0)
136                     (*srw_pdu)->u.explain_request->database = db;
137
138                 *soap_ns = odr_strdup(decode, soap_package->ns);
139                 return 0;
140             }
141             return 1;
142         }
143     }
144     return 2;
145 }
146
147 int yaz_check_for_sru(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
148                       char **soap_ns, ODR decode)
149 {
150     if (!strcmp(hreq->method, "GET"))
151     {
152         char *db = "Default";
153         const char *p0 = hreq->path, *p1;
154         const char *operation = 0;
155         
156         if (*p0 == '/')
157             p0++;
158         p1 = strchr(p0, '?');
159         if (!p1)
160             p1 = p0 + strlen(p0);
161         if (p1 != p0)
162         {
163             db = (char*) odr_malloc(decode, p1 - p0 + 1);
164             memcpy (db, p0, p1 - p0);
165             db[p1 - p0] = '\0';
166         }
167 #if HAVE_XML2
168         if (p1)
169             operation = yaz_uri_val(p1, "operation", decode);
170         if (!operation)
171             operation = "explain";
172         if (p1 && !strcmp(operation, "searchRetrieve"))
173         {
174             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
175             char *query = yaz_uri_val(p1, "query", decode);
176             char *pQuery = yaz_uri_val(p1, "pQuery", decode);
177             char *sortKeys = yaz_uri_val(p1, "sortKeys", decode);
178             
179             *srw_pdu = sr;
180             if (query)
181             {
182                 sr->u.request->query_type = Z_SRW_query_type_cql;
183                 sr->u.request->query.cql = query;
184             }
185             if (pQuery)
186             {
187                 sr->u.request->query_type = Z_SRW_query_type_pqf;
188                 sr->u.request->query.pqf = pQuery;
189             }
190             if (sortKeys)
191             {
192                 sr->u.request->sort_type = Z_SRW_sort_type_sort;
193                 sr->u.request->sort.sortKeys = sortKeys;
194             }
195             sr->u.request->recordSchema = yaz_uri_val(p1, "recordSchema", decode);
196             sr->u.request->recordPacking = yaz_uri_val(p1, "recordPacking", decode);
197             if (!sr->u.request->recordPacking)
198                 sr->u.request->recordPacking = "xml";
199             yaz_uri_val_int(p1, "maximumRecords", decode, 
200                         &sr->u.request->maximumRecords);
201             yaz_uri_val_int(p1, "startRecord", decode,
202                         &sr->u.request->startRecord);
203
204             sr->u.request->database = db;
205             *soap_ns = "SRU";
206             return 0;
207         }
208         else if (p1 && !strcmp(operation, "explain"))
209         {
210             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
211
212             *srw_pdu = sr;
213             sr->u.explain_request->recordPacking =
214                 yaz_uri_val(p1, "recordPacking", decode);
215             if (!sr->u.explain_request->recordPacking)
216                 sr->u.explain_request->recordPacking = "xml";
217             sr->u.explain_request->database = db;
218             *soap_ns = "SRU";
219             return 0;
220         }
221 #endif
222         return 1;
223     }
224     return 2;
225 }