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)
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 | 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) {
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)
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) {
849 | dieif(qrytype >= QC_TYPE_MAX);
850 |
851 | return qrytype_str[qrytype];
852 | }