1    | /***************************************
2    |   $Revision: 1.58 $
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  |     UT_free(qe->version);
246  | 
247  |     if (qe->sources_list != NULL) {
248  |       g_list_free(qe->sources_list); 
249  |       qe->sources_list=NULL;
250  |     }
251  |     UT_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  |       UT_free(qc->keys);
280  |     }
281  |     UT_free(qc);
282  |   }
283  | } /* QC_free() */
284  | 
285  | 
286  | 
287  | /* QC_fill() */
288  | /*++++++++++++++++++++++++++++++++++++++
289  |   Create a new query_command.
290  |   Returns 0 when OK, -1 when query incorrect.
291  |   
292  |   char *query_str The garden variety whois query string.
293  | 
294  |   Query_environ *qe the environment
295  | 
296  |   More:
297  |   +html+ <PRE>
298  |   Authors:
299  |         ottrey - original code
300  | 	marek - modified for my getopts, multiple sources;
301  | 	        and generally cleaned.
302  |   +html+ </PRE><DL COMPACT>
303  |   +html+ <DT>Online References:
304  |   +html+ <DD><UL>
305  |   +html+ </UL></DL>
306  | 
307  |   ++++++++++++++++++++++++++++++++++++++*/
308  | static
309  | int QC_fill(char *query_str, 
310  | 	     Query_command *query_command,
311  | 	     Query_environ *qe) {
312  |   
313  |   int c;
314  |   int synerrflg = 0;
315  |   int badparerr = 0;
316  |   int minusk = 0;
317  |   char *inv_attrs_str = NULL;
318  |   char *object_types_str = NULL;
319  |   int opt_argc;
320  |   gchar **opt_argv;
321  |   char *value;
322  | /*  char *tmp_query_str;*/
323  |   unsigned key_length;
324  |   int i;
325  |   int index;
326  |   C_Type_t type;
327  |   A_Type_t attr;
328  |   getopt_state_t *gst = NULL;
329  | 
330  |   query_command->c_irt_search = FALSE;
331  |   query_command->d = 0;
332  |   query_command->e = 0;
333  |   query_command->g = 0;
334  |   query_command->inv_attrs_bitmap = MA_new(MA_END);
335  |   query_command->recursive = 1;  /* Recursion is on by default. */
336  |   query_command->l = 0;
337  |   query_command->m = 0;
338  |   query_command->q = -1;
339  |   query_command->t = -1;
340  |   query_command->v = -1;
341  |   query_command->x = 0;
342  |   query_command->fast = 0;
343  |   query_command->filtered = 0;
344  |   query_command->L = 0;
345  |   query_command->M = 0;
346  |   query_command->R = 0;
347  |   query_command->S = 0;
348  | 
349  |   /* XXX UGLY - "all zeros" in object_type_bitmap means the same as 
350  |      "all ones". To limit the inconsistency, this is changed at the end 
351  |      of this function, so outside "all zeros" is an illegal value. */
352  |   query_command->object_type_bitmap = MA_new(MA_END);
353  |   /*
354  |   query_command->keytypes_bitmap = MA_new(MA_END);
355  |   */
356  |   query_command->keys = NULL;
357  | 
358  |   /* This is so Marek can't crash me :-) */
359  |   /* Side Effect - query keys are subsequently cut short to STR_S size. */
360  | 
361  | /*  tmp_query_str = (char *)UT_calloc(1, STR_S+1);
362  |   strncpy(tmp_query_str, query_str, STR_S);*/
363  | 
364  |   /* Create the arguments. */
365  |   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
366  | /*  opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);*/
367  |   opt_argv = g_strsplit(query_str, " ", MAX_OPT_ARG_C);
368  | 
369  |   /* Determine the number of arguments. */
370  |   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
371  | 
372  |   dieif( (gst = mg_new(0)) == NULL );
373  |   
374  |   while ((c = mg_getopt(opt_argc, opt_argv, "acdegi:klrmq:s:t:v:xFKLMRST:V:", 
375  | 			gst)) != EOF) {
376  |     switch (c) {
377  |       case 'a':
378  |         /* Remove any user specified sources from the sources list. */
379  | 	/* free the list only, do not touch the elements */
380  | 	g_list_free(qe->sources_list); 
381  | 	qe->sources_list=NULL;
382  | 
383  |         /* Add all the config sources to the sources list. */
384  | 	{
385  | 	  int i;
386  | 	  ca_dbSource_t *hdl;
387  | 	  
388  | 	  for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
389  | 	    qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
390  | 	  }
391  | 	}
392  | 
393  | 
394  |       break;
395  | 
396  |       case 'c':
397  |         query_command->c_irt_search = TRUE;
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  |           /* 
418  |              Now a really stupid hard-coded hack to support "pn" being a
419  |              synonym for "ac,tc,zc,ah".  I particularly object to this because
420  |              it references attributes that should only be defined in XML - but
421  |              I don't see a simplier more robust way of doing this hack.
422  |              :-( - ottrey 8/12/99 
423  | 
424  | 	     ** removed a memory leak - MB, 1/08/00
425  | 
426  |              ** removed the use of "ro", added "person" - shane, 2002-01-23
427  | 
428  | 	     */
429  |           if (   strcmp(inv_attrs_str, "pn") == 0 
430  | 	      || strcmp(inv_attrs_str, "person") == 0) {
431  |             hackstr = UT_strdup("ac,tc,zc,ah,cn");
432  | 	    inv_attrs_str = hackstr;
433  |           }
434  |           while (*inv_attrs_str) {
435  |             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
436  |             if (index == -1) {
437  | 	      /* Unknown attribute encountered. */
438  | 	      char *rep = ca_get_qc_badattr ;
439  |               SK_cd_puts(&(qe->condat), rep);
440  | 	      UT_free(rep);
441  | 
442  |               attr = -1;
443  |               badparerr++;
444  |             }
445  |             else {
446  |               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
447  |               attr = DF_get_attribute_index(index);
448  |               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
449  |                 /* Add the attr to the bitmap. */
450  |                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
451  |               }
452  |               else {
453  | 	        /* "%s" is not an inverse searchable attribute. */
454  | 	        char *rep = ca_get_qc_fmt_attrnotinv ;
455  | 	        SK_cd_printf(&(qe->condat), rep, 
456  | 		    (DF_get_attribute_aliases())[index]);
457  |                 UT_free(rep);
458  |                 badparerr++;
459  |               }
460  |             } 
461  |           } /* while () */
462  | 
463  | 	  if( hackstr != NULL) {
464  | 	    UT_free(hackstr);
465  | 	  }
466  |         } /* if () */
467  |       break;
468  | 
469  |       case 'k':
470  | 	minusk = 1;
471  |       break;
472  | 
473  |       case 'r':
474  |         query_command->recursive=0;       /* Unset recursion */
475  |       break;
476  | 
477  |       case 'l':
478  |         query_command->l=1;
479  |       break;
480  | 
481  |       case 'm':
482  |         query_command->m=1;
483  |       break;
484  | 
485  |       case 'q':
486  |         if (gst->optarg != NULL) {
487  |           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
488  |           if (index == -1) {
489  |             synerrflg++;
490  |           }
491  |           else {
492  |             query_command->q = index;
493  |           } 
494  |         } /* if () */
495  |       break;
496  | 
497  |       case 's':
498  |         if (gst->optarg != NULL) {
499  | 	  char *token, *cursor = gst->optarg;
500  | 	  ca_dbSource_t *handle;
501  | 	  
502  |           /* Remove any sources from the sources list. */
503  | 	  g_list_free(qe->sources_list); 
504  | 	  qe->sources_list=NULL;
505  | 	  
506  | 	  /* go through specified sources */
507  | 	  while( (token = strsep( &cursor, "," )) != NULL ) {
508  | 	    
509  | 	    if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
510  | 	      /* append */
511  | 	      qe->sources_list 
512  | 		= g_list_append(qe->sources_list, (void *) handle );
513  | 	    }
514  | 	    else {
515  | 	      /* bail out */
516  | 	      
517  | 	      /* Unknown source %s requested. */
518  | 	      char *rep = ca_get_qc_fmt_badsource ;
519  | 	      SK_cd_printf(&(qe->condat), rep, token ); 
520  | 	      UT_free(rep);
521  | 	      
522  | 	      /* XXX error */
523  | 	      badparerr++;
524  | 	      
525  | 	    } /* if handle not null */
526  | 	  } /* while sources */
527  |         } /* if argument present */
528  | 	break;
529  | 	
530  |       case 't':
531  |         if (gst->optarg != NULL) {
532  |           object_types_str = gst->optarg;
533  |           while (*object_types_str) {
534  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
535  |             if (index == -1) {
536  | 	      /* Unknown object type encountered */
537  | 	      char *rep = ca_get_qc_badobjtype ;
538  |               SK_cd_puts(&(qe->condat), rep);
539  | 	      UT_free(rep);
540  |               badparerr++;
541  |             }
542  |             else {
543  |               type = DF_get_class_index(index);
544  |               query_command->t=type;
545  |             }
546  |           }
547  |         }
548  |       break;
549  | 
550  |       case 'v':
551  |         if (gst->optarg != NULL) {
552  |           object_types_str = gst->optarg;
553  |           if (*object_types_str) {
554  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
555  |             if (index == -1) {
556  | 	      /* Unknown object type encountered */
557  | 	      char *rep = ca_get_qc_badobjtype ;
558  |               SK_cd_puts(&(qe->condat), rep);
559  | 	      UT_free(rep);
560  |               badparerr++;
561  |             }
562  |             else {
563  |               type = DF_get_class_index(index);
564  |               query_command->v=type;
565  |             }
566  |           }
567  |         }
568  |       break;
569  | 
570  |       case 'x':
571  |         query_command->x=1;
572  |       break;
573  | 
574  |       case 'F':
575  |         query_command->fast=1;
576  | 	query_command->recursive=0; /* implies no recursion */
577  |       break;
578  | 
579  |       case 'K':
580  |         query_command->filtered=1;
581  | 	query_command->recursive=0; /* implies no recursion */
582  |       break;
583  | 
584  |       case 'L':
585  |         query_command->L=1;
586  |       break;
587  | 
588  |       case 'M':
589  |         query_command->M=1;
590  |       break;
591  | 
592  |       case 'R':
593  |         query_command->R=1;
594  |       break;
595  | 
596  |       case 'S':
597  |         query_command->S=1;
598  |       break;
599  | 
600  |       case 'T':
601  |         if (gst->optarg != NULL) {
602  | 	  /* parse the specification */
603  |           object_types_str = gst->optarg;
604  |           while (*object_types_str) {
605  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
606  |             if (index == -1) {
607  | 	      /* Unknown object type encountered */
608  | 	      char *rep = ca_get_qc_badobjtype ;
609  |               SK_cd_puts(&(qe->condat), rep);
610  | 	      UT_free(rep);
611  |               badparerr++;
612  |             }
613  |             else {
614  |               type = DF_get_class_index(index);
615  |               /* Add the type to the bitmap. */
616  |               MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
617  |             }
618  |           }
619  |         }
620  |       break;
621  | 
622  |       case 'V':
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  |               UT_free(qe->version);
630  |               qe->version = UT_strdup(token);
631  |             }
632  |           }
633  |         }
634  |       break;
635  | 
636  |       /* any other flag, including '?' and ':' errors */
637  |       default:
638  |         synerrflg++;
639  |     }
640  |   }
641  | 
642  |   /* copy the key */
643  | 
644  |   /* Work out the length of space needed */
645  |   key_length = 1; /* for terminal '\0' */
646  |   for (i=gst->optind ; i < opt_argc; i++) {
647  |     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
648  |     if (opt_argv[i] != NULL) {
649  |       key_length += strlen(opt_argv[i])+1;
650  |     }
651  |   }
652  |   /* allocate */
653  |   query_command->keys = (char *)UT_calloc(1, key_length+1);
654  | 
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  |     log_command(query_str, query_command);
694  | 
695  |     /* "keep connection" processing:
696  |        when opening connection, -k may be alone or with a query
697  |        later -k must appear alone (or there must be an empty line,
698  |        or an error) for the connection to close.
699  |     */
700  |     if( minusk ) {
701  |       if( qe->k == 0 ) { /* opening */ 
702  | 	qe->k = 1;
703  |       }
704  |       else { /* closing, if no key; otherwise keep open */
705  | 	if( key_length <= 1 ) {
706  | 	  qe->k = 0;
707  | 	}
708  |       }
709  |     }
710  |     
711  |   } /* if no error */
712  | 
713  |   /* we don't need this anymore */
714  | /*  UT_free(tmp_query_str);*/
715  |   UT_free(gst);
716  |   g_strfreev(opt_argv);
717  | 
718  |   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
719  |     return QC_SYNERR;
720  |   }
721  |   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
722  |     return QC_PARERR;
723  |   }
724  |   else {
725  |     return 0;
726  |   }
727  | } /* QC_fill() */
728  | 
729  | /* QC_environ_new() */
730  | /*++++++++++++++++++++++++++++++++++++++
731  |   Create a new query environment.
732  | 
733  |   More:
734  |   +html+ <PRE>
735  |   Authors:
736  |         ottrey
737  |   +html+ </PRE><DL COMPACT>
738  |   +html+ <DT>Online References:
739  |   +html+ <DD><UL>
740  |   +html+ </UL></DL>
741  | 
742  |   ++++++++++++++++++++++++++++++++++++++*/
743  | Query_environ *QC_environ_new(char *ip, int sock) {
744  |   Query_environ *qe;
745  | 
746  |   qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ));
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  |       UT_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 = UT_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  |   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
801  |     /* EMPTY */
802  |   }
803  | 
804  |   for(co = (unsigned char *) copy; *ci != 0; ci++) {
805  |     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
806  | 	       "abcdefghijklmnopqrstuvwxyz"
807  | 	       "0123456789-_:+=.,@/?' \n", *ci) != NULL) {
808  |       *(co++) = *ci;
809  |     }
810  |   }
811  | 
812  |   /* now delete whitespace chars at the end */
813  |   while( co != (unsigned char *)copy /* don't read past the beginning */
814  | 	 && isspace(*co) ) {
815  |     *co = '\0';
816  |     co--;
817  |   }
818  | 
819  | 
820  |   qc = (Query_command *)UT_calloc(1, sizeof(Query_command));
821  |   
822  |   if ( strlen(copy) == 0) {
823  |     /* An empty query (Ie return) was sent */
824  |     qc->query_type = QC_EMPTY;
825  |   } 
826  |   else {        /* else <==> input_length > 0 ) */
827  |     /* parse query */
828  |     qt = QC_fill(copy, qc, qe);
829  | 
830  |     if( qt == QC_SYNERR || qt == QC_PARERR ) {
831  |       qc->query_type = qt;
832  |     }
833  |     else {
834  |       /* Update the query environment */
835  |       /* qe = QC_environ_update(qc, qe); */
836  | 
837  |       /* Only do a query if there are keys. */
838  |       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
839  | 	if( strlen(qc->keys) == 0 
840  | 	    && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
841  | 	  qc->query_type = QC_TEMPLATE;
842  | 	}
843  | 	else {
844  | 	  qc->query_type = QC_NOKEY;
845  | 	}
846  |       }
847  |       else {
848  | 	if ( strcmp(qc->keys, "HELP") == 0 ) {
849  | 	  qc->query_type = QC_HELP;
850  | 	}
851  | 	/* So, a real query */
852  | 	else if( qc->filtered ) {
853  | 	  qc->query_type = QC_FILTERED;
854  | 	}
855  | 	else {
856  | 	  qc->query_type = QC_REAL;
857  | 	}
858  |       }
859  |     }
860  |   }
861  | 
862  |   UT_free(copy);
863  | 
864  |   return qc;
865  | }
866  | 
867  | 
868  | /*++++++++++++++++++++++++++++++++++++++
869  | 
870  |   Get the name of the given query type code.
871  | 
872  |   char *QC_get_qrytype   returns a pointer to an element of array of static strings
873  | 
874  |   qc_qtype_t qrytype     query type code
875  | 
876  |   ++++++++++++++++++++++++++++++++++++++*/
877  | 
878  | char *QC_get_qrytype(qc_qtype_t qrytype) {
879  |   dieif(qrytype >= QC_TYPE_MAX);
880  | 
881  |   return qrytype_str[qrytype];
882  | }