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  | }