1 | /***************************************
2 | $Revision: 1.48 $
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_dictionary.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 | /*++++++++++++++++++++++++++++++++++++++
64 | make a list of sources. expects list to hold source handles
65 |
66 | char *
67 | qc_sources_list_to_string returns an allocated string, must be freed
68 |
69 | GList *list list of source handles (as defined by CA)
70 |
71 | ++++++++++++++++++++++++++++++++++++++*/
72 | char *
73 | qc_sources_list_to_string(GList *list)
74 | {
75 | char *result = NULL;
76 | int oldlen = 0;
77 | GList *qitem;
78 |
79 | for( qitem = g_list_first(list);
80 | qitem != NULL;
81 | qitem = g_list_next(qitem)) {
82 | ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data );
83 | char *srcname = ca_get_srcname( source_hdl );
84 |
85 | dieif( wr_realloc( (void **)& result, oldlen + strlen(srcname) + 2)
86 | != UT_OK);
87 | if(oldlen > 0) {
88 | strcat(result, ",");
89 | }
90 | strcat(result, srcname);
91 | }
92 |
93 | return result;
94 | }
95 |
96 | /* QC_environ_to_string() */
97 | /*++++++++++++++++++++++++++++++++++++++
98 | Convert the query_environ to a string.
99 |
100 | Query_environ *query_environ The query_environ to be converted.
101 |
102 | More:
103 | +html+ <PRE>
104 | Authors:
105 | ottrey
106 | +html+ </PRE><DL COMPACT>
107 | +html+ <DT>Online References:
108 | +html+ <DD><UL>
109 | +html+ </UL></DL>
110 |
111 | ++++++++++++++++++++++++++++++++++++++*/
112 | char *QC_environ_to_string(Query_environ qe) {
113 | char *result;
114 | char *str1;
115 | char str2[IP_ADDRSTR_MAX];
116 | char result_buf[STR_XL];
117 |
118 | str1 = qc_sources_list_to_string(qe.sources_list);
119 |
120 | if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) {
121 | *str2 = '\0';
122 | }
123 |
124 | sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip,
125 | qe.k?"on":"off",
126 | str1,
127 | (qe.version == NULL) ? "?" : qe.version,
128 | *str2 == '\0' ? "" : ", passedIP=",
129 | *str2 == '\0' ? "" : str2
130 | );
131 |
132 | wr_free(str1);
133 |
134 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
135 |
136 | strcpy(result, result_buf);
137 |
138 | return result;
139 |
140 | } /* QC_environ_to_string() */
141 |
142 | /* QC_query_command_to_string() */
143 | /*++++++++++++++++++++++++++++++++++++++
144 | Convert the query_command to a string.
145 |
146 | Query_command *query_command The query_command to be converted.
147 |
148 | More:
149 | +html+ <PRE>
150 | Authors:
151 | ottrey
152 | +html+ </PRE><DL COMPACT>
153 | +html+ <DT>Online References:
154 | +html+ <DD><UL>
155 | +html+ </UL></DL>
156 |
157 | ++++++++++++++++++++++++++++++++++++++*/
158 | char *QC_query_command_to_string(Query_command *query_command) {
159 | char *result;
160 | char result_buf[STR_XL];
161 | char *str1;
162 | char *str2;
163 | char *str3;
164 |
165 | str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
166 | str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
167 | str3 = WK_to_string(query_command->keytypes_bitmap);
168 |
169 | 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]",
170 | str1,
171 | query_command->recursive?"y":"n",
172 | str2,
173 | query_command->e,
174 | query_command->g,
175 | query_command->l,
176 | query_command->m,
177 | query_command->q,
178 | query_command->t,
179 | query_command->v,
180 | query_command->x,
181 | query_command->fast,
182 | query_command->filtered,
183 | query_command->L,
184 | query_command->M,
185 | query_command->R,
186 | query_command->S,
187 | str3,
188 | query_command->keys);
189 | wr_free(str1);
190 | wr_free(str2);
191 | wr_free(str3);
192 |
193 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
194 | strcpy(result, result_buf);
195 |
196 | return result;
197 |
198 | } /* QC_query_command_to_string() */
199 |
200 | /* log_command() */
201 | /*++++++++++++++++++++++++++++++++++++++
202 | Log the command.
203 | This is more to do with Tracing. And should/will get merged with a tracing
204 | module (when it is finalized.)
205 |
206 | char *query_str
207 |
208 | Query_command *query_command
209 |
210 | More:
211 | +html+ <PRE>
212 | Authors:
213 | ottrey
214 | +html+ </PRE><DL COMPACT>
215 | +html+ <DT>Online References:
216 | +html+ <DD><UL>
217 | +html+ </UL></DL>
218 |
219 | ++++++++++++++++++++++++++++++++++++++*/
220 | static void log_command(char *query_str, Query_command *query_command) {
221 | char *str;
222 |
223 | if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
224 | str = QC_query_command_to_string(query_command);
225 | ER_dbg_va(FAC_QC, ASP_QC_BUILD,
226 | "query=[%s] %s", query_str, str);
227 | wr_free(str);
228 | }
229 | } /* log_command() */
230 |
231 | /* QC_environ_free() */
232 | /*++++++++++++++++++++++++++++++++++++++
233 | Free the query_environ.
234 |
235 | Query_command *qc query_environ to be freed.
236 |
237 | More:
238 | +html+ <PRE>
239 | Authors:
240 | ottrey
241 | +html+ </PRE><DL COMPACT>
242 | +html+ <DT>Online References:
243 | +html+ <DD><UL>
244 | +html+ </UL></DL>
245 |
246 | ++++++++++++++++++++++++++++++++++++++*/
247 | void QC_environ_free(Query_environ *qe) {
248 | if (qe != NULL) {
249 | if (qe->version != NULL) {
250 | wr_free(qe->version);
251 | }
252 |
253 | if (qe->sources_list != NULL) {
254 | g_list_free(qe->sources_list);
255 | qe->sources_list=NULL;
256 | }
257 | wr_free(qe);
258 | }
259 | } /* QC_environ_free() */
260 |
261 | /* QC_free() */
262 | /*++++++++++++++++++++++++++++++++++++++
263 | Free the query_command.
264 |
265 | Query_command *qc query_command to be freed.
266 |
267 | XXX I'm not sure the bitmaps will get freed.
268 | qc->inv_attrs_bitmap
269 | qc->object_type_bitmap
270 | qc->keytypes_bitmap
271 |
272 | More:
273 | +html+ <PRE>
274 | Authors:
275 | ottrey
276 | +html+ </PRE><DL COMPACT>
277 | +html+ <DT>Online References:
278 | +html+ <DD><UL>
279 | +html+ </UL></DL>
280 |
281 | ++++++++++++++++++++++++++++++++++++++*/
282 | void QC_free(Query_command *qc) {
283 | if (qc != NULL) {
284 | if (qc->keys != NULL) {
285 | wr_free(qc->keys);
286 | }
287 | wr_free(qc);
288 | }
289 | } /* QC_free() */
290 |
291 |
292 |
293 | /* QC_fill() */
294 | /*++++++++++++++++++++++++++++++++++++++
295 | Create a new query_command.
296 | Returns 0 when OK, -1 when query incorrect.
297 |
298 | char *query_str The garden variety whois query string.
299 |
300 | Query_environ *qe the environment
301 |
302 | More:
303 | +html+ <PRE>
304 | Authors:
305 | ottrey - original code
306 | marek - modified for my getopts, multiple sources;
307 | and generally cleaned.
308 | +html+ </PRE><DL COMPACT>
309 | +html+ <DT>Online References:
310 | +html+ <DD><UL>
311 | +html+ </UL></DL>
312 |
313 | ++++++++++++++++++++++++++++++++++++++*/
314 | static
315 | int QC_fill(char *query_str,
316 | Query_command *query_command,
317 | Query_environ *qe) {
318 |
319 | int c;
320 | int synerrflg = 0;
321 | int badparerr = 0;
322 | int minusk = 0;
323 | char *inv_attrs_str = NULL;
324 | char *object_types_str = NULL;
325 | int opt_argc;
326 | gchar **opt_argv;
327 | char *value;
328 | char *tmp_query_str;
329 | unsigned key_length;
330 | int i;
331 | int index;
332 | C_Type_t type;
333 | A_Type_t attr;
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 | /* Unknown attribute encountered. */
433 | char *rep = ca_get_qc_badattr ;
434 | SK_cd_puts(&(qe->condat), rep);
435 | wr_free(rep);
436 |
437 | attr = -1;
438 | badparerr++;
439 | }
440 | else {
441 | mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
442 | attr = DF_get_attribute_index(index);
443 | if ( MA_isset(inv_attr_mask, attr) == 1 ) {
444 | /* Add the attr to the bitmap. */
445 | MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
446 | }
447 | else {
448 | /* "%s" is not an inverse searchable attribute. */
449 | char *rep = ca_get_qc_fmt_attrnotinv ;
450 | SK_cd_printf(&(qe->condat), rep,
451 | (DF_get_attribute_aliases())[index]);
452 | wr_free(rep);
453 | badparerr++;
454 | }
455 | }
456 | } /* while () */
457 |
458 | if( hackstr != NULL) {
459 | wr_free(hackstr);
460 | }
461 | } /* if () */
462 | break;
463 |
464 | case 'k':
465 | minusk = 1;
466 | break;
467 |
468 | case 'r':
469 | query_command->recursive=0; /* Unset recursion */
470 | break;
471 |
472 | case 'l':
473 | query_command->l=1;
474 | break;
475 |
476 | case 'm':
477 | query_command->m=1;
478 | break;
479 |
480 | case 'q':
481 | if (gst->optarg != NULL) {
482 | index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
483 | if (index == -1) {
484 | synerrflg++;
485 | }
486 | else {
487 | query_command->q = index;
488 | }
489 | } /* if () */
490 | break;
491 |
492 | case 's':
493 | if (gst->optarg != NULL) {
494 | char *token, *cursor = gst->optarg;
495 | ca_dbSource_t *handle;
496 |
497 | /* Remove any sources from the sources list. */
498 | g_list_free(qe->sources_list);
499 | qe->sources_list=NULL;
500 |
501 | /* go through specified sources */
502 | while( (token = strsep( &cursor, "," )) != NULL ) {
503 |
504 | if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
505 | /* append */
506 | qe->sources_list
507 | = g_list_append(qe->sources_list, (void *) handle );
508 | }
509 | else {
510 | /* bail out */
511 |
512 | /* Unknown source %s requested. */
513 | char *rep = ca_get_qc_fmt_badsource ;
514 | SK_cd_printf(&(qe->condat), rep, token );
515 | wr_free(rep);
516 |
517 | /* XXX error */
518 | badparerr++;
519 |
520 | } /* if handle not null */
521 | } /* while sources */
522 | } /* if argument present */
523 | break;
524 |
525 | case 't':
526 | if (gst->optarg != NULL) {
527 | object_types_str = gst->optarg;
528 | while (*object_types_str) {
529 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
530 | if (index == -1) {
531 | /* Unknown object type encountered */
532 | char *rep = ca_get_qc_badobjtype ;
533 | SK_cd_puts(&(qe->condat), rep);
534 | wr_free(rep);
535 | badparerr++;
536 | }
537 | else {
538 | type = DF_get_class_index(index);
539 | query_command->t=type;
540 | }
541 | }
542 | }
543 | break;
544 |
545 | case 'v':
546 | if (gst->optarg != NULL) {
547 | object_types_str = gst->optarg;
548 | if (*object_types_str) {
549 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
550 | if (index == -1) {
551 | /* Unknown object type encountered */
552 | char *rep = ca_get_qc_badobjtype ;
553 | SK_cd_puts(&(qe->condat), rep);
554 | wr_free(rep);
555 | badparerr++;
556 | }
557 | else {
558 | type = DF_get_class_index(index);
559 | query_command->v=type;
560 | }
561 | }
562 | }
563 | break;
564 |
565 | case 'x':
566 | query_command->x=1;
567 | break;
568 |
569 | case 'F':
570 | query_command->fast=1;
571 | query_command->recursive=0; /* implies no recursion */
572 | break;
573 |
574 | case 'K':
575 | query_command->filtered=1;
576 | query_command->recursive=0; /* implies no recursion */
577 | break;
578 |
579 | case 'L':
580 | query_command->L=1;
581 | break;
582 |
583 | case 'M':
584 | query_command->M=1;
585 | break;
586 |
587 | case 'R':
588 | query_command->R=1;
589 | break;
590 |
591 | case 'S':
592 | query_command->S=1;
593 | break;
594 |
595 | case 'T':
596 | if (gst->optarg != NULL) {
597 | /* parse the specification */
598 | object_types_str = gst->optarg;
599 | while (*object_types_str) {
600 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
601 | if (index == -1) {
602 | /* Unknown object type encountered */
603 | char *rep = ca_get_qc_badobjtype ;
604 | SK_cd_puts(&(qe->condat), rep);
605 | wr_free(rep);
606 | badparerr++;
607 | }
608 | else {
609 | type = DF_get_class_index(index);
610 | /* Add the type to the bitmap. */
611 | MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
612 | }
613 | }
614 | }
615 | break;
616 |
617 | case 'V':
618 | if (qe->version != NULL) {
619 | /* free up the old client info */
620 | wr_free(qe->version);
621 | }
622 |
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 | dieif( wr_malloc( (void **)&(qe->version),
630 | strlen(token)+1) != UT_OK);
631 | strcpy(qe->version, token);
632 | }
633 | }
634 | }
635 | break;
636 |
637 | /* any other flag, including '?' and ':' errors */
638 | default:
639 | synerrflg++;
640 | }
641 | }
642 |
643 | /* copy the key */
644 |
645 | /* Work out the length of space needed */
646 | key_length = 1; /* for terminal '\0' */
647 | for (i=gst->optind ; i < opt_argc; i++) {
648 | /* length for the string + 1 for the '\0'+ 1 for the ' ' */
649 | if (opt_argv[i] != NULL) {
650 | key_length += strlen(opt_argv[i])+1;
651 | }
652 | }
653 | /* allocate */
654 | dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
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 |
694 | /* "keep connection" processing:
695 | when opening connection, -k may be alone or with a query
696 | later -k must appear alone (or there must be an empty line,
697 | or an error) for the connection to close.
698 | */
699 | if( minusk ) {
700 | if( qe->k == 0 ) { /* opening */
701 | qe->k = 1;
702 | }
703 | else { /* closing, if no key; otherwise keep open */
704 | if( key_length <= 1 ) {
705 | qe->k = 0;
706 | }
707 | }
708 | }
709 |
710 | } /* if no error */
711 |
712 | /* we don't need this anymore */
713 | wr_free(tmp_query_str);
714 | wr_free(gst);
715 | g_strfreev(opt_argv);
716 |
717 | if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
718 | return QC_SYNERR;
719 | }
720 | else if(badparerr > 0) { /* the requester has a clue. No Usage info */
721 | return QC_PARERR;
722 | }
723 | else {
724 | return 0;
725 | }
726 | } /* QC_fill() */
727 |
728 | /* QC_environ_new() */
729 | /*++++++++++++++++++++++++++++++++++++++
730 | Create a new query environment.
731 |
732 | More:
733 | +html+ <PRE>
734 | Authors:
735 | ottrey
736 | +html+ </PRE><DL COMPACT>
737 | +html+ <DT>Online References:
738 | +html+ <DD><UL>
739 | +html+ </UL></DL>
740 |
741 | ++++++++++++++++++++++++++++++++++++++*/
742 | Query_environ *QC_environ_new(char *ip, int sock) {
743 | Query_environ *qe;
744 |
745 |
746 | dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
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 | 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)
788 | {
789 | Query_command *qc;
790 | /* allocate place for a copy of the input */
791 | char *copy = 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 | dieif(copy == NULL);
801 |
802 | for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
803 | /* EMPTY */
804 | }
805 |
806 | for(co = (unsigned char *) copy; *ci != 0; ci++) {
807 | if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */
808 | "abcdefghijklmnopqrstuvwxyz"
809 | "0123456789-_:+=.,@/' \n", *ci) != NULL) {
810 | *(co++) = *ci;
811 | }
812 | }
813 |
814 | /* now delete whitespace chars at the end */
815 | while( co != (unsigned char *)copy /* don't read past the beginning */
816 | && isspace(*co) ) {
817 | *co = '\0';
818 | co--;
819 | }
820 |
821 |
822 | dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
823 |
824 | if ( strlen(copy) == 0) {
825 | /* An empty query (Ie return) was sent */
826 | qc->query_type = QC_EMPTY;
827 | }
828 | else { /* else <==> input_length > 0 ) */
829 | /* parse query */
830 | qt = QC_fill(copy, qc, qe);
831 |
832 | if( qt == QC_SYNERR || qt == QC_PARERR ) {
833 | qc->query_type = qt;
834 | }
835 | else {
836 | /* Update the query environment */
837 | /* qe = QC_environ_update(qc, qe); */
838 |
839 | /* Only do a query if there are keys. */
840 | if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
841 | if( strlen(qc->keys) == 0
842 | && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
843 | qc->query_type = QC_TEMPLATE;
844 | }
845 | else {
846 | qc->query_type = QC_NOKEY;
847 | }
848 | }
849 | else {
850 | if ( strcmp(qc->keys, "HELP") == 0 ) {
851 | qc->query_type = QC_HELP;
852 | }
853 | /* So, a real query */
854 | else if( qc->filtered ) {
855 | qc->query_type = QC_FILTERED;
856 | }
857 | else {
858 | qc->query_type = QC_REAL;
859 | }
860 | }
861 | }
862 | }
863 |
864 | free(copy);
865 |
866 | return qc;
867 | }
868 |
869 |
870 | /*++++++++++++++++++++++++++++++++++++++
871 |
872 | Get the name of the given query type code.
873 |
874 | char *QC_get_qrytype returns a pointer to an element of array of static strings
875 |
876 | qc_qtype_t qrytype query type code
877 |
878 | ++++++++++++++++++++++++++++++++++++++*/
879 |
880 | char *QC_get_qrytype(qc_qtype_t qrytype) {
881 | dieif(qrytype >= QC_TYPE_MAX);
882 |
883 | return qrytype_str[qrytype];
884 | }