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