1 /*
2 * $Id: query_parser.c 53 2011-05-09 16:55:39Z kaori $
3 *
4 * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5 * Copyright (c) 2002-2011, Professor Benoit Macq
6 * Copyright (c) 2010-2011, Kaori Hagihara
7 * Copyright (c) 2011, Lucian Corlaciu, GSoC
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33 #ifdef _WIN32
34 #include <windows.h>
35 #define strcasecmp _stricmp
36 #define strncasecmp _strnicmp
37 #else
38 #include <strings.h>
39 #endif
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include "query_parser.h"
45
46 #ifdef SERVER
47 #include "fcgi_stdio.h"
48 #define logstream FCGI_stdout
49 #else
50 #define FCGI_stdout stdout
51 #define FCGI_stderr stderr
52 #define logstream stderr
53 #endif /*SERVER*/
54
55
56 /**
57 * Get initialized query parameters
58 *
59 * @return initial query parameters
60 */
61 query_param_t * get_initquery(void);
62
63 /*
64 * get a pair of field name and value from the string starting fieldname=fieldval&... format
65 *
66 * @param[in] stringptr pointer to the beginning of the parsing string
67 * @param[out] fieldname string to copy the field name, if not found, NULL
68 * @param[out] fieldval string to copy the field value, if not found, NULL
69 * @return pointer to the next field string, if there is none, NULL
70 */
71 char * get_fieldparam( char *stringptr, char *fieldname, char *fieldval);
72
73 void parse_cclose( char *src, query_param_t *query_param);
74 void parse_metareq( char *field, query_param_t *query_param);
75
76 /* parse the requested components (parses forms like:a; a,b; a-b; a-b,c; a,b-c)*/
77 void parse_comps( char *field, query_param_t *query_param);
78
79
80 /** maximum length of field name*/
81 #define MAX_LENOFFIELDNAME 10
82
83 /** maximum length of field value*/
84 #define MAX_LENOFFIELDVAL 128
85
parse_query(char * query_string)86 query_param_t * parse_query( char *query_string)
87 {
88 query_param_t *query_param;
89 char *pquery, fieldname[MAX_LENOFFIELDNAME], fieldval[MAX_LENOFFIELDVAL];
90
91 query_param = get_initquery();
92
93 pquery = query_string;
94
95 while( pquery!=NULL) {
96
97 pquery = get_fieldparam( pquery, fieldname, fieldval);
98
99 if( fieldname[0] != '\0'){
100 if( strcasecmp( fieldname, "target") == 0)
101 query_param->target = strdup( fieldval);
102
103 else if( strcasecmp( fieldname, "tid") == 0)
104 query_param->tid = strdup( fieldval);
105
106 else if( strcasecmp( fieldname, "fsiz") == 0)
107 sscanf( fieldval, "%d,%d", &query_param->fx, &query_param->fy);
108
109 else if( strcasecmp( fieldname, "roff") == 0)
110 sscanf( fieldval, "%d,%d", &query_param->rx, &query_param->ry);
111
112 else if( strcasecmp( fieldname, "rsiz") == 0)
113 sscanf( fieldval, "%d,%d", &query_param->rw, &query_param->rh);
114
115 else if( strcasecmp( fieldname, "layers") == 0)
116 sscanf( fieldval, "%d", &query_param->layers);
117
118 else if( strcasecmp( fieldname, "cid") == 0)
119 query_param->cid = strdup( fieldval);
120
121 else if( strcasecmp( fieldname, "cnew") == 0){
122 if( strncasecmp( fieldval, "http-tcp", 8) == 0)
123 query_param->cnew = tcp;
124 else if( strncasecmp( fieldval, "http", 4) == 0)
125 query_param->cnew = http;
126 }
127
128 else if( strcasecmp( fieldname, "cclose") == 0)
129 parse_cclose( fieldval, query_param);
130
131 else if( strcasecmp( fieldname, "metareq") == 0)
132 parse_metareq( fieldval, query_param);
133
134 else if( strcasecmp( fieldname, "comps") == 0)
135 parse_comps( fieldval, query_param);
136
137 else if( strcasecmp( fieldname, "type") == 0){
138 if( strncasecmp( fieldval, "jpp-stream", 10) == 0)
139 query_param->return_type = JPPstream;
140 else if( strncasecmp( fieldval, "jpt-stream", 10) == 0)
141 query_param->return_type = JPTstream;
142 }
143
144 else if( strcasecmp( fieldname, "len") == 0){
145 sscanf( fieldval, "%d", &query_param->len);
146 if( query_param->len == 2000) /* for kakadu client*/
147 strncpy( query_param->box_type[0], "ftyp", 4);
148 }
149 }
150 }
151 return query_param;
152 }
153
get_initquery(void)154 query_param_t * get_initquery(void)
155 {
156 query_param_t *query;
157 int i;
158
159 query = (query_param_t *)malloc( sizeof(query_param_t));
160
161 query->target = NULL;
162 query->tid = NULL;
163 query->fx = -1;
164 query->fy = -1;
165 query->rx = -1;
166 query->ry = -1;
167 query->rw = -1;
168 query->rh = -1;
169 query->layers = -1;
170 query->lastcomp = -1;
171 query->comps = NULL;
172 query->cid = NULL;
173 query->cnew = non;
174 query->cclose = NULL;
175 query->numOfcclose = 0;
176 memset( query->box_type, 0, MAX_NUMOFBOX*4);
177 memset( query->limit, 0, MAX_NUMOFBOX*sizeof(int));
178 for( i=0; i<MAX_NUMOFBOX; i++){
179 query->w[i] = false;
180 query->s[i] = false;
181 query->g[i] = false;
182 query->a[i] = false;
183 query->priority[i] = false;
184 }
185 query->root_bin = 0;
186 query->max_depth = -1;
187 query->metadata_only = false;
188 query->return_type = UNKNOWN;
189 query->len = -1;
190
191 return query;
192 }
193
194
get_fieldparam(char * stringptr,char * fieldname,char * fieldval)195 char * get_fieldparam( char *stringptr, char *fieldname, char *fieldval)
196 {
197 char *eqp, *andp, *nexfieldptr;
198
199 if((eqp = strchr( stringptr, '='))==NULL){
200 fprintf( stderr, "= not found\n");
201 strcpy( fieldname, "");
202 strcpy( fieldval, "");
203 return NULL;
204 }
205 if((andp = strchr( stringptr, '&'))==NULL){
206 andp = strchr( stringptr, '\0');
207 nexfieldptr = NULL;
208 }
209 else
210 nexfieldptr = andp+1;
211
212 strncpy( fieldname, stringptr, eqp-stringptr);
213 fieldname[eqp-stringptr]='\0';
214 strncpy( fieldval, eqp+1, andp-eqp-1);
215 fieldval[andp-eqp-1]='\0';
216
217 return nexfieldptr;
218 }
219
print_queryparam(query_param_t query_param)220 void print_queryparam( query_param_t query_param)
221 {
222 int i;
223 char *cclose;
224
225 fprintf( logstream, "query parameters:\n");
226
227 if( query_param.target)
228 fprintf( logstream, "\t target: %s\n", query_param.target);
229
230 if( query_param.tid)
231 fprintf( logstream, "\t tid: %s\n", query_param.tid);
232
233 fprintf( logstream, "\t fx,fy: %d, %d\n", query_param.fx, query_param.fy);
234 fprintf( logstream, "\t rx,ry: %d, %d \t rw,rh: %d, %d\n", query_param.rx, query_param.ry, query_param.rw, query_param.rh);
235 fprintf( logstream, "\t layers: %d\n", query_param.layers);
236 fprintf( logstream, "\t components: ");
237
238 if( query_param.lastcomp == -1)
239 fprintf( logstream, "ALL\n");
240 else{
241 for( i=0; i<=query_param.lastcomp; i++)
242 if( query_param.comps[i])
243 fprintf( logstream, "%d ", i);
244 fprintf( logstream, "\n");
245 }
246 fprintf( logstream, "\t cnew: %d\n", query_param.cnew);
247
248 if( query_param.cid)
249 fprintf( logstream, "\t cid: %s\n", query_param.cid);
250
251 if( query_param.cclose){
252 fprintf( logstream, "\t cclose: ");
253
254 for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++){
255 fprintf( logstream, "%s ", cclose);
256 cclose += (strlen(cclose)+1);
257 }
258 fprintf(logstream, "\n");
259 }
260
261 fprintf( logstream, "\t req-box-prop\n");
262 for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
263 fprintf( logstream, "\t\t box_type: %.4s limit: %d w:%d s:%d g:%d a:%d priority:%d\n", query_param.box_type[i], query_param.limit[i], query_param.w[i], query_param.s[i], query_param.g[i], query_param.a[i], query_param.priority[i]);
264 }
265
266 fprintf( logstream, "\t root-bin: %d\n", query_param.root_bin);
267 fprintf( logstream, "\t max-depth: %d\n", query_param.max_depth);
268 fprintf( logstream, "\t metadata-only: %d\n", query_param.metadata_only);
269 fprintf( logstream, "\t image return type: %d, [JPP-stream=0, JPT-stream=1, UNKNOWN=-1]\n", query_param.return_type);
270 fprintf( logstream, "\t len: %d\n", query_param.len);
271 }
272
parse_cclose(char * src,query_param_t * query_param)273 void parse_cclose( char *src, query_param_t *query_param)
274 {
275 size_t i;
276 size_t len;
277
278 len = strlen( src);
279 query_param->cclose = strdup( src);
280
281 for( i=0; i<len; i++)
282 if( query_param->cclose[i] == ','){
283 query_param->cclose[i] = '\0';
284 query_param->numOfcclose ++;
285 }
286
287 query_param->numOfcclose ++;
288 }
289
290 void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param);
291
parse_metareq(char * field,query_param_t * query_param)292 void parse_metareq( char *field, query_param_t *query_param)
293 {
294 char req_box_prop[20];
295 char *ptr, *src;
296 int numofboxreq = 0;
297
298 memset( req_box_prop, 0, 20);
299
300 /* req-box-prop*/
301 ptr = strchr( field, '[');
302 ptr++;
303 src = ptr;
304 while( *ptr != ']'){
305 if( *ptr == ';'){
306 strncpy( req_box_prop, src, ptr-src);
307 parse_req_box_prop( req_box_prop, numofboxreq++, query_param);
308 ptr++;
309 src = ptr;
310 memset( req_box_prop, 0, 20);
311 }
312 ptr++;
313 }
314 strncpy( req_box_prop, src, ptr-src);
315
316 parse_req_box_prop( req_box_prop, numofboxreq++, query_param);
317
318 if(( ptr = strchr( field, 'R')))
319 sscanf( ptr+1, "%d", &(query_param->root_bin));
320
321 if(( ptr = strchr( field, 'D')))
322 sscanf( ptr+1, "%d", &(query_param->max_depth));
323
324 if(( ptr = strstr( field, "!!")))
325 query_param->metadata_only = true;
326 }
327
parse_req_box_prop(char * req_box_prop,int idx,query_param_t * query_param)328 void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param)
329 {
330 char *ptr;
331
332 if( *req_box_prop == '*')
333 query_param->box_type[idx][0]='*';
334 else
335 strncpy( query_param->box_type[idx], req_box_prop, 4);
336
337 if(( ptr = strchr( req_box_prop, ':'))){
338 if( *(ptr+1)=='r')
339 query_param->limit[idx] = -1;
340 else
341 sscanf( ptr+1, "%d", &(query_param->limit[idx]));
342 }
343
344 if(( ptr = strchr( req_box_prop, '/'))){
345 ptr++;
346 while( *ptr=='w' || *ptr=='s' || *ptr=='g' || *ptr=='a'){
347 switch( *ptr){
348 case 'w': query_param->w[idx] = true; break;
349 case 's': query_param->s[idx] = true; break;
350 case 'g': query_param->g[idx] = true; break;
351 case 'a': query_param->a[idx] = true; break;
352 }
353 ptr++;
354 }
355 }
356 else{
357 query_param->g[idx] = true;
358 query_param->s[idx] = true;
359 query_param->w[idx] = true;
360 }
361
362 if((ptr = strchr( req_box_prop, '!')))
363 query_param->priority[idx] = true;
364
365 idx++;
366 }
367
parse_comps(char * field,query_param_t * query_param)368 void parse_comps( char *field, query_param_t *query_param)
369 {
370 int i,start,stop,aux = -1;
371 char *ptr1,*ptr2;
372
373 ptr1 = strchr( field, '-');
374 ptr2 = strchr( field, ',');
375
376 if( ptr1 && ptr2)
377 if( ptr1 > ptr2)
378 sscanf( field, "%d,%d-%d",&aux, &start, &stop);
379 else
380 sscanf( field, "%d-%d,%d", &start, &stop, &aux);
381 else
382 if(ptr1)
383 sscanf( field, "%d-%d", &start, &stop);
384 else if(ptr2){
385 sscanf( field, "%d,%d", &start, &stop);
386 aux = start;
387 start = stop;
388 }
389 else{
390 sscanf( field, "%d", &stop);
391 start = stop;
392 }
393
394 query_param->lastcomp = stop > aux ? stop : aux;
395 query_param->comps = (bool *)calloc( 1, (query_param->lastcomp+1)*sizeof(bool));
396
397 for( i=start; i<=stop; i++)
398 query_param->comps[i]=true;
399
400 if(aux!=-1)
401 query_param->comps[aux] = true;
402 }
403
delete_query(query_param_t ** query)404 void delete_query( query_param_t **query)
405 {
406 if( (*query)->target)
407 free( (*query)->target);
408
409 if( (*query)->tid)
410 free( (*query)->tid);
411
412 if( (*query)->comps)
413 free((*query)->comps);
414
415 if( (*query)->cid)
416 free( (*query)->cid);
417
418 if( (*query)->cclose)
419 free( (*query)->cclose);
420
421 free( *query);
422 }
423