1    | /***************************************
2    |   $Revision: 1.39 $
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->e = 0;
337  |   query_command->g = 0;
338  |   query_command->inv_attrs_bitmap = MA_new(MA_END);
339  |   query_command->recursive = 1;  /* Recursion is on by default. */
340  |   query_command->l = 0;
341  |   query_command->m = 0;
342  |   query_command->q = -1;
343  |   query_command->t = -1;
344  |   query_command->v = -1;
345  |   query_command->x = 0;
346  |   query_command->fast = 0;
347  |   query_command->filtered = 0;
348  |   query_command->L = 0;
349  |   query_command->M = 0;
350  |   query_command->R = 0;
351  |   query_command->S = 0;
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  |   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);  
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  | 
368  |   /* Determine the number of arguments. */
369  |   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
370  | 
371  |   dieif( (gst = mg_new(0)) == NULL );
372  |   
373  |   while ((c = mg_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:", 
374  | 			gst)) != EOF) {
375  |     switch (c) {
376  |       case 'a':
377  |         /* Remove any user specified sources from the sources list. */
378  | 	/* free the list only, do not touch the elements */
379  | 	g_list_free(qe->sources_list); 
380  | 	qe->sources_list=NULL;
381  | 
382  |         /* Add all the config sources to the sources list. */
383  | 	{
384  | 	  int i;
385  | 	  ca_dbSource_t *hdl;
386  | 	  
387  | 	  for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
388  | 	    qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
389  | 	  }
390  | 	}
391  | 
392  | 
393  |       break;
394  | 
395  |       case 'e':
396  |         query_command->e=1;
397  |       break;
398  | 
399  |       case 'g':
400  |         query_command->g=1;
401  |       break;
402  | 
403  |       case 'i':
404  |         if (gst->optarg != NULL) {
405  | 	  char *hackstr = NULL;
406  | 
407  |           inv_attrs_str = gst->optarg;
408  |           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
409  |           /* I particularly object to this because it references attributes that should only be 
410  |              defined in XML - but I don't see a simplier more robust way of doing this hack.
411  |              :-( - ottrey 8/12/99 
412  | 	     ** removed a memory leak - MB, 1/08/00
413  | 	     */
414  |           if (   strcmp(inv_attrs_str, "pn") == 0 
415  | 	      || strcmp(inv_attrs_str, "ro") == 0) {
416  | 	    wr_malloc( (void **)& hackstr, 24);  /* make a copy */
417  | 	    strcpy(hackstr, "ac,tc,zc,ah");      
418  | 	    inv_attrs_str = hackstr;
419  |           }
420  |           while (*inv_attrs_str) {
421  |             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
422  |             if (index == -1) {
423  |               attr = -1;
424  |               strcpy(str_buf, "");
425  |               sprintf(str_buf, "Unknown attribute encountered.\n"); 
426  |               SK_cd_puts(&(qe->condat), str_buf);
427  |               badparerr++;
428  |             }
429  |             else {
430  |               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
431  |               attr = DF_get_attribute_index(index);
432  |               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
433  |                 /* Add the attr to the bitmap. */
434  |                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
435  |               }
436  |               else {
437  |                 strcpy(str_buf, "");
438  |                 sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]); 
439  |                 SK_cd_puts(&(qe->condat), str_buf);
440  |                 badparerr++;
441  |               }
442  |             } 
443  |           } /* while () */
444  | 
445  | 	  if( hackstr != NULL) {
446  | 	    wr_free(hackstr);
447  | 	  }
448  |         } /* if () */
449  |       break;
450  | 
451  |       case 'k':
452  | 	minusk = 1;
453  |       break;
454  | 
455  |       case 'r':
456  |         query_command->recursive=0;       /* Unset recursion */
457  |       break;
458  | 
459  |       case 'l':
460  |         query_command->l=1;
461  |       break;
462  | 
463  |       case 'm':
464  |         query_command->m=1;
465  |       break;
466  | 
467  |       case 'q':
468  |         if (gst->optarg != NULL) {
469  |           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
470  |           if (index == -1) {
471  |             synerrflg++;
472  |           }
473  |           else {
474  |             query_command->q = index;
475  |           } 
476  |         } /* if () */
477  |       break;
478  | 
479  |       case 's':
480  |         if (gst->optarg != NULL) {
481  | 	  char *token, *cursor = gst->optarg;
482  | 	  ca_dbSource_t *handle;
483  | 	  
484  |           /* Remove any sources from the sources list. */
485  | 	  g_list_free(qe->sources_list); 
486  | 	  qe->sources_list=NULL;
487  | 	  
488  | 	  /* go through specified sources */
489  | 	  while( (token = strsep( &cursor, "," )) != NULL ) {
490  | 	    
491  | 	    if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
492  | 	      /* append */
493  | 	      qe->sources_list 
494  | 		= g_list_append(qe->sources_list, (void *) handle );
495  | 	    }
496  | 	    else {
497  | 	      /* bail out */
498  | 	      
499  | 	      SK_cd_printf(&(qe->condat), 
500  | 			   "%% Unknown source %s requested.\n",token ); 
501  | 	      
502  | 	      /* XXX error */
503  | 	      badparerr++;
504  | 	      
505  | 	    } /* if handle not null */
506  | 	  } /* while sources */
507  |         } /* if argument present */
508  | 	break;
509  | 	
510  |       case 't':
511  |         if (gst->optarg != NULL) {
512  |           object_types_str = gst->optarg;
513  |           while (*object_types_str) {
514  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
515  |             if (index == -1) {
516  |               strcpy(str_buf, "");
517  |               sprintf(str_buf, "Unknown object encountered.\n"); 
518  |               SK_cd_puts(&(qe->condat), str_buf);
519  |               badparerr++;
520  |             }
521  |             else {
522  |               type = DF_get_class_index(index);
523  |               query_command->t=type;
524  |             }
525  |           }
526  |         }
527  |       break;
528  | 
529  |       case 'v':
530  |         if (gst->optarg != NULL) {
531  |           object_types_str = gst->optarg;
532  |           if (*object_types_str) {
533  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
534  |             if (index == -1) {
535  |               strcpy(str_buf, "");
536  |               sprintf(str_buf, "Unknown object encountered.\n"); 
537  |               SK_cd_puts(&(qe->condat), str_buf);
538  |               badparerr++;
539  |             }
540  |             else {
541  |               type = DF_get_class_index(index);
542  |               query_command->v=type;
543  |             }
544  |           }
545  |         }
546  |       break;
547  | 
548  |       case 'x':
549  |         query_command->x=1;
550  |       break;
551  | 
552  |       case 'F':
553  |         query_command->fast=1;
554  | 	query_command->recursive=0; /* implies no recursion */
555  |       break;
556  | 
557  |       case 'K':
558  |         query_command->filtered=1;
559  | 	query_command->recursive=0; /* implies no recursion */
560  |       break;
561  | 
562  |       case 'L':
563  |         query_command->L=1;
564  |       break;
565  | 
566  |       case 'M':
567  |         query_command->M=1;
568  |       break;
569  | 
570  |       case 'R':
571  |         query_command->R=1;
572  |       break;
573  | 
574  |       case 'S':
575  |         query_command->S=1;
576  |       break;
577  | 
578  |       case 'T':
579  |         if (gst->optarg != NULL) {
580  |           object_types_str = gst->optarg;
581  |           while (*object_types_str) {
582  |             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
583  |             if (index == -1) {
584  |               strcpy(str_buf, "");
585  |               sprintf(str_buf, "Unknown obejct type encountered.\n"); 
586  |               SK_cd_puts(&(qe->condat), str_buf);
587  |               badparerr++;
588  |             }
589  |             else {
590  |               type = DF_get_class_index(index);
591  |               /* Add the type to the bitmap. */
592  |               MA_set(&(query_command->object_type_bitmap), type, 1);
593  |             }
594  |           }
595  |         }
596  |       break;
597  | 
598  |       case 'V':
599  |         if (qe->version != NULL) {
600  |           /* free up the old client info */
601  |           wr_free(qe->version);
602  |         }
603  |         
604  |         {
605  |           char *token, *cursor = gst->optarg;
606  |           while( (token = strsep( &cursor, "," )) != NULL ) {
607  |             if(IP_addr_e2b( & (qe->pIP), token) 
608  |                != IP_OK ) {
609  |               /* means it was not an IP -> it was a version */
610  |               dieif( wr_malloc( (void **)&(qe->version), 
611  | 				strlen(token)+1) != UT_OK);  
612  |               strcpy(qe->version, token);
613  |             }
614  |           }
615  |         }
616  |       break;
617  | 
618  |       /* any other flag, including '?' and ':' errors */
619  |       default:
620  |         synerrflg++;
621  |     }
622  |   }
623  | 
624  |   /* copy the key */
625  | 
626  |   /* Work out the length of space needed */
627  |   key_length = 1; /* for terminal '\0' */
628  |   for (i=gst->optind ; i < opt_argc; i++) {
629  |     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
630  |     if (opt_argv[i] != NULL) {
631  |       key_length += strlen(opt_argv[i])+1;
632  |     }
633  |   }
634  |   /* allocate */
635  |   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);  
636  |   /* copy */
637  |   for (i=gst->optind; i < opt_argc; i++) {
638  |     strcat(query_command->keys, opt_argv[i]);
639  |     if ( (i + 1) < opt_argc) {
640  |       strcat(query_command->keys, " ");
641  |     }
642  |   }
643  |     
644  |   /* if no error, process the key, otherwise don't bother */
645  |   if ( ! synerrflg && ! badparerr ) { 
646  |     /* convert the key to uppercase. */
647  |     for (i=0; i <= key_length; i++) {
648  |       query_command->keys[i] = toupper(query_command->keys[i]);
649  |     }
650  |     
651  |     /* make the keytypes_bitmap. */
652  |     query_command->keytypes_bitmap = WK_new(query_command->keys);
653  |     
654  |     /* tracing */
655  |     log_command(tmp_query_str, query_command);
656  | 
657  | 
658  |     /* "keep connection" processing:
659  |        when opening connection, -k may be alone or with a query
660  |        later -k must appear alone (or there must be an empty line,
661  |        or an error) for the connection to close.
662  |     */
663  |     if( minusk ) {
664  |       if( qe->k == 0 ) { /* opening */ 
665  | 	qe->k = 1;
666  |       }
667  |       else { /* closing, if no key; otherwise keep open */
668  | 	if( key_length <= 1 ) {
669  | 	  qe->k = 0;
670  | 	}
671  |       }
672  |     }
673  |     
674  |   } /* if no error */
675  | 
676  |   /* we don't need this anymore */
677  |   wr_free(tmp_query_str);
678  |   wr_free(gst);
679  | 
680  |   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
681  |     return QC_SYNERR;
682  |   }
683  |   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
684  |     return QC_PARERR;
685  |   }
686  |   else {
687  |     return 0;
688  |   }
689  | } /* QC_fill() */
690  | 
691  | /* QC_environ_new() */
692  | /*++++++++++++++++++++++++++++++++++++++
693  |   Create a new query environment.
694  | 
695  |   More:
696  |   +html+ <PRE>
697  |   Authors:
698  |         ottrey
699  |   +html+ </PRE><DL COMPACT>
700  |   +html+ <DT>Online References:
701  |   +html+ <DD><UL>
702  |   +html+ </UL></DL>
703  | 
704  |   ++++++++++++++++++++++++++++++++++++++*/
705  | Query_environ *QC_environ_new(char *ip, unsigned sock) {
706  |   Query_environ *qe;
707  | 
708  | 
709  |   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);  
710  |   qe->condat.ip = ip;
711  |   qe->condat.sock = sock;
712  | 
713  |   /* The source is initialized to include only the deflook sources */
714  |   {
715  |     int i;
716  |     ca_dbSource_t *hdl;
717  |     
718  |     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
719  |       if( ca_get_srcdeflook(hdl) ) {
720  | 	qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
721  |       }
722  |     }
723  |   }
724  |   
725  |   return qe;
726  | 
727  | } /* QC_environ_new() */
728  | 
729  | 
730  | 
731  | /*++ QC_create()
732  |   
733  |   try to parse the query and fill in the QC struct, setting 
734  |   qc->query_type accordingly.
735  |  
736  |   by marek.
737  | ++++++++++++++++++++++++++++++++++++++*/
738  | Query_command *QC_create(char *input, Query_environ *qe)
739  | {
740  |   Query_command *qc;
741  |   /* allocate place for a copy of the input */
742  |   char *copy = calloc(1,strlen(input)+1); 
743  |   char *ci, *co;
744  |   int qt;
745  |   /* clean the string from junk - allow only known chars, something like
746  |      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd; 
747  | 
748  |      strip leading spaces too
749  |   */
750  | 
751  |   dieif(copy == NULL);
752  | 
753  |   for(ci = input; *ci != 0 && isspace(*ci); ci++) {
754  |     /* EMPTY */
755  |   }
756  | 
757  |   for(co = copy; *ci != 0; ci++) {
758  |     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
759  | 	       "abcdefghijklmnopqrstuvwxyz"
760  | 	       "0123456789-_:+=.,@/' \n", *ci) != NULL) {
761  |       *(co++) = *ci;
762  |     }
763  |   }
764  | 
765  |   /* now delete whitespace chars at the end */
766  |   co--;
767  |   while( isspace(*co) ) {
768  |     *co = '\0';
769  |     co--;
770  |   }
771  | 
772  | 
773  |   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
774  |   
775  |   if ( strlen(copy) == 0) {
776  |     /* An empty query (Ie return) was sent */
777  |     qc->query_type = QC_EMPTY;
778  |   } 
779  |   else {        /* else <==> input_length > 0 ) */
780  |     /* parse query */
781  |     qt = QC_fill(copy, qc, qe);
782  | 
783  |     if( qt == QC_SYNERR || qt == QC_PARERR ) {
784  |       qc->query_type = qt;
785  |     }
786  |     else {
787  |       /* Update the query environment */
788  |       /* qe = QC_environ_update(qc, qe); */
789  | 
790  |       /* Only do a query if there are keys. */
791  |       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
792  | 	if( strlen(qc->keys) == 0 
793  | 	    && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
794  | 	  qc->query_type = QC_TEMPLATE;
795  | 	}
796  | 	else {
797  | 	  qc->query_type = QC_NOKEY;
798  | 	}
799  |       }
800  |       else {
801  | 	if ( strcmp(qc->keys, "HELP") == 0 ) {
802  | 	  qc->query_type = QC_HELP;
803  | 	}
804  | 	/* So, a real query */
805  | 	else if( qc->filtered ) {
806  | 	  qc->query_type = QC_FILTERED;
807  | 	}
808  | 	else {
809  | 	  qc->query_type = QC_REAL;
810  | 	}
811  |       }
812  |     }
813  |   }
814  | 
815  |   free(copy);
816  | 
817  |   return qc;
818  | }
819  | 
820  | 
821  | char *QC_get_qrytype(qc_qtype_t qrytype) {
822  |   dieif(qrytype >= QC_TYPE_MAX);
823  | 
824  |   return qrytype_str[qrytype];
825  | }