## modules/qc/query_command.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. qc_sources_list_to_string
2. QC_environ_to_string
3. QC_query_command_to_string
4. log_command
5. QC_environ_free
6. QC_free
7. QC_fill
8. QC_environ_new
9. QC_create
10. QC_get_qrytype

       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)
         /* [<][>][^][v][top][bottom][index][help] */
      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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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,
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     881   dieif(qrytype >= QC_TYPE_MAX);
     882
     883   return qrytype_str[qrytype];
     884 }

/* [<][>][^][v][top][bottom][index][help] */