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