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.56 $
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,2002 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, (c=%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->c_irt_search ? "TRUE" : "FALSE",
172 query_command->e,
173 query_command->g,
174 query_command->l,
175 query_command->m,
176 query_command->q,
177 query_command->t,
178 query_command->v,
179 query_command->x,
180 query_command->fast,
181 query_command->filtered,
182 query_command->L,
183 query_command->M,
184 query_command->R,
185 query_command->S,
186 str3,
187 query_command->keys);
188 UT_free(str1);
189 UT_free(str2);
190 UT_free(str3);
191
192 return UT_strdup(result_buf);
193
194 } /* QC_query_command_to_string() */
195
196 /* log_command() */
197 /*++++++++++++++++++++++++++++++++++++++
198 Log the command.
199 This is more to do with Tracing. And should/will get merged with a tracing
200 module (when it is finalized.)
201
202 char *query_str
203
204 Query_command *query_command
205
206 More:
207 +html+ <PRE>
208 Authors:
209 ottrey
210 +html+ </PRE><DL COMPACT>
211 +html+ <DT>Online References:
212 +html+ <DD><UL>
213 +html+ </UL></DL>
214
215 ++++++++++++++++++++++++++++++++++++++*/
216 static void log_command(char *query_str, Query_command *query_command) {
/* [<][>][^][v][top][bottom][index][help] */
217 char *str;
218
219 if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
220 str = QC_query_command_to_string(query_command);
221 ER_dbg_va(FAC_QC, ASP_QC_BUILD,
222 "query=[%s] %s", query_str, str);
223 UT_free(str);
224 }
225 } /* log_command() */
226
227 /* QC_environ_free() */
228 /*++++++++++++++++++++++++++++++++++++++
229 Free the query_environ.
230
231 Query_command *qc query_environ to be freed.
232
233 More:
234 +html+ <PRE>
235 Authors:
236 ottrey
237 +html+ </PRE><DL COMPACT>
238 +html+ <DT>Online References:
239 +html+ <DD><UL>
240 +html+ </UL></DL>
241
242 ++++++++++++++++++++++++++++++++++++++*/
243 void QC_environ_free(Query_environ *qe) {
/* [<][>][^][v][top][bottom][index][help] */
244 if (qe != NULL) {
245 if (qe->version != NULL) {
246 UT_free(qe->version);
247 }
248
249 if (qe->sources_list != NULL) {
250 g_list_free(qe->sources_list);
251 qe->sources_list=NULL;
252 }
253 UT_free(qe);
254 }
255 } /* QC_environ_free() */
256
257 /* QC_free() */
258 /*++++++++++++++++++++++++++++++++++++++
259 Free the query_command.
260
261 Query_command *qc query_command to be freed.
262
263 XXX I'm not sure the bitmaps will get freed.
264 qc->inv_attrs_bitmap
265 qc->object_type_bitmap
266 qc->keytypes_bitmap
267
268 More:
269 +html+ <PRE>
270 Authors:
271 ottrey
272 +html+ </PRE><DL COMPACT>
273 +html+ <DT>Online References:
274 +html+ <DD><UL>
275 +html+ </UL></DL>
276
277 ++++++++++++++++++++++++++++++++++++++*/
278 void QC_free(Query_command *qc) {
/* [<][>][^][v][top][bottom][index][help] */
279 if (qc != NULL) {
280 if (qc->keys != NULL) {
281 UT_free(qc->keys);
282 }
283 UT_free(qc);
284 }
285 } /* QC_free() */
286
287
288
289 /* QC_fill() */
290 /*++++++++++++++++++++++++++++++++++++++
291 Create a new query_command.
292 Returns 0 when OK, -1 when query incorrect.
293
294 char *query_str The garden variety whois query string.
295
296 Query_environ *qe the environment
297
298 More:
299 +html+ <PRE>
300 Authors:
301 ottrey - original code
302 marek - modified for my getopts, multiple sources;
303 and generally cleaned.
304 +html+ </PRE><DL COMPACT>
305 +html+ <DT>Online References:
306 +html+ <DD><UL>
307 +html+ </UL></DL>
308
309 ++++++++++++++++++++++++++++++++++++++*/
310 static
311 int QC_fill(char *query_str,
/* [<][>][^][v][top][bottom][index][help] */
312 Query_command *query_command,
313 Query_environ *qe) {
314
315 int c;
316 int synerrflg = 0;
317 int badparerr = 0;
318 int minusk = 0;
319 char *inv_attrs_str = NULL;
320 char *object_types_str = NULL;
321 int opt_argc;
322 gchar **opt_argv;
323 char *value;
324 /* char *tmp_query_str;*/
325 unsigned key_length;
326 int i;
327 int index;
328 C_Type_t type;
329 A_Type_t attr;
330 getopt_state_t *gst = NULL;
331
332 query_command->c_irt_search = FALSE;
333 query_command->d = 0;
334 query_command->e = 0;
335 query_command->g = 0;
336 query_command->inv_attrs_bitmap = MA_new(MA_END);
337 query_command->recursive = 1; /* Recursion is on by default. */
338 query_command->l = 0;
339 query_command->m = 0;
340 query_command->q = -1;
341 query_command->t = -1;
342 query_command->v = -1;
343 query_command->x = 0;
344 query_command->fast = 0;
345 query_command->filtered = 0;
346 query_command->L = 0;
347 query_command->M = 0;
348 query_command->R = 0;
349 query_command->S = 0;
350
351 /* XXX UGLY - "all zeros" in object_type_bitmap means the same as
352 "all ones". To limit the inconsistency, this is changed at the end
353 of this function, so outside "all zeros" is an illegal value. */
354 query_command->object_type_bitmap = MA_new(MA_END);
355 /*
356 query_command->keytypes_bitmap = MA_new(MA_END);
357 */
358 query_command->keys = NULL;
359
360 /* This is so Marek can't crash me :-) */
361 /* Side Effect - query keys are subsequently cut short to STR_S size. */
362
363 /* tmp_query_str = (char *)UT_calloc(1, STR_S+1);
364 strncpy(tmp_query_str, query_str, STR_S);*/
365
366 /* Create the arguments. */
367 /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
368 /* opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);*/
369 opt_argv = g_strsplit(query_str, " ", MAX_OPT_ARG_C);
370
371 /* Determine the number of arguments. */
372 for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
373
374 dieif( (gst = mg_new(0)) == NULL );
375
376 while ((c = mg_getopt(opt_argc, opt_argv, "acdegi:klrmq:s:t:v:xFKLMRST:V:",
377 gst)) != EOF) {
378 switch (c) {
379 case 'a':
380 /* Remove any user specified sources from the sources list. */
381 /* free the list only, do not touch the elements */
382 g_list_free(qe->sources_list);
383 qe->sources_list=NULL;
384
385 /* Add all the config sources to the sources list. */
386 {
387 int i;
388 ca_dbSource_t *hdl;
389
390 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
391 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
392 }
393 }
394
395
396 break;
397
398 case 'c':
399 query_command->c_irt_search = TRUE;
400 break;
401
402 case 'e':
403 query_command->e=1;
404 break;
405
406 case 'd':
407 query_command->d=1;
408 break;
409
410 case 'g':
411 query_command->g=1;
412 break;
413
414 case 'i':
415 if (gst->optarg != NULL) {
416 char *hackstr = NULL;
417
418 inv_attrs_str = gst->optarg;
419 /*
420 Now a really stupid hard-coded hack to support "pn" being a
421 synonym for "ac,tc,zc,ah". I particularly object to this because
422 it references attributes that should only be defined in XML - but
423 I don't see a simplier more robust way of doing this hack.
424 :-( - ottrey 8/12/99
425
426 ** removed a memory leak - MB, 1/08/00
427
428 ** removed the use of "ro", added "person" - shane, 2002-01-23
429
430 */
431 if ( strcmp(inv_attrs_str, "pn") == 0
432 || strcmp(inv_attrs_str, "person") == 0) {
433 hackstr = UT_strdup("ac,tc,zc,ah,cn");
434 inv_attrs_str = hackstr;
435 }
436 while (*inv_attrs_str) {
437 index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
438 if (index == -1) {
439 /* Unknown attribute encountered. */
440 char *rep = ca_get_qc_badattr ;
441 SK_cd_puts(&(qe->condat), rep);
442 UT_free(rep);
443
444 attr = -1;
445 badparerr++;
446 }
447 else {
448 mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
449 attr = DF_get_attribute_index(index);
450 if ( MA_isset(inv_attr_mask, attr) == 1 ) {
451 /* Add the attr to the bitmap. */
452 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
453 }
454 else {
455 /* "%s" is not an inverse searchable attribute. */
456 char *rep = ca_get_qc_fmt_attrnotinv ;
457 SK_cd_printf(&(qe->condat), rep,
458 (DF_get_attribute_aliases())[index]);
459 UT_free(rep);
460 badparerr++;
461 }
462 }
463 } /* while () */
464
465 if( hackstr != NULL) {
466 UT_free(hackstr);
467 }
468 } /* if () */
469 break;
470
471 case 'k':
472 minusk = 1;
473 break;
474
475 case 'r':
476 query_command->recursive=0; /* Unset recursion */
477 break;
478
479 case 'l':
480 query_command->l=1;
481 break;
482
483 case 'm':
484 query_command->m=1;
485 break;
486
487 case 'q':
488 if (gst->optarg != NULL) {
489 index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
490 if (index == -1) {
491 synerrflg++;
492 }
493 else {
494 query_command->q = index;
495 }
496 } /* if () */
497 break;
498
499 case 's':
500 if (gst->optarg != NULL) {
501 char *token, *cursor = gst->optarg;
502 ca_dbSource_t *handle;
503
504 /* Remove any sources from the sources list. */
505 g_list_free(qe->sources_list);
506 qe->sources_list=NULL;
507
508 /* go through specified sources */
509 while( (token = strsep( &cursor, "," )) != NULL ) {
510
511 if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
512 /* append */
513 qe->sources_list
514 = g_list_append(qe->sources_list, (void *) handle );
515 }
516 else {
517 /* bail out */
518
519 /* Unknown source %s requested. */
520 char *rep = ca_get_qc_fmt_badsource ;
521 SK_cd_printf(&(qe->condat), rep, token );
522 UT_free(rep);
523
524 /* XXX error */
525 badparerr++;
526
527 } /* if handle not null */
528 } /* while sources */
529 } /* if argument present */
530 break;
531
532 case 't':
533 if (gst->optarg != NULL) {
534 object_types_str = gst->optarg;
535 while (*object_types_str) {
536 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
537 if (index == -1) {
538 /* Unknown object type encountered */
539 char *rep = ca_get_qc_badobjtype ;
540 SK_cd_puts(&(qe->condat), rep);
541 UT_free(rep);
542 badparerr++;
543 }
544 else {
545 type = DF_get_class_index(index);
546 query_command->t=type;
547 }
548 }
549 }
550 break;
551
552 case 'v':
553 if (gst->optarg != NULL) {
554 object_types_str = gst->optarg;
555 if (*object_types_str) {
556 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
557 if (index == -1) {
558 /* Unknown object type encountered */
559 char *rep = ca_get_qc_badobjtype ;
560 SK_cd_puts(&(qe->condat), rep);
561 UT_free(rep);
562 badparerr++;
563 }
564 else {
565 type = DF_get_class_index(index);
566 query_command->v=type;
567 }
568 }
569 }
570 break;
571
572 case 'x':
573 query_command->x=1;
574 break;
575
576 case 'F':
577 query_command->fast=1;
578 query_command->recursive=0; /* implies no recursion */
579 break;
580
581 case 'K':
582 query_command->filtered=1;
583 query_command->recursive=0; /* implies no recursion */
584 break;
585
586 case 'L':
587 query_command->L=1;
588 break;
589
590 case 'M':
591 query_command->M=1;
592 break;
593
594 case 'R':
595 query_command->R=1;
596 break;
597
598 case 'S':
599 query_command->S=1;
600 break;
601
602 case 'T':
603 if (gst->optarg != NULL) {
604 /* parse the specification */
605 object_types_str = gst->optarg;
606 while (*object_types_str) {
607 index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
608 if (index == -1) {
609 /* Unknown object type encountered */
610 char *rep = ca_get_qc_badobjtype ;
611 SK_cd_puts(&(qe->condat), rep);
612 UT_free(rep);
613 badparerr++;
614 }
615 else {
616 type = DF_get_class_index(index);
617 /* Add the type to the bitmap. */
618 MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
619 }
620 }
621 }
622 break;
623
624 case 'V':
625 if (qe->version != NULL) {
626 /* free up the old client info */
627 UT_free(qe->version);
628 }
629
630 {
631 char *token, *cursor = gst->optarg;
632 while( (token = strsep( &cursor, "," )) != NULL ) {
633 if(IP_addr_e2b( & (qe->pIP), token)
634 != IP_OK ) {
635 /* means it was not an IP -> it was a version */
636 qe->version = UT_strdup(token);
637 }
638 }
639 }
640 break;
641
642 /* any other flag, including '?' and ':' errors */
643 default:
644 synerrflg++;
645 }
646 }
647
648 /* copy the key */
649
650 /* Work out the length of space needed */
651 key_length = 1; /* for terminal '\0' */
652 for (i=gst->optind ; i < opt_argc; i++) {
653 /* length for the string + 1 for the '\0'+ 1 for the ' ' */
654 if (opt_argv[i] != NULL) {
655 key_length += strlen(opt_argv[i])+1;
656 }
657 }
658 /* allocate */
659 query_command->keys = (char *)UT_calloc(1, key_length+1);
660
661 /* copy */
662 for (i=gst->optind; i < opt_argc; i++) {
663 strcat(query_command->keys, opt_argv[i]);
664 if ( (i + 1) < opt_argc) {
665 strcat(query_command->keys, " ");
666 }
667 }
668
669 /* if no error, process the key, otherwise don't bother */
670 if ( ! synerrflg && ! badparerr ) {
671 /* convert the key to uppercase. */
672 for (i=0; i <= key_length; i++) {
673 query_command->keys[i] = toupper(query_command->keys[i]);
674 }
675
676 /* make the keytypes_bitmap. */
677 query_command->keytypes_bitmap = WK_new(query_command->keys);
678
679 /* fix the object type bitmap - turn "all zeros" into "all ones" */
680 if( MA_bitcount(query_command->object_type_bitmap) == 0 ) {
681 query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap);
682 }
683
684 /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then
685 exclude the domains unless -d is set
686 XXX this must be kept in sync with new types */
687 if( query_command->d == 0
688 && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS)
689 || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE )
690 || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX )
691 || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX )
692 ) ) {
693
694 MA_set(&(query_command->object_type_bitmap), C_DN , 0);
695 }
696
697 /* tracing */
698 /* log_command(tmp_query_str, query_command);*/
699 log_command(query_str, query_command);
700
701 /* "keep connection" processing:
702 when opening connection, -k may be alone or with a query
703 later -k must appear alone (or there must be an empty line,
704 or an error) for the connection to close.
705 */
706 if( minusk ) {
707 if( qe->k == 0 ) { /* opening */
708 qe->k = 1;
709 }
710 else { /* closing, if no key; otherwise keep open */
711 if( key_length <= 1 ) {
712 qe->k = 0;
713 }
714 }
715 }
716
717 } /* if no error */
718
719 /* we don't need this anymore */
720 /* UT_free(tmp_query_str);*/
721 UT_free(gst);
722 g_strfreev(opt_argv);
723
724 if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
725 return QC_SYNERR;
726 }
727 else if(badparerr > 0) { /* the requester has a clue. No Usage info */
728 return QC_PARERR;
729 }
730 else {
731 return 0;
732 }
733 } /* QC_fill() */
734
735 /* QC_environ_new() */
736 /*++++++++++++++++++++++++++++++++++++++
737 Create a new query environment.
738
739 More:
740 +html+ <PRE>
741 Authors:
742 ottrey
743 +html+ </PRE><DL COMPACT>
744 +html+ <DT>Online References:
745 +html+ <DD><UL>
746 +html+ </UL></DL>
747
748 ++++++++++++++++++++++++++++++++++++++*/
749 Query_environ *QC_environ_new(char *ip, int sock) {
/* [<][>][^][v][top][bottom][index][help] */
750 Query_environ *qe;
751
752 qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ));
753 qe->condat.ip = ip;
754 qe->condat.sock = sock;
755
756 /* The source is initialized to include only the deflook sources */
757 {
758 int i;
759 ca_dbSource_t *hdl;
760
761 for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
762 char *amrmrulez = ca_get_srcdeflook(hdl);
763 if( strcmp(amrmrulez, "y")==0 ) {
764 qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
765 }
766 UT_free(amrmrulez);
767 }
768 }
769
770 return qe;
771
772 } /* QC_environ_new() */
773
774
775
776
777 /* QC_create() */
778 /*++++++++++++++++++++++++++++++++++++++
779 try to parse the query and fill in the QC struct, setting
780 qc->query_type accordingly.
781
782 Query_command *QC_create returns allocated structure
783
784 char *input user query
785
786 Query_environ *qe query environment structure
787
788 Author:
789 marek.
790
791 ++++++++++++++++++++++++++++++++++++++*/
792
793 Query_command *QC_create(char *input, Query_environ *qe)
/* [<][>][^][v][top][bottom][index][help] */
794 {
795 Query_command *qc;
796 /* allocate place for a copy of the input */
797 char *copy = UT_calloc(1,strlen(input)+1);
798 unsigned char *ci, *co;
799 int qt;
800 /* clean the string from junk - allow only known chars, something like
801 tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
802
803 strip leading spaces too
804 */
805
806 for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
807 /* EMPTY */
808 }
809
810 for(co = (unsigned char *) copy; *ci != 0; ci++) {
811 if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */
812 "abcdefghijklmnopqrstuvwxyz"
813 "0123456789-_:+=.,@/?' \n", *ci) != NULL) {
814 *(co++) = *ci;
815 }
816 }
817
818 /* now delete whitespace chars at the end */
819 while( co != (unsigned char *)copy /* don't read past the beginning */
820 && isspace(*co) ) {
821 *co = '\0';
822 co--;
823 }
824
825
826 qc = (Query_command *)UT_calloc(1, sizeof(Query_command));
827
828 if ( strlen(copy) == 0) {
829 /* An empty query (Ie return) was sent */
830 qc->query_type = QC_EMPTY;
831 }
832 else { /* else <==> input_length > 0 ) */
833 /* parse query */
834 qt = QC_fill(copy, qc, qe);
835
836 if( qt == QC_SYNERR || qt == QC_PARERR ) {
837 qc->query_type = qt;
838 }
839 else {
840 /* Update the query environment */
841 /* qe = QC_environ_update(qc, qe); */
842
843 /* Only do a query if there are keys. */
844 if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
845 if( strlen(qc->keys) == 0
846 && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
847 qc->query_type = QC_TEMPLATE;
848 }
849 else {
850 qc->query_type = QC_NOKEY;
851 }
852 }
853 else {
854 if ( strcmp(qc->keys, "HELP") == 0 ) {
855 qc->query_type = QC_HELP;
856 }
857 /* So, a real query */
858 else if( qc->filtered ) {
859 qc->query_type = QC_FILTERED;
860 }
861 else {
862 qc->query_type = QC_REAL;
863 }
864 }
865 }
866 }
867
868 UT_free(copy);
869
870 return qc;
871 }
872
873
874 /*++++++++++++++++++++++++++++++++++++++
875
876 Get the name of the given query type code.
877
878 char *QC_get_qrytype returns a pointer to an element of array of static strings
879
880 qc_qtype_t qrytype query type code
881
882 ++++++++++++++++++++++++++++++++++++++*/
883
884 char *QC_get_qrytype(qc_qtype_t qrytype) {
/* [<][>][^][v][top][bottom][index][help] */
885 dieif(qrytype >= QC_TYPE_MAX);
886
887 return qrytype_str[qrytype];
888 }