SRW/SRU 1.1
[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.1 2003-12-20 00:51:19 adam Exp $
6  */
7
8 #include <yaz/srw.h>
9
10 static int hex_digit (int ch)
11 {
12     if (ch >= '0' && ch <= '9')
13         return ch - '0';
14     else if (ch >= 'a' && ch <= 'f')
15         return ch - 'a'+10;
16     else if (ch >= 'A' && ch <= 'F')
17         return ch - 'A'+10;
18     return 0;
19 }
20
21 char *yaz_uri_val(const char *path, const char *name, ODR o)
22 {
23     size_t nlen = strlen(name);
24     if (*path != '?')
25         return 0;
26     path++;
27     while (path && *path)
28     {
29         const char *p1 = strchr(path, '=');
30         if (!p1)
31             break;
32         if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
33         {
34             size_t i = 0;
35             char *ret;
36             
37             path = p1 + 1;
38             p1 = strchr(path, '&');
39             if (!p1)
40                 p1 = strlen(path) + path;
41             ret = odr_malloc(o, p1 - path + 1);
42             while (*path && *path != '&')
43             {
44                 if (*path == '+')
45                 {
46                     ret[i++] = ' ';
47                     path++;
48                 }
49                 else if (*path == '%' && path[1] && path[2])
50                 {
51                     ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
52                     path = path + 3;
53                 }
54                 else
55                     ret[i++] = *path++;
56             }
57             ret[i] = '\0';
58             return ret;
59         }
60         path = strchr(p1, '&');
61         if (path)
62             path++;
63     }
64     return 0;
65 }
66
67 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
68 {
69     const char *v = yaz_uri_val(path, name, o);
70     if (v)
71         *intp = odr_intdup(o, atoi(v));
72 }
73
74 int yaz_check_for_srw(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
75                       char **soap_ns, ODR decode)
76 {
77     if (!strcmp(hreq->method, "POST"))
78     {
79         const char *content_type = z_HTTP_header_lookup(hreq->headers,
80                                                         "Content-Type");
81         if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
82         {
83             char *db = "Default";
84             const char *p0 = hreq->path, *p1;
85             Z_SOAP *soap_package = 0;
86             int ret = -1;
87             int http_code = 500;
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 #if HAVE_XML2
156         int ret = -1;
157         char *charset = 0;
158         Z_SOAP *soap_package = 0;
159         static Z_SOAP_Handler soap_handlers[2] = {
160             {"http://www.loc.gov/zing/srw/", 0,
161              (Z_SOAP_fun) yaz_srw_codec},
162             {0, 0, 0}
163         };
164 #endif
165         
166         if (*p0 == '/')
167             p0++;
168         p1 = strchr(p0, '?');
169         if (!p1)
170             p1 = p0 + strlen(p0);
171         if (p1 != p0)
172         {
173             db = (char*) odr_malloc(decode, p1 - p0 + 1);
174             memcpy (db, p0, p1 - p0);
175             db[p1 - p0] = '\0';
176         }
177 #if HAVE_XML2
178         if (p1)
179             operation = yaz_uri_val(p1, "operation", decode);
180         if (!operation)
181             operation = "explain";
182         if (p1 && !strcmp(operation, "searchRetrieve"))
183         {
184             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
185             char *query = yaz_uri_val(p1, "query", decode);
186             char *pQuery = yaz_uri_val(p1, "pQuery", decode);
187             char *sortKeys = yaz_uri_val(p1, "sortKeys", decode);
188             
189             *srw_pdu = sr;
190             if (query)
191             {
192                 sr->u.request->query_type = Z_SRW_query_type_cql;
193                 sr->u.request->query.cql = query;
194             }
195             if (pQuery)
196             {
197                 sr->u.request->query_type = Z_SRW_query_type_pqf;
198                 sr->u.request->query.pqf = pQuery;
199             }
200             if (sortKeys)
201             {
202                 sr->u.request->sort_type = Z_SRW_sort_type_sort;
203                 sr->u.request->sort.sortKeys = sortKeys;
204             }
205             sr->u.request->recordSchema = yaz_uri_val(p1, "recordSchema", decode);
206             sr->u.request->recordPacking = yaz_uri_val(p1, "recordPacking", decode);
207             if (!sr->u.request->recordPacking)
208                 sr->u.request->recordPacking = "xml";
209             yaz_uri_val_int(p1, "maximumRecords", decode, 
210                         &sr->u.request->maximumRecords);
211             yaz_uri_val_int(p1, "startRecord", decode,
212                         &sr->u.request->startRecord);
213
214             sr->u.request->database = db;
215             *soap_ns = "SRU";
216             return 0;
217         }
218         else if (p1 && !strcmp(operation, "explain"))
219         {
220             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
221
222             *srw_pdu = sr;
223             sr->u.explain_request->recordPacking =
224                 yaz_uri_val(p1, "recordPacking", decode);
225             if (!sr->u.explain_request->recordPacking)
226                 sr->u.explain_request->recordPacking = "xml";
227             sr->u.explain_request->database = db;
228             *soap_ns = "SRU";
229             return 0;
230         }
231 #endif
232         return 1;
233     }
234     return 2;
235 }