Source File modules/qc/query_command.c

    1    | /***************************************
    2    |   $Revision: 1.38 $
    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  |   char *inv_attrs_str = NULL;
    322  |   char *object_types_str = NULL;
    323  |   int opt_argc;
    324  |   gchar **opt_argv;
    325  |   char *value;
    326  |   char *tmp_query_str;
    327  |   int key_length;
    328  |   int i;
    329  |   int index;
    330  |   int type;
    331  |   int attr;
    332  |   char str_buf[STR_XL];
    333  |   getopt_state_t *gst = NULL;
    334  |
    335  |   query_command->e = 0;
    336  |   query_command->g = 0;
    337  |   query_command->inv_attrs_bitmap = MA_new(MA_END);
    338  |   query_command->recursive = 1;  /* Recursion is on by default. */
    339  |   query_command->l = 0;
    340  |   query_command->m = 0;
    341  |   query_command->q = -1;
    342  |   query_command->t = -1;
    343  |   query_command->v = -1;
    344  |   query_command->x = 0;
    345  |   query_command->fast = 0;
    346  |   query_command->filtered = 0;
    347  |   query_command->L = 0;
    348  |   query_command->M = 0;
    349  |   query_command->R = 0;
    350  |   query_command->S = 0;
    351  |   query_command->object_type_bitmap = MA_new(MA_END);
    352  |   /*
    353  |   query_command->keytypes_bitmap = MA_new(MA_END);
    354  |   */
    355  |   query_command->keys = NULL;
    356  |
    357  |   /* This is so Marek can't crash me :-) */
    358  |   /* Side Effect - query keys are subsequently cut short to STR_S size. */
    359  |
    360  |   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
    361  |   strncpy(tmp_query_str, query_str, STR_S);
    362  |
    363  |   /* Create the arguments. */
    364  |   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
    365  |   opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
    366  |
    367  |   /* Determine the number of arguments. */
    368  |   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
    369  |
    370  |   dieif( (gst = mg_new(0)) == NULL );
    371  |
    372  |   while ((c = mg_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:",
    373  | 			gst)) != EOF) {
    374  |     switch (c) {
    375  |       case 'a':
    376  |         /* Remove any user specified sources from the sources list. */
    377  | 	/* free the list only, do not touch the elements */
    378  | 	g_list_free(qe->sources_list);
    379  | 	qe->sources_list=NULL;
    380  |
    381  |         /* Add all the config sources to the sources list. */
    382  | 	{
    383  | 	  int i;
    384  | 	  ca_dbSource_t *hdl;
    385  |
    386  | 	  for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
    387  | 	    qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
    388  | 	  }
    389  | 	}
    390  |
    391  |
    392  |       break;
    393  |
    394  |       case 'e':
    395  |         query_command->e=1;
    396  |       break;
    397  |
    398  |       case 'g':
    399  |         query_command->g=1;
    400  |       break;
    401  |
    402  |       case 'i':
    403  |         if (gst->optarg != NULL) {
    404  | 	  char *hackstr = NULL;
    405  |
    406  |           inv_attrs_str = gst->optarg;
    407  |           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
    408  |           /* I particularly object to this because it references attributes that should only be
    409  |              defined in XML - but I don't see a simplier more robust way of doing this hack.
    410  |              :-( - ottrey 8/12/99
    411  | 	     ** removed a memory leak - MB, 1/08/00
    412  | 	     */
    413  |           if (   strcmp(inv_attrs_str, "pn") == 0
    414  | 	      || strcmp(inv_attrs_str, "ro") == 0) {
    415  | 	    wr_malloc( (void **)& hackstr, 24);  /* make a copy */
    416  | 	    strcpy(hackstr, "ac,tc,zc,ah");
    417  | 	    inv_attrs_str = hackstr;
    418  |           }
    419  |           while (*inv_attrs_str) {
    420  |             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
    421  |             if (index == -1) {
    422  |               attr = -1;
    423  |               strcpy(str_buf, "");
    424  |               sprintf(str_buf, "Unknown attribute encountered.\n");
    425  |               SK_cd_puts(&(qe->condat), str_buf);
    426  |               badparerr++;
    427  |             }
    428  |             else {
    429  |               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
    430  |               attr = DF_get_attribute_index(index);
    431  |               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
    432  |                 /* Add the attr to the bitmap. */
    433  |                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
    434  |               }
    435  |               else {
    436  |                 strcpy(str_buf, "");
    437  |                 sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]);
    438  |                 SK_cd_puts(&(qe->condat), str_buf);
    439  |                 badparerr++;
    440  |               }
    441  |             }
    442  |           } /* while () */
    443  |
    444  | 	  if( hackstr != NULL) {
    445  | 	    wr_free(hackstr);
    446  | 	  }
    447  |         } /* if () */
    448  |       break;
    449  |
    450  |       case 'k':
    451  |         /* triggering flag == a XOR operation */
    452  |         qe->k ^= 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  |   } /* if no error */
    658  |
    659  |   /* we don't need this anymore */
    660  |   wr_free(tmp_query_str);
    661  |   wr_free(gst);
    662  |
    663  |   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
    664  |     return QC_SYNERR;
    665  |   }
    666  |   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
    667  |     return QC_PARERR;
    668  |   }
    669  |   else {
    670  |     return 0;
    671  |   }
    672  | } /* QC_fill() */
    673  |
    674  | /* QC_environ_new() */
    675  | /*++++++++++++++++++++++++++++++++++++++
    676  |   Create a new query environment.
    677  |
    678  |   More:
    679  |   +html+ <PRE>
    680  |   Authors:
    681  |         ottrey
    682  |   +html+ </PRE><DL COMPACT>
    683  |   +html+ <DT>Online References:
    684  |   +html+ <DD><UL>
    685  |   +html+ </UL></DL>
    686  |
    687  |   ++++++++++++++++++++++++++++++++++++++*/
    688  | Query_environ *QC_environ_new(char *ip, unsigned sock) {
    689  |   Query_environ *qe;
    690  |
    691  |
    692  |   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
    693  |   qe->condat.ip = ip;
    694  |   qe->condat.sock = sock;
    695  |
    696  |   /* The source is initialized to include only the deflook sources */
    697  |   {
    698  |     int i;
    699  |     ca_dbSource_t *hdl;
    700  |
    701  |     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
    702  |       if( ca_get_srcdeflook(hdl) ) {
    703  | 	qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
    704  |       }
    705  |     }
    706  |   }
    707  |
    708  |   return qe;
    709  |
    710  | } /* QC_environ_new() */
    711  |
    712  |
    713  |
    714  | /*++ QC_create()
    715  |
    716  |   try to parse the query and fill in the QC struct, setting
    717  |   qc->query_type accordingly.
    718  |
    719  |   by marek.
    720  | ++++++++++++++++++++++++++++++++++++++*/
    721  | Query_command *QC_create(char *input, Query_environ *qe)
    722  | {
    723  |   Query_command *qc;
    724  |   /* allocate place for a copy of the input */
    725  |   char *copy = calloc(1,strlen(input)+1);
    726  |   char *ci, *co;
    727  |   int qt;
    728  |   /* clean the string from junk - allow only known chars, something like
    729  |      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
    730  |
    731  |      strip leading spaces too
    732  |   */
    733  |
    734  |   dieif(copy == NULL);
    735  |
    736  |   for(ci = input; *ci != 0 && isspace(*ci); ci++) {
    737  |     /* EMPTY */
    738  |   }
    739  |
    740  |   for(co = copy; *ci != 0; ci++) {
    741  |     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
    742  | 	       "abcdefghijklmnopqrstuvwxyz"
    743  | 	       "0123456789-_:+=.,@/' \n", *ci) != NULL) {
    744  |       *(co++) = *ci;
    745  |     }
    746  |   }
    747  |
    748  |   /* now delete whitespace chars at the end */
    749  |   co--;
    750  |   while( isspace(*co) ) {
    751  |     *co = '\0';
    752  |     co--;
    753  |   }
    754  |
    755  |
    756  |   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
    757  |
    758  |   if ( strlen(copy) == 0) {
    759  |     /* An empty query (Ie return) was sent */
    760  |     qc->query_type = QC_EMPTY;
    761  |   }
    762  |   else {        /* else <==> input_length > 0 ) */
    763  |     /* parse query */
    764  |     qt = QC_fill(copy, qc, qe);
    765  |
    766  |     if( qt == QC_SYNERR || qt == QC_PARERR ) {
    767  |       qc->query_type = qt;
    768  |     }
    769  |     else {
    770  |       /* Update the query environment */
    771  |       /* qe = QC_environ_update(qc, qe); */
    772  |
    773  |       /* Only do a query if there are keys. */
    774  |       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
    775  | 	if( strlen(qc->keys) == 0
    776  | 	    && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
    777  | 	  qc->query_type = QC_TEMPLATE;
    778  | 	}
    779  | 	else {
    780  | 	  qc->query_type = QC_NOKEY;
    781  | 	}
    782  |       }
    783  |       else {
    784  | 	if ( strcmp(qc->keys, "HELP") == 0 ) {
    785  | 	  qc->query_type = QC_HELP;
    786  | 	}
    787  | 	/* So, a real query */
    788  | 	else if( qc->filtered ) {
    789  | 	  qc->query_type = QC_FILTERED;
    790  | 	}
    791  | 	else {
    792  | 	  qc->query_type = QC_REAL;
    793  | 	}
    794  |       }
    795  |     }
    796  |   }
    797  |
    798  |   free(copy);
    799  |
    800  |   return qc;
    801  | }
    802  |
    803  |
    804  | char *QC_get_qrytype(qc_qtype_t qrytype) {
    805  |   dieif(qrytype >= QC_TYPE_MAX);
    806  |
    807  |   return qrytype_str[qrytype];
    808  | }