modules/qc/query_command.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- qc_sources_list_to_string
- QC_environ_to_string
- QC_query_command_to_string
- log_command
- QC_environ_free
- QC_free
- QC_fill
- QC_environ_new
- QC_create
- QC_get_qrytype
1 /***************************************
2 $Revision: 1.52 $
3
4 Query command module (qc). This is what the whois query gets stored as in
5 memory.
6
7 Status: NOT REVUED, TESTED
8
9 ******************/ /******************
10 Filename : query_command.c
11 Author : ottrey@ripe.net
12 Modifications by : marek@ripe.net
13 ******************/ /******************
14 Copyright (c) 1999,2000,2001 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33
34 #define QC_IMPL
35 #include "rip.h"
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <ctype.h>
41
42
43 #define MAX_OPT_ARG_C 20
44
45 extern char *suboptarg;
46 extern int getsubopt(char **optionp, char * const *tokens, char **valuep);
47
48 /*++++++++++++++++++++++++++++++++++++++
49 make a list of sources. expects list to hold source handles
50
51 char *
52 qc_sources_list_to_string returns an allocated string, must be freed
53
54 GList *list list of source handles (as defined by CA)
55
56 ++++++++++++++++++++++++++++++++++++++*/
57 char *
58 qc_sources_list_to_string(GList *list)
/* [<][>][^][v][top][bottom][index][help] */
59 {
60 GString *tmp;
61 GList *qitem;
62 char *result;
63
64 /* use GString for the result, because it resizes magically */
65 tmp = g_string_sized_new(STR_L);
66
67 /* loop through the list, creating a string with the names of the
68 sources separated by commas */
69 qitem = g_list_first(list);
70 if (qitem != NULL) {
71 for (;;) {
72 ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data );
73 char *srcname = ca_get_srcname( source_hdl );
74 g_string_append(tmp, srcname);
75
76 qitem = g_list_next(qitem);
77 if (qitem == NULL) {
78 break;
79 }
80
81 g_string_append_c(tmp, ',');
82 }
83 }
84
85 /* move to a new buffer for the return */
86 result = UT_strdup(tmp->str);
87 g_string_free(tmp, TRUE);
88 return result;
89 }
90
91 /* QC_environ_to_string() */
92 /*++++++++++++++++++++++++++++++++++++++
93 Convert the query_environ to a string.
94
95 Query_environ *query_environ The query_environ to be converted.
96
97 More:
98 +html+ <PRE>
99 Authors:
100 ottrey
101 +html+ </PRE><DL COMPACT>
102 +html+ <DT>Online References:
103 +html+ <DD><UL>
104 +html+ </UL></DL>
105
106 ++++++++++++++++++++++++++++++++++++++*/
107 char *
108 QC_environ_to_string(Query_environ qe)
/* [<][>][^][v][top][bottom][index][help] */
109 {
110 char *sources;
111 char passed_addr[IP_ADDRSTR_MAX];
112 GString *tmp;
113 char *result;
114
115 /* convert the sources and the passed address (if any) to printable strings */
116 sources = qc_sources_list_to_string(qe.sources_list);
117 if( IP_addr_b2a( &(qe.pIP), passed_addr, IP_ADDRSTR_MAX) != IP_OK ) {
118 passed_addr[0] = '\0';
119 }
120
121 /* format the environment info */
122 tmp = g_string_sized_new(STR_L);
123 g_string_sprintf(tmp,
124 "host=%s, keep_connection=%s, sources=%s, version=%s%s%s",
125 qe.condat.ip,
126 qe.k ? "on" : "off",
127 sources,
128 (qe.version == NULL) ? "?" : qe.version,
129 passed_addr[0] == '\0' ? "" : ", passedIP=",
130 passed_addr);
131
132 /* move result to return buffer, and free up memory */
133 result = UT_strdup(tmp->str);
134 g_string_free(tmp, TRUE);
135 UT_free(sources);
136
137 return result;
138
139 } /* QC_environ_to_string() */
140
141 /* QC_query_command_to_string() */
142 /*++++++++++++++++++++++++++++++++++++++
143 Convert the query_command to a string.
144
145 Query_command *query_command The query_command to be converted.
146
147 More:
148 +html+ <PRE>
149 Authors:
150 ottrey
151 +html+ </PRE><DL COMPACT>
152 +html+ <DT>Online References:
153 +html+ <DD><UL>
154 +html+ </UL></DL>
155
156 ++++++++++++++++++++++++++++++++++++++*/
157 char *QC_query_command_to_string(Query_command *query_command) {
/* [<][>][^][v][top][bottom][index][help] */
158 char result_buf[STR_XL];
159 char *str1;
160 char *str2;
161 char *str3;
162
163 str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
164 str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
165 str3 = WK_to_string(query_command->keytypes_bitmap);
166
167 sprintf(result_buf, "Query_command : inv_attrs=%s, recursive=%s, object_type=%s, (e=%d,g=%d,l=%d,m=%d,q=%d,t=%d,v=%d,x=%d,F=%d,K=%d,L=%d,M=%d,R=%d,S=%d), possible keytypes=%s, keys=[%s]",
168 str1,
169 query_command->recursive?"y":"n",
170 str2,
171 query_command->e,
172 query_command->g,
173 query_command->l,
174 query_command->m,
175 query_command->q,
176 query_command->t,
177 query_command->v,
178 query_command->x,
179 query_command->fast,
180 query_command->filtered,
181 query_command->L,
182 query_command->M,
183 query_command->R,
184 query_command->S,
185 str3,
186 query_command->keys);
187 UT_free(str1);
188 UT_free(str2);
189 UT_free(str3);
190
191 return UT_strdup(result_buf);
192
193 } /* QC_query_command_to_string() */
194
195 /* log_command() */
196 /*++++++++++++++++++++++++++++++++++++++
197 Log the command.
198 This is more to do with Tracing. And should/will get merged with a tracing
199 module (when it is finalized.)
200
201 char *query_str
202
203 Query_command *query_command
204
205 More:
206 +html+ <PRE>
207 Authors:
208 ottrey
209 +html+ </PRE><DL COMPACT>
210 +html+ <DT>Online References:
211 +html+ <DD><UL>
212 +html+ </UL></DL>
213
214 ++++++++++++++++++++++++++++++++++++++*/
215 static void log_command(char *query_str, Query_command *query_command) {
/* [<][>][^][v][top][bottom][index][help] */
216 char *str;
217
218 if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
219 str = QC_query_command_to_string(query_command);
220 ER_dbg_va(FAC_QC, ASP_QC_BUILD,
221 "query=[%s] %s", query_str, str);
222 UT_free(str);
223 }
224 } /* log_command() */
225
226 /* QC_environ_free() */
227 /*++++++++++++++++++++++++++++++++++++++
228 Free the query_environ.
229
230 Query_command *qc query_environ to be freed.
231
232 More:
233 +html+ <PRE>
234 Authors:
235 ottrey
236 +html+ </PRE><DL COMPACT>
237 +html+ <DT>Online References:
238 +html+ <DD><UL>
239 +html+ </UL></DL>
240
241 ++++++++++++++++++++++++++++++++++++++*/
242 void QC_environ_free(Query_environ *qe) {
/* [<][>][^][v][top][bottom][index][help] */
243 if (qe != NULL) {
244 if (qe->version != NULL) {
245 UT_free(qe->version);
246 }
247
248 if (qe->sources_list != NULL) {
249 g_list_free(qe->sources_list);
250 qe->sources_list=NULL;
251 }
252 UT_free(qe);
253 }
254 } /* QC_environ_free() */
255
256 /* QC_free() */
257 /*++++++++++++++++++++++++++++++++++++++
258 Free the query_command.
259
260 Query_command *qc query_command to be freed.
261
262 XXX I'm not sure the bitmaps will get freed.
263 qc->inv_attrs_bitmap
264 qc->object_type_bitmap
265 qc->keytypes_bitmap
266
267 More:
268 +html+ <PRE>
269 Authors:
270 ottrey
271 +html+ </PRE><DL COMPACT>
272 +html+ <DT>Online References:
273 +html+ <DD><UL>
274 +html+ </UL></DL>
275
276 ++++++++++++++++++++++++++++++++++++++*/
277 void QC_free(Query_command *qc) {
/* [<][>][^][v][top][bottom][index][help] */
278 if (qc != NULL) {
279 if (qc->keys != NULL) {
280 UT_free(qc->keys);
281 }
282 UT_free(qc);
283 }
284 } /* QC_free() */
285
286
287
288 /* QC_fill() */
289 /*++++++++++++++++++++++++++++++++++++++
290 Create a new query_command.
291 Returns 0 when OK, -1 when query incorrect.
292
293 char *query_str The garden variety whois query string.
294
295 Query_environ *qe the environment
296
297 More:
298 +html+ <PRE>
299 Authors:
300 ottrey - original code
301 marek - modified for my getopts, multiple sources;
302 and generally cleaned.
303 +html+ </PRE><DL COMPACT>
304 +html+ <DT>Online References:
305 +html+ <DD><UL>
306 +html+ </UL></DL>
307
308 ++++++++++++++++++++++++++++++++++++++*/
309 static
310 int QC_fill(char *query_str,
/* [<][>][^][v][top][bottom][index][help] */
311 Query_command *query_command,
312 Query_environ *qe) {
313
314 int c;
315 int synerrflg = 0;
316 int badparerr = 0;
317 int minusk = 0;
318 char *inv_attrs_str = NULL;
319 char *object_types_str = NULL;
320 int opt_argc;
321 gchar **opt_argv;
322 char *value;
323 /* char *tmp_query_str;*/
324 unsigned key_length;
325 int i;
326 int index;
327 C_Type_t type;
328 A_Type_t attr;
329 getopt_state_t *gst = NULL;
330
331 query_command->d = 0;
332 query_command->e = 0;
333 query_command->g = 0;
334 query_command->inv_attrs_bitmap = MA_new(MA_END);
335 query_command->recursive = 1; /* Recursion is on by default. */
336 query_command->l = 0;
337 query_command->m = 0;
338 query_command->q = -1;
339 query_command->t = -1;
340 query_command->v = -1;
341 query_command->x = 0;
342 query_command->fast = 0;
343 query_command->filtered = 0;
344 query_command->L = 0;
345 query_command->M = 0;
346 query_command->R = 0;
347 query_command->S = 0;
348
349 /* XXX UGLY - "all zeros" in object_type_bitmap means the same as
350 "all ones". To limit the inconsistency, this is changed at the end
351 of this function, so outside "all zeros" is an illegal value. */
352 query_command->object_type_bitmap = MA_new(MA_END);
353 /*
354 query_command->keytypes_bitmap = MA_new(MA_END);
355 */
356 query_command->keys = NULL;
357
358 /* This is so Marek can't crash me :-) */
359 /* Side Effect - query keys are subsequently cut short to STR_S size. */
360
361 /* tmp_query_str = (char *)UT_calloc(1, STR_S+1);
362 strncpy(tmp_query_str, query_str, STR_S);*/
363
364 /* Create the arguments. */
365 /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
366 /* opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);*/
367 opt_argv = g_strsplit(query_str, " ", MAX_OPT_ARG_C);
368
369 /* Determine the number of arguments. */
370 for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
371
372 dieif( (gst = mg_new(0)) == NULL );
373
374 while ((c = mg_getopt(opt_argc, opt_argv, "adegi:klrmq:s:t:v:xFKLMRST:V:",
375 gst)) != EOF) {
376 switch (c) {
377 case 'a':
378 /* Remove any user specified sources from the sources list. */
379 /* free the list only, do not touch the elements */
380 g_list_free(qe->sources_list);
381 qe->sources_list=NULL;
382
383 /* Add all the config sources to the sources list. */
384 {
385 int i;
386 ca_dbSource_t *hdl;
387
388 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
389 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
390 }
391 }
392
393
394 break;
395
396 case 'e':
397 query_command->e=1;
398 break;
399
400 case 'd':
401 query_command->d=1;
402 break;
403
404 case 'g':
405 query_command->g=1;
406 break;
407
408 case 'i':
409 if (gst->optarg != NULL) {
410 char *hackstr = NULL;
411
412 inv_attrs_str = gst->optarg;
413 /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
414 /* I particularly object to this because it references attributes that should only be
415 defined in XML - but I don't see a simplier more robust way of doing this hack.
416 :-( - ottrey 8/12/99
417 ** removed a memory leak - MB, 1/08/00
418 */
419 if ( strcmp(inv_attrs_str, "pn") == 0
420 || strcmp(inv_attrs_str, "ro") == 0) {
421 hackstr = UT_strdup("ac,tc,zc,ah");
422 inv_attrs_str = hackstr;
423 }
424 while (*inv_attrs_str) {
425 index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
426 if (index == -1) {
427 /* Unknown attribute encountered. */
428 char *rep = ca_get_qc_badattr ;
429 SK_cd_puts(&(qe->condat), rep);
430 UT_free(rep);
431
432 attr = -1;
433 badparerr++;
434 }
435 else {
436 mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
437 attr = DF_get_attribute_index(index);
438 if ( MA_isset(inv_attr_mask, attr) == 1 ) {
439 /* Add the attr to the bitmap. */
440 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
441 }
442 else {
443 /* "%s" is not an inverse searchable attribute. */
444 char *rep = ca_get_qc_fmt_attrnotinv ;
445 SK_cd_printf(&(qe->condat), rep,
446 (DF_get_attribute_aliases())[index]);
447 UT_free(rep);
448 badparerr++;
449 }
450 }
451 } /* while () */
452
453 if( hackstr != NULL) {
454 UT_free(hackstr);
455 }
456 } /* if () */
457 break;
458
459 case 'k':
460 minusk = 1;
461 break;
462
463 case 'r':
464 query_command->recursive=0; /* Unset recursion */
465 break;
466
467 case 'l':
468 query_command->l=1;
469 break;
470
471 case 'm':
472 query_command->m=1;
473 break;
474
475 case 'q':
476 if (gst->optarg != NULL) {
477 index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
478 if (index == -1) {
479 synerrflg++;
480 }
481 else {
482 query_command->q = index;
483 }
484 } /* if () */
485 break;
486
487 case 's':
488 if (gst->optarg != NULL) {
489 char *token, *cursor = gst->optarg;
490 ca_dbSource_t *handle;
491
492 /* Remove any sources from the sources list. */
493 g_list_free(qe->sources_list);
494 qe->sources_list=NULL;
495
496 /* go through specified sources */
497 while( (token = strsep( &cursor, "," )) != NULL ) {
498
499 if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
500 /* append */
501 qe->sources_list
502 = g_list_append(qe->sources_list, (void *) handle );
503 }
504 else {
505 /* bail out */
506
507 /* Unknown source %s requested. */
508 char *rep = ca_get_qc_fmt_badsource ;
509 SK_cd_printf(&(qe->condat), rep, token );
510 UT_free(rep);
511
512 /* XXX error */
513 badparerr++;
514
515 } /* if handle not null */
516 } /* while sources */
517 } /* if argument present */
518 break;
519
520 case 't':
521 if (gst->optarg != NULL) {
522 object_types_str = gst->optarg;
523 while (*object_types_str) {
524 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
525 if (index == -1) {
526 /* Unknown object type encountered */
527 char *rep = ca_get_qc_badobjtype ;
528 SK_cd_puts(&(qe->condat), rep);
529 UT_free(rep);
530 badparerr++;
531 }
532 else {
533 type = DF_get_class_index(index);
534 query_command->t=type;
535 }
536 }
537 }
538 break;
539
540 case 'v':
541 if (gst->optarg != NULL) {
542 object_types_str = gst->optarg;
543 if (*object_types_str) {
544 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
545 if (index == -1) {
546 /* Unknown object type encountered */
547 char *rep = ca_get_qc_badobjtype ;
548 SK_cd_puts(&(qe->condat), rep);
549 UT_free(rep);
550 badparerr++;
551 }
552 else {
553 type = DF_get_class_index(index);
554 query_command->v=type;
555 }
556 }
557 }
558 break;
559
560 case 'x':
561 query_command->x=1;
562 break;
563
564 case 'F':
565 query_command->fast=1;
566 query_command->recursive=0; /* implies no recursion */
567 break;
568
569 case 'K':
570 query_command->filtered=1;
571 query_command->recursive=0; /* implies no recursion */
572 break;
573
574 case 'L':
575 query_command->L=1;
576 break;
577
578 case 'M':
579 query_command->M=1;
580 break;
581
582 case 'R':
583 query_command->R=1;
584 break;
585
586 case 'S':
587 query_command->S=1;
588 break;
589
590 case 'T':
591 if (gst->optarg != NULL) {
592 /* parse the specification */
593 object_types_str = gst->optarg;
594 while (*object_types_str) {
595 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
596 if (index == -1) {
597 /* Unknown object type encountered */
598 char *rep = ca_get_qc_badobjtype ;
599 SK_cd_puts(&(qe->condat), rep);
600 UT_free(rep);
601 badparerr++;
602 }
603 else {
604 type = DF_get_class_index(index);
605 /* Add the type to the bitmap. */
606 MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
607 }
608 }
609 }
610 break;
611
612 case 'V':
613 if (qe->version != NULL) {
614 /* free up the old client info */
615 UT_free(qe->version);
616 }
617
618 {
619 char *token, *cursor = gst->optarg;
620 while( (token = strsep( &cursor, "," )) != NULL ) {
621 if(IP_addr_e2b( & (qe->pIP), token)
622 != IP_OK ) {
623 /* means it was not an IP -> it was a version */
624 qe->version = UT_strdup(token);
625 }
626 }
627 }
628 break;
629
630 /* any other flag, including '?' and ':' errors */
631 default:
632 synerrflg++;
633 }
634 }
635
636 /* copy the key */
637
638 /* Work out the length of space needed */
639 key_length = 1; /* for terminal '\0' */
640 for (i=gst->optind ; i < opt_argc; i++) {
641 /* length for the string + 1 for the '\0'+ 1 for the ' ' */
642 if (opt_argv[i] != NULL) {
643 key_length += strlen(opt_argv[i])+1;
644 }
645 }
646 /* allocate */
647 query_command->keys = (char *)UT_calloc(1, key_length+1);
648
649 /* copy */
650 for (i=gst->optind; i < opt_argc; i++) {
651 strcat(query_command->keys, opt_argv[i]);
652 if ( (i + 1) < opt_argc) {
653 strcat(query_command->keys, " ");
654 }
655 }
656
657 /* if no error, process the key, otherwise don't bother */
658 if ( ! synerrflg && ! badparerr ) {
659 /* convert the key to uppercase. */
660 for (i=0; i <= key_length; i++) {
661 query_command->keys[i] = toupper(query_command->keys[i]);
662 }
663
664 /* make the keytypes_bitmap. */
665 query_command->keytypes_bitmap = WK_new(query_command->keys);
666
667 /* fix the object type bitmap - turn "all zeros" into "all ones" */
668 if( MA_bitcount(query_command->object_type_bitmap) == 0 ) {
669 query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap);
670 }
671
672 /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then
673 exclude the domains unless -d is set
674 XXX this must be kept in sync with new types */
675 if( query_command->d == 0
676 && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS)
677 || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE )
678 || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX )
679 || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX )
680 ) ) {
681
682 MA_set(&(query_command->object_type_bitmap), C_DN , 0);
683 }
684
685 /* tracing */
686 /* log_command(tmp_query_str, query_command);*/
687 log_command(query_str, query_command);
688
689 /* "keep connection" processing:
690 when opening connection, -k may be alone or with a query
691 later -k must appear alone (or there must be an empty line,
692 or an error) for the connection to close.
693 */
694 if( minusk ) {
695 if( qe->k == 0 ) { /* opening */
696 qe->k = 1;
697 }
698 else { /* closing, if no key; otherwise keep open */
699 if( key_length <= 1 ) {
700 qe->k = 0;
701 }
702 }
703 }
704
705 } /* if no error */
706
707 /* we don't need this anymore */
708 /* UT_free(tmp_query_str);*/
709 UT_free(gst);
710 g_strfreev(opt_argv);
711
712 if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
713 return QC_SYNERR;
714 }
715 else if(badparerr > 0) { /* the requester has a clue. No Usage info */
716 return QC_PARERR;
717 }
718 else {
719 return 0;
720 }
721 } /* QC_fill() */
722
723 /* QC_environ_new() */
724 /*++++++++++++++++++++++++++++++++++++++
725 Create a new query environment.
726
727 More:
728 +html+ <PRE>
729 Authors:
730 ottrey
731 +html+ </PRE><DL COMPACT>
732 +html+ <DT>Online References:
733 +html+ <DD><UL>
734 +html+ </UL></DL>
735
736 ++++++++++++++++++++++++++++++++++++++*/
737 Query_environ *QC_environ_new(char *ip, int sock) {
/* [<][>][^][v][top][bottom][index][help] */
738 Query_environ *qe;
739
740 qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ));
741 qe->condat.ip = ip;
742 qe->condat.sock = sock;
743
744 /* The source is initialized to include only the deflook sources */
745 {
746 int i;
747 ca_dbSource_t *hdl;
748
749 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
750 char *amrmrulez = ca_get_srcdeflook(hdl);
751 if( strcmp(amrmrulez, "y")==0 ) {
752 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
753 }
754 UT_free(amrmrulez);
755 }
756 }
757
758 return qe;
759
760 } /* QC_environ_new() */
761
762
763
764
765 /* QC_create() */
766 /*++++++++++++++++++++++++++++++++++++++
767 try to parse the query and fill in the QC struct, setting
768 qc->query_type accordingly.
769
770 Query_command *QC_create returns allocated structure
771
772 char *input user query
773
774 Query_environ *qe query environment structure
775
776 Author:
777 marek.
778
779 ++++++++++++++++++++++++++++++++++++++*/
780
781 Query_command *QC_create(char *input, Query_environ *qe)
/* [<][>][^][v][top][bottom][index][help] */
782 {
783 Query_command *qc;
784 /* allocate place for a copy of the input */
785 char *copy = UT_calloc(1,strlen(input)+1);
786 unsigned char *ci, *co;
787 int qt;
788 /* clean the string from junk - allow only known chars, something like
789 tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
790
791 strip leading spaces too
792 */
793
794 for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
795 /* EMPTY */
796 }
797
798 for(co = (unsigned char *) copy; *ci != 0; ci++) {
799 if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */
800 "abcdefghijklmnopqrstuvwxyz"
801 "0123456789-_:+=.,@/?' \n", *ci) != NULL) {
802 *(co++) = *ci;
803 }
804 }
805
806 /* now delete whitespace chars at the end */
807 while( co != (unsigned char *)copy /* don't read past the beginning */
808 && isspace(*co) ) {
809 *co = '\0';
810 co--;
811 }
812
813
814 qc = (Query_command *)UT_calloc(1, sizeof(Query_command));
815
816 if ( strlen(copy) == 0) {
817 /* An empty query (Ie return) was sent */
818 qc->query_type = QC_EMPTY;
819 }
820 else { /* else <==> input_length > 0 ) */
821 /* parse query */
822 qt = QC_fill(copy, qc, qe);
823
824 if( qt == QC_SYNERR || qt == QC_PARERR ) {
825 qc->query_type = qt;
826 }
827 else {
828 /* Update the query environment */
829 /* qe = QC_environ_update(qc, qe); */
830
831 /* Only do a query if there are keys. */
832 if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
833 if( strlen(qc->keys) == 0
834 && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
835 qc->query_type = QC_TEMPLATE;
836 }
837 else {
838 qc->query_type = QC_NOKEY;
839 }
840 }
841 else {
842 if ( strcmp(qc->keys, "HELP") == 0 ) {
843 qc->query_type = QC_HELP;
844 }
845 /* So, a real query */
846 else if( qc->filtered ) {
847 qc->query_type = QC_FILTERED;
848 }
849 else {
850 qc->query_type = QC_REAL;
851 }
852 }
853 }
854 }
855
856 UT_free(copy);
857
858 return qc;
859 }
860
861
862 /*++++++++++++++++++++++++++++++++++++++
863
864 Get the name of the given query type code.
865
866 char *QC_get_qrytype returns a pointer to an element of array of static strings
867
868 qc_qtype_t qrytype query type code
869
870 ++++++++++++++++++++++++++++++++++++++*/
871
872 char *QC_get_qrytype(qc_qtype_t qrytype) {
/* [<][>][^][v][top][bottom][index][help] */
873 dieif(qrytype >= QC_TYPE_MAX);
874
875 return qrytype_str[qrytype];
876 }