2 * $Id: query_parser.c 53 2011-05-09 16:55:39Z kaori $
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
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
35 #define strcasecmp _stricmp
36 #define strncasecmp _strnicmp
45 #include "query_parser.h"
46 #include "opj_stdint.h"
49 #include "fcgi_stdio.h"
50 #define logstream FCGI_stdout
52 #define FCGI_stdout stdout
53 #define FCGI_stderr stderr
54 #define logstream stderr
59 * Get initialized query parameters
61 * @return initial query parameters
63 query_param_t * get_initquery(void);
66 * get a pair of field name and value from the string starting fieldname=fieldval&... format
68 * @param[in] stringptr pointer to the beginning of the parsing string
69 * @param[out] fieldname string to copy the field name, if not found, NULL
70 * @param[out] fieldval string to copy the field value, if not found, NULL
71 * @return pointer to the next field string, if there is none, NULL
73 char * get_fieldparam( const char *stringptr, char *fieldname, char *fieldval);
75 void parse_cclose( char *src, query_param_t *query_param);
76 void parse_metareq( char *field, query_param_t *query_param);
78 /* parse the requested components (parses forms like:a; a,b; a-b; a-b,c; a,b-c)*/
79 void parse_comps( char *field, query_param_t *query_param);
82 /** maximum length of field name*/
83 #define MAX_LENOFFIELDNAME 10
85 /** maximum length of field value*/
86 #define MAX_LENOFFIELDVAL 128
88 query_param_t * parse_query( const char *query_string)
90 query_param_t *query_param;
92 char fieldname[MAX_LENOFFIELDNAME], fieldval[MAX_LENOFFIELDVAL];
94 query_param = get_initquery();
96 pquery = query_string;
98 while( pquery!=NULL) {
100 pquery = get_fieldparam( pquery, fieldname, fieldval);
102 if( fieldname[0] != '\0'){
103 if( strcasecmp( fieldname, "target") == 0)
104 query_param->target = strdup( fieldval);
106 else if( strcasecmp( fieldname, "tid") == 0)
107 query_param->tid = strdup( fieldval);
109 else if( strcasecmp( fieldname, "fsiz") == 0)
110 sscanf( fieldval, "%d,%d", &query_param->fx, &query_param->fy);
112 else if( strcasecmp( fieldname, "roff") == 0)
113 sscanf( fieldval, "%d,%d", &query_param->rx, &query_param->ry);
115 else if( strcasecmp( fieldname, "rsiz") == 0)
116 sscanf( fieldval, "%d,%d", &query_param->rw, &query_param->rh);
118 else if( strcasecmp( fieldname, "layers") == 0)
119 sscanf( fieldval, "%d", &query_param->layers);
121 else if( strcasecmp( fieldname, "cid") == 0)
122 query_param->cid = strdup( fieldval);
124 else if( strcasecmp( fieldname, "cnew") == 0){
125 if( strncasecmp( fieldval, "http-tcp", 8) == 0)
126 query_param->cnew = tcp;
127 else if( strncasecmp( fieldval, "http", 4) == 0)
128 query_param->cnew = http;
131 else if( strcasecmp( fieldname, "cclose") == 0)
132 parse_cclose( fieldval, query_param);
134 else if( strcasecmp( fieldname, "metareq") == 0)
135 parse_metareq( fieldval, query_param);
137 else if( strcasecmp( fieldname, "comps") == 0)
138 parse_comps( fieldval, query_param);
140 else if( strcasecmp( fieldname, "type") == 0){
141 if( strncasecmp( fieldval, "jpp-stream", 10) == 0)
142 query_param->return_type = JPPstream;
143 else if( strncasecmp( fieldval, "jpt-stream", 10) == 0)
144 query_param->return_type = JPTstream;
147 else if( strcasecmp( fieldname, "len") == 0){
148 sscanf( fieldval, "%d", &query_param->len);
149 if( query_param->len == 2000) /* for kakadu client*/
150 strncpy( query_param->box_type[0], "ftyp", 4);
157 query_param_t * get_initquery(void)
159 query_param_t *query;
162 query = (query_param_t *)malloc( sizeof(query_param_t));
164 query->target = NULL;
173 query->lastcomp = -1;
177 query->cclose = NULL;
178 query->numOfcclose = 0;
179 memset( query->box_type, 0, MAX_NUMOFBOX*4);
180 memset( query->limit, 0, MAX_NUMOFBOX*sizeof(int));
181 for( i=0; i<MAX_NUMOFBOX; i++){
186 query->priority[i] = false;
189 query->max_depth = -1;
190 query->metadata_only = false;
191 query->return_type = UNKNOWN;
198 char * get_fieldparam( const char *stringptr, char *fieldname, char *fieldval)
200 char *eqp, *andp, *nexfieldptr;
202 if((eqp = strchr( stringptr, '='))==NULL){
203 fprintf( stderr, "= not found\n");
204 strcpy( fieldname, "");
205 strcpy( fieldval, "");
208 if((andp = strchr( stringptr, '&'))==NULL){
209 andp = strchr( stringptr, '\0');
213 nexfieldptr = andp+1;
215 assert( (size_t)(eqp-stringptr));
216 strncpy( fieldname, stringptr, (size_t)(eqp-stringptr));
217 fieldname[eqp-stringptr]='\0';
218 assert( andp-eqp-1 >= 0);
219 strncpy( fieldval, eqp+1, (size_t)(andp-eqp-1));
220 fieldval[andp-eqp-1]='\0';
225 void print_queryparam( query_param_t query_param)
230 fprintf( logstream, "query parameters:\n");
232 if( query_param.target)
233 fprintf( logstream, "\t target: %s\n", query_param.target);
236 fprintf( logstream, "\t tid: %s\n", query_param.tid);
238 fprintf( logstream, "\t fx,fy: %d, %d\n", query_param.fx, query_param.fy);
239 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);
240 fprintf( logstream, "\t layers: %d\n", query_param.layers);
241 fprintf( logstream, "\t components: ");
243 if( query_param.lastcomp == -1)
244 fprintf( logstream, "ALL\n");
246 for( i=0; i<=query_param.lastcomp; i++)
247 if( query_param.comps[i])
248 fprintf( logstream, "%d ", i);
249 fprintf( logstream, "\n");
251 fprintf( logstream, "\t cnew: %d\n", query_param.cnew);
254 fprintf( logstream, "\t cid: %s\n", query_param.cid);
256 if( query_param.cclose){
257 fprintf( logstream, "\t cclose: ");
259 for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++){
260 fprintf( logstream, "%s ", cclose);
261 cclose += (strlen(cclose)+1);
263 fprintf(logstream, "\n");
266 fprintf( logstream, "\t req-box-prop\n");
267 for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
268 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]);
271 fprintf( logstream, "\t root-bin: %d\n", query_param.root_bin);
272 fprintf( logstream, "\t max-depth: %d\n", query_param.max_depth);
273 fprintf( logstream, "\t metadata-only: %d\n", query_param.metadata_only);
274 fprintf( logstream, "\t image return type: %d, [JPP-stream=0, JPT-stream=1, UNKNOWN=-1]\n", query_param.return_type);
275 fprintf( logstream, "\t len: %d\n", query_param.len);
278 void parse_cclose( char *src, query_param_t *query_param)
284 query_param->cclose = strdup( src);
286 for( i=0; i<len; i++)
287 if( query_param->cclose[i] == ','){
288 query_param->cclose[i] = '\0';
289 query_param->numOfcclose ++;
292 query_param->numOfcclose ++;
295 void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param);
297 void parse_metareq( char *field, query_param_t *query_param)
299 char req_box_prop[20];
303 memset( req_box_prop, 0, 20);
306 ptr = strchr( field, '[');
311 assert( ptr-src >= 0);
312 strncpy( req_box_prop, src, (size_t)(ptr-src));
313 parse_req_box_prop( req_box_prop, numofboxreq++, query_param);
316 memset( req_box_prop, 0, 20);
321 strncpy( req_box_prop, src, (size_t)(ptr-src));
323 parse_req_box_prop( req_box_prop, numofboxreq++, query_param);
325 if(( ptr = strchr( field, 'R')))
326 sscanf( ptr+1, "%d", &(query_param->root_bin));
328 if(( ptr = strchr( field, 'D')))
329 sscanf( ptr+1, "%d", &(query_param->max_depth));
331 if(( ptr = strstr( field, "!!")))
332 query_param->metadata_only = true;
335 void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param)
339 if( *req_box_prop == '*')
340 query_param->box_type[idx][0]='*';
342 strncpy( query_param->box_type[idx], req_box_prop, 4);
344 if(( ptr = strchr( req_box_prop, ':'))){
346 query_param->limit[idx] = -1;
348 sscanf( ptr+1, "%d", &(query_param->limit[idx]));
351 if(( ptr = strchr( req_box_prop, '/'))){
353 while( *ptr=='w' || *ptr=='s' || *ptr=='g' || *ptr=='a'){
355 case 'w': query_param->w[idx] = true; break;
356 case 's': query_param->s[idx] = true; break;
357 case 'g': query_param->g[idx] = true; break;
358 case 'a': query_param->a[idx] = true; break;
364 query_param->g[idx] = true;
365 query_param->s[idx] = true;
366 query_param->w[idx] = true;
369 if((ptr = strchr( req_box_prop, '!')))
370 query_param->priority[idx] = true;
375 void parse_comps( char *field, query_param_t *query_param)
377 int i,start,stop,aux = -1;
380 ptr1 = strchr( field, '-');
381 ptr2 = strchr( field, ',');
385 sscanf( field, "%d,%d-%d",&aux, &start, &stop);
387 sscanf( field, "%d-%d,%d", &start, &stop, &aux);
390 sscanf( field, "%d-%d", &start, &stop);
392 sscanf( field, "%d,%d", &start, &stop);
397 sscanf( field, "%d", &stop);
401 query_param->lastcomp = stop > aux ? stop : aux;
402 query_param->comps = (bool *)calloc( 1, (OPJ_SIZE_T)(query_param->lastcomp+1)*sizeof(bool));
404 for( i=start; i<=stop; i++)
405 query_param->comps[i]=true;
408 query_param->comps[aux] = true;
411 void delete_query( query_param_t **query)
413 if( (*query)->target)
414 free( (*query)->target);
417 free( (*query)->tid);
420 free((*query)->comps);
423 free( (*query)->cid);
425 if( (*query)->cclose)
426 free( (*query)->cclose);