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