1 | /***************************************
2 | $Revision: 1.38 $
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)
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) {
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) {
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) {
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) {
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) {
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,
315 | Query_command *query_command,
316 | Query_environ *qe) {
317 |
318 | int c;
319 | int synerrflg = 0;
320 | int badparerr = 0;
321 | char *inv_attrs_str = NULL;
322 | char *object_types_str = NULL;
323 | int opt_argc;
324 | gchar **opt_argv;
325 | char *value;
326 | char *tmp_query_str;
327 | int key_length;
328 | int i;
329 | int index;
330 | int type;
331 | int attr;
332 | char str_buf[STR_XL];
333 | getopt_state_t *gst = NULL;
334 |
335 | query_command->e = 0;
336 | query_command->g = 0;
337 | query_command->inv_attrs_bitmap = MA_new(MA_END);
338 | query_command->recursive = 1; /* Recursion is on by default. */
339 | query_command->l = 0;
340 | query_command->m = 0;
341 | query_command->q = -1;
342 | query_command->t = -1;
343 | query_command->v = -1;
344 | query_command->x = 0;
345 | query_command->fast = 0;
346 | query_command->filtered = 0;
347 | query_command->L = 0;
348 | query_command->M = 0;
349 | query_command->R = 0;
350 | query_command->S = 0;
351 | query_command->object_type_bitmap = MA_new(MA_END);
352 | /*
353 | query_command->keytypes_bitmap = MA_new(MA_END);
354 | */
355 | query_command->keys = NULL;
356 |
357 | /* This is so Marek can't crash me :-) */
358 | /* Side Effect - query keys are subsequently cut short to STR_S size. */
359 |
360 | dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
361 | strncpy(tmp_query_str, query_str, STR_S);
362 |
363 | /* Create the arguments. */
364 | /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
365 | opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
366 |
367 | /* Determine the number of arguments. */
368 | for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
369 |
370 | dieif( (gst = mg_new(0)) == NULL );
371 |
372 | while ((c = mg_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:",
373 | gst)) != EOF) {
374 | switch (c) {
375 | case 'a':
376 | /* Remove any user specified sources from the sources list. */
377 | /* free the list only, do not touch the elements */
378 | g_list_free(qe->sources_list);
379 | qe->sources_list=NULL;
380 |
381 | /* Add all the config sources to the sources list. */
382 | {
383 | int i;
384 | ca_dbSource_t *hdl;
385 |
386 | for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
387 | qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
388 | }
389 | }
390 |
391 |
392 | break;
393 |
394 | case 'e':
395 | query_command->e=1;
396 | break;
397 |
398 | case 'g':
399 | query_command->g=1;
400 | break;
401 |
402 | case 'i':
403 | if (gst->optarg != NULL) {
404 | char *hackstr = NULL;
405 |
406 | inv_attrs_str = gst->optarg;
407 | /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
408 | /* I particularly object to this because it references attributes that should only be
409 | defined in XML - but I don't see a simplier more robust way of doing this hack.
410 | :-( - ottrey 8/12/99
411 | ** removed a memory leak - MB, 1/08/00
412 | */
413 | if ( strcmp(inv_attrs_str, "pn") == 0
414 | || strcmp(inv_attrs_str, "ro") == 0) {
415 | wr_malloc( (void **)& hackstr, 24); /* make a copy */
416 | strcpy(hackstr, "ac,tc,zc,ah");
417 | inv_attrs_str = hackstr;
418 | }
419 | while (*inv_attrs_str) {
420 | index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
421 | if (index == -1) {
422 | attr = -1;
423 | strcpy(str_buf, "");
424 | sprintf(str_buf, "Unknown attribute encountered.\n");
425 | SK_cd_puts(&(qe->condat), str_buf);
426 | badparerr++;
427 | }
428 | else {
429 | mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
430 | attr = DF_get_attribute_index(index);
431 | if ( MA_isset(inv_attr_mask, attr) == 1 ) {
432 | /* Add the attr to the bitmap. */
433 | MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
434 | }
435 | else {
436 | strcpy(str_buf, "");
437 | sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]);
438 | SK_cd_puts(&(qe->condat), str_buf);
439 | badparerr++;
440 | }
441 | }
442 | } /* while () */
443 |
444 | if( hackstr != NULL) {
445 | wr_free(hackstr);
446 | }
447 | } /* if () */
448 | break;
449 |
450 | case 'k':
451 | /* triggering flag == a XOR operation */
452 | qe->k ^= 1;
453 | break;
454 |
455 | case 'r':
456 | query_command->recursive=0; /* Unset recursion */
457 | break;
458 |
459 | case 'l':
460 | query_command->l=1;
461 | break;
462 |
463 | case 'm':
464 | query_command->m=1;
465 | break;
466 |
467 | case 'q':
468 | if (gst->optarg != NULL) {
469 | index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
470 | if (index == -1) {
471 | synerrflg++;
472 | }
473 | else {
474 | query_command->q = index;
475 | }
476 | } /* if () */
477 | break;
478 |
479 | case 's':
480 | if (gst->optarg != NULL) {
481 | char *token, *cursor = gst->optarg;
482 | ca_dbSource_t *handle;
483 |
484 | /* Remove any sources from the sources list. */
485 | g_list_free(qe->sources_list);
486 | qe->sources_list=NULL;
487 |
488 | /* go through specified sources */
489 | while( (token = strsep( &cursor, "," )) != NULL ) {
490 |
491 | if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
492 | /* append */
493 | qe->sources_list
494 | = g_list_append(qe->sources_list, (void *) handle );
495 | }
496 | else {
497 | /* bail out */
498 |
499 | SK_cd_printf(&(qe->condat),
500 | "%% Unknown source %s requested.\n",token );
501 |
502 | /* XXX error */
503 | badparerr++;
504 |
505 | } /* if handle not null */
506 | } /* while sources */
507 | } /* if argument present */
508 | break;
509 |
510 | case 't':
511 | if (gst->optarg != NULL) {
512 | object_types_str = gst->optarg;
513 | while (*object_types_str) {
514 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
515 | if (index == -1) {
516 | strcpy(str_buf, "");
517 | sprintf(str_buf, "Unknown object encountered.\n");
518 | SK_cd_puts(&(qe->condat), str_buf);
519 | badparerr++;
520 | }
521 | else {
522 | type = DF_get_class_index(index);
523 | query_command->t=type;
524 | }
525 | }
526 | }
527 | break;
528 |
529 | case 'v':
530 | if (gst->optarg != NULL) {
531 | object_types_str = gst->optarg;
532 | if (*object_types_str) {
533 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
534 | if (index == -1) {
535 | strcpy(str_buf, "");
536 | sprintf(str_buf, "Unknown object encountered.\n");
537 | SK_cd_puts(&(qe->condat), str_buf);
538 | badparerr++;
539 | }
540 | else {
541 | type = DF_get_class_index(index);
542 | query_command->v=type;
543 | }
544 | }
545 | }
546 | break;
547 |
548 | case 'x':
549 | query_command->x=1;
550 | break;
551 |
552 | case 'F':
553 | query_command->fast=1;
554 | query_command->recursive=0; /* implies no recursion */
555 | break;
556 |
557 | case 'K':
558 | query_command->filtered=1;
559 | query_command->recursive=0; /* implies no recursion */
560 | break;
561 |
562 | case 'L':
563 | query_command->L=1;
564 | break;
565 |
566 | case 'M':
567 | query_command->M=1;
568 | break;
569 |
570 | case 'R':
571 | query_command->R=1;
572 | break;
573 |
574 | case 'S':
575 | query_command->S=1;
576 | break;
577 |
578 | case 'T':
579 | if (gst->optarg != NULL) {
580 | object_types_str = gst->optarg;
581 | while (*object_types_str) {
582 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
583 | if (index == -1) {
584 | strcpy(str_buf, "");
585 | sprintf(str_buf, "Unknown obejct type encountered.\n");
586 | SK_cd_puts(&(qe->condat), str_buf);
587 | badparerr++;
588 | }
589 | else {
590 | type = DF_get_class_index(index);
591 | /* Add the type to the bitmap. */
592 | MA_set(&(query_command->object_type_bitmap), type, 1);
593 | }
594 | }
595 | }
596 | break;
597 |
598 | case 'V':
599 | if (qe->version != NULL) {
600 | /* free up the old client info */
601 | wr_free(qe->version);
602 | }
603 |
604 | {
605 | char *token, *cursor = gst->optarg;
606 | while( (token = strsep( &cursor, "," )) != NULL ) {
607 | if(IP_addr_e2b( & (qe->pIP), token)
608 | != IP_OK ) {
609 | /* means it was not an IP -> it was a version */
610 | dieif( wr_malloc( (void **)&(qe->version),
611 | strlen(token)+1) != UT_OK);
612 | strcpy(qe->version, token);
613 | }
614 | }
615 | }
616 | break;
617 |
618 | /* any other flag, including '?' and ':' errors */
619 | default:
620 | synerrflg++;
621 | }
622 | }
623 |
624 | /* copy the key */
625 |
626 | /* Work out the length of space needed */
627 | key_length = 1; /* for terminal '\0' */
628 | for (i=gst->optind ; i < opt_argc; i++) {
629 | /* length for the string + 1 for the '\0'+ 1 for the ' ' */
630 | if (opt_argv[i] != NULL) {
631 | key_length += strlen(opt_argv[i])+1;
632 | }
633 | }
634 | /* allocate */
635 | dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
636 | /* copy */
637 | for (i=gst->optind; i < opt_argc; i++) {
638 | strcat(query_command->keys, opt_argv[i]);
639 | if ( (i + 1) < opt_argc) {
640 | strcat(query_command->keys, " ");
641 | }
642 | }
643 |
644 | /* if no error, process the key, otherwise don't bother */
645 | if ( ! synerrflg && ! badparerr ) {
646 | /* convert the key to uppercase. */
647 | for (i=0; i <= key_length; i++) {
648 | query_command->keys[i] = toupper(query_command->keys[i]);
649 | }
650 |
651 | /* make the keytypes_bitmap. */
652 | query_command->keytypes_bitmap = WK_new(query_command->keys);
653 |
654 | /* tracing */
655 | log_command(tmp_query_str, query_command);
656 |
657 | } /* if no error */
658 |
659 | /* we don't need this anymore */
660 | wr_free(tmp_query_str);
661 | wr_free(gst);
662 |
663 | if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
664 | return QC_SYNERR;
665 | }
666 | else if(badparerr > 0) { /* the requester has a clue. No Usage info */
667 | return QC_PARERR;
668 | }
669 | else {
670 | return 0;
671 | }
672 | } /* QC_fill() */
673 |
674 | /* QC_environ_new() */
675 | /*++++++++++++++++++++++++++++++++++++++
676 | Create a new query environment.
677 |
678 | More:
679 | +html+ <PRE>
680 | Authors:
681 | ottrey
682 | +html+ </PRE><DL COMPACT>
683 | +html+ <DT>Online References:
684 | +html+ <DD><UL>
685 | +html+ </UL></DL>
686 |
687 | ++++++++++++++++++++++++++++++++++++++*/
688 | Query_environ *QC_environ_new(char *ip, unsigned sock) {
689 | Query_environ *qe;
690 |
691 |
692 | dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
693 | qe->condat.ip = ip;
694 | qe->condat.sock = sock;
695 |
696 | /* The source is initialized to include only the deflook sources */
697 | {
698 | int i;
699 | ca_dbSource_t *hdl;
700 |
701 | for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
702 | if( ca_get_srcdeflook(hdl) ) {
703 | qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
704 | }
705 | }
706 | }
707 |
708 | return qe;
709 |
710 | } /* QC_environ_new() */
711 |
712 |
713 |
714 | /*++ QC_create()
715 |
716 | try to parse the query and fill in the QC struct, setting
717 | qc->query_type accordingly.
718 |
719 | by marek.
720 | ++++++++++++++++++++++++++++++++++++++*/
721 | Query_command *QC_create(char *input, Query_environ *qe)
722 | {
723 | Query_command *qc;
724 | /* allocate place for a copy of the input */
725 | char *copy = calloc(1,strlen(input)+1);
726 | char *ci, *co;
727 | int qt;
728 | /* clean the string from junk - allow only known chars, something like
729 | tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
730 |
731 | strip leading spaces too
732 | */
733 |
734 | dieif(copy == NULL);
735 |
736 | for(ci = input; *ci != 0 && isspace(*ci); ci++) {
737 | /* EMPTY */
738 | }
739 |
740 | for(co = copy; *ci != 0; ci++) {
741 | if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */
742 | "abcdefghijklmnopqrstuvwxyz"
743 | "0123456789-_:+=.,@/' \n", *ci) != NULL) {
744 | *(co++) = *ci;
745 | }
746 | }
747 |
748 | /* now delete whitespace chars at the end */
749 | co--;
750 | while( isspace(*co) ) {
751 | *co = '\0';
752 | co--;
753 | }
754 |
755 |
756 | dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
757 |
758 | if ( strlen(copy) == 0) {
759 | /* An empty query (Ie return) was sent */
760 | qc->query_type = QC_EMPTY;
761 | }
762 | else { /* else <==> input_length > 0 ) */
763 | /* parse query */
764 | qt = QC_fill(copy, qc, qe);
765 |
766 | if( qt == QC_SYNERR || qt == QC_PARERR ) {
767 | qc->query_type = qt;
768 | }
769 | else {
770 | /* Update the query environment */
771 | /* qe = QC_environ_update(qc, qe); */
772 |
773 | /* Only do a query if there are keys. */
774 | if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
775 | if( strlen(qc->keys) == 0
776 | && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
777 | qc->query_type = QC_TEMPLATE;
778 | }
779 | else {
780 | qc->query_type = QC_NOKEY;
781 | }
782 | }
783 | else {
784 | if ( strcmp(qc->keys, "HELP") == 0 ) {
785 | qc->query_type = QC_HELP;
786 | }
787 | /* So, a real query */
788 | else if( qc->filtered ) {
789 | qc->query_type = QC_FILTERED;
790 | }
791 | else {
792 | qc->query_type = QC_REAL;
793 | }
794 | }
795 | }
796 | }
797 |
798 | free(copy);
799 |
800 | return qc;
801 | }
802 |
803 |
804 | char *QC_get_qrytype(qc_qtype_t qrytype) {
805 | dieif(qrytype >= QC_TYPE_MAX);
806 |
807 | return qrytype_str[qrytype];
808 | }