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