## 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.44 $
       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)
         /* [<][>][^][v][top][bottom][index][help] */
      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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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) {
         /* [<][>][^][v][top][bottom][index][help] */
     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,
         /* [<][>][^][v][top][bottom][index][help] */
     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->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               attr = -1;
     433               strcpy(str_buf, "");
     434               sprintf(str_buf, "Unknown attribute encountered.\n"); /* YYY configurable constant: text  */
     435               SK_cd_puts(&(qe->condat), str_buf);
     436               badparerr++;
     437             }
     438             else {
     439               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
     440               attr = DF_get_attribute_index(index);
     441               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
     442                 /* Add the attr to the bitmap. */
     443                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
     444               }
     445               else {
     446                 strcpy(str_buf, "");
     447                 sprintf(str_buf, "\"%s\" is not an inverse searchable attribute.\n", (DF_get_attribute_aliases())[index]); /* YYY configurable constant: text  */
     448                 SK_cd_puts(&(qe->condat), str_buf);
     449                 badparerr++;
     450               }
     451             }
     452           } /* while () */
     453
     454           if( hackstr != NULL) {
     455             wr_free(hackstr);
     456           }
     457         } /* if () */
     458       break;
     459
     460       case 'k':
     461         minusk = 1;
     462       break;
     463
     464       case 'r':
     465         query_command->recursive=0;       /* Unset recursion */
     466       break;
     467
     468       case 'l':
     469         query_command->l=1;
     470       break;
     471
     472       case 'm':
     473         query_command->m=1;
     474       break;
     475
     476       case 'q':
     477         if (gst->optarg != NULL) {
     478           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
     479           if (index == -1) {
     480             synerrflg++;
     481           }
     482           else {
     483             query_command->q = index;
     484           }
     485         } /* if () */
     486       break;
     487
     488       case 's':
     489         if (gst->optarg != NULL) {
     490           char *token, *cursor = gst->optarg;
     491           ca_dbSource_t *handle;
     492
     493           /* Remove any sources from the sources list. */
     494           g_list_free(qe->sources_list);
     495           qe->sources_list=NULL;
     496
     497           /* go through specified sources */
     498           while( (token = strsep( &cursor, "," )) != NULL ) {
     499
     500             if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
     501               /* append */
     502               qe->sources_list
     503                 = g_list_append(qe->sources_list, (void *) handle );
     504             }
     505             else {
     506               /* bail out */
     507
     508               SK_cd_printf(&(qe->condat),
     509                            "%% Unknown source %s requested.\n",token ); /* YYY configurable constant: text  */
     510
     511               /* XXX error */
     512               badparerr++;
     513
     514             } /* if handle not null */
     515           } /* while sources */
     516         } /* if argument present */
     517         break;
     518
     519       case 't':
     520         if (gst->optarg != NULL) {
     521           object_types_str = gst->optarg;
     522           while (*object_types_str) {
     523             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     524             if (index == -1) {
     525               strcpy(str_buf, "");
     526               sprintf(str_buf, "Unknown object encountered.\n"); /* YYY configurable constant: text  */
     527               SK_cd_puts(&(qe->condat), str_buf);
     528               badparerr++;
     529             }
     530             else {
     531               type = DF_get_class_index(index);
     532               query_command->t=type;
     533             }
     534           }
     535         }
     536       break;
     537
     538       case 'v':
     539         if (gst->optarg != NULL) {
     540           object_types_str = gst->optarg;
     541           if (*object_types_str) {
     542             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     543             if (index == -1) {
     544               strcpy(str_buf, "");
     545               sprintf(str_buf, "Unknown object encountered.\n"); /* YYY configurable constant: text  */
     546               SK_cd_puts(&(qe->condat), str_buf);
     547               badparerr++;
     548             }
     549             else {
     550               type = DF_get_class_index(index);
     551               query_command->v=type;
     552             }
     553           }
     554         }
     555       break;
     556
     557       case 'x':
     558         query_command->x=1;
     559       break;
     560
     561       case 'F':
     562         query_command->fast=1;
     563         query_command->recursive=0; /* implies no recursion */
     564       break;
     565
     566       case 'K':
     567         query_command->filtered=1;
     568         query_command->recursive=0; /* implies no recursion */
     569       break;
     570
     571       case 'L':
     572         query_command->L=1;
     573       break;
     574
     575       case 'M':
     576         query_command->M=1;
     577       break;
     578
     579       case 'R':
     580         query_command->R=1;
     581       break;
     582
     583       case 'S':
     584         query_command->S=1;
     585       break;
     586
     587       case 'T':
     588         if (gst->optarg != NULL) {
     589           /* parse the specification */
     590           object_types_str = gst->optarg;
     591           while (*object_types_str) {
     592             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     593             if (index == -1) {
     594               strcpy(str_buf, "");
     595               sprintf(str_buf, "Unknown object type encountered.\n"); /* YYY configurable constant: text  */
     596               SK_cd_puts(&(qe->condat), str_buf);
     597               badparerr++;
     598             }
     599             else {
     600               type = DF_get_class_index(index);
     601               /* Add the type to the bitmap. */
     602               MA_set(&(query_command->object_type_bitmap), type, 1);
     603             }
     604           }
     605         }
     606       break;
     607
     608       case 'V':
     609         if (qe->version != NULL) {
     610           /* free up the old client info */
     611           wr_free(qe->version);
     612         }
     613
     614         {
     615           char *token, *cursor = gst->optarg;
     616           while( (token = strsep( &cursor, "," )) != NULL ) {
     617             if(IP_addr_e2b( & (qe->pIP), token)
     618                != IP_OK ) {
     619               /* means it was not an IP -> it was a version */
     620               dieif( wr_malloc( (void **)&(qe->version),
     621                                 strlen(token)+1) != UT_OK);
     622               strcpy(qe->version, token);
     623             }
     624           }
     625         }
     626       break;
     627
     628       /* any other flag, including '?' and ':' errors */
     629       default:
     630         synerrflg++;
     631     }
     632   }
     633
     634   /* copy the key */
     635
     636   /* Work out the length of space needed */
     637   key_length = 1; /* for terminal '\0' */
     638   for (i=gst->optind ; i < opt_argc; i++) {
     639     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
     640     if (opt_argv[i] != NULL) {
     641       key_length += strlen(opt_argv[i])+1;
     642     }
     643   }
     644   /* allocate */
     645   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
     646   /* copy */
     647   for (i=gst->optind; i < opt_argc; i++) {
     648     strcat(query_command->keys, opt_argv[i]);
     649     if ( (i + 1) < opt_argc) {
     650       strcat(query_command->keys, " ");
     651     }
     652   }
     653
     654   /* if no error, process the key, otherwise don't bother */
     655   if ( ! synerrflg && ! badparerr ) {
     656     /* convert the key to uppercase. */
     657     for (i=0; i <= key_length; i++) {
     658       query_command->keys[i] = toupper(query_command->keys[i]);
     659     }
     660
     661     /* make the keytypes_bitmap. */
     662     query_command->keytypes_bitmap = WK_new(query_command->keys);
     663
     664     /* fix the object type bitmap - turn "all zeros" into "all ones" */
     665     if( MA_bitcount(query_command->object_type_bitmap) == 0 ) {
     666       query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap);
     667     }
     668
     669     /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then
     670        exclude the domains unless -d is set
     671        XXX this must be kept in sync with new types */
     672     if( query_command->d == 0
     673         && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS)
     674              || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE )
     675              || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX )
     676              || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX )
     677              ) ) {
     678
     679       MA_set(&(query_command->object_type_bitmap), C_DN , 0);
     680     }
     681
     682     /* tracing */
     683     log_command(tmp_query_str, query_command);
     684
     685     /* "keep connection" processing:
     686        when opening connection, -k may be alone or with a query
     687        later -k must appear alone (or there must be an empty line,
     688        or an error) for the connection to close.
     689     */
     690     if( minusk ) {
     691       if( qe->k == 0 ) { /* opening */
     692         qe->k = 1;
     693       }
     694       else { /* closing, if no key; otherwise keep open */
     695         if( key_length <= 1 ) {
     696           qe->k = 0;
     697         }
     698       }
     699     }
     700
     701   } /* if no error */
     702
     703   /* we don't need this anymore */
     704   wr_free(tmp_query_str);
     705   wr_free(gst);
     706
     707   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
     708     return QC_SYNERR;
     709   }
     710   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
     711     return QC_PARERR;
     712   }
     713   else {
     714     return 0;
     715   }
     716 } /* QC_fill() */
     717
     718 /* QC_environ_new() */
     719 /*++++++++++++++++++++++++++++++++++++++
     720   Create a new query environment.
     721
     722   More:
     723   +html+ <PRE>
     724   Authors:
     725         ottrey
     726   +html+ </PRE><DL COMPACT>
     727   +html+ <DT>Online References:
     728   +html+ <DD><UL>
     729   +html+ </UL></DL>
     730
     731   ++++++++++++++++++++++++++++++++++++++*/
     732 Query_environ *QC_environ_new(char *ip, unsigned sock) {
         /* [<][>][^][v][top][bottom][index][help] */
     733   Query_environ *qe;
     734
     735
     736   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
     737   qe->condat.ip = ip;
     738   qe->condat.sock = sock;
     739
     740   /* The source is initialized to include only the deflook sources */
     741   {
     742     int i;
     743     ca_dbSource_t *hdl;
     744
     745     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
     746       if( ca_get_srcdeflook(hdl) ) {
     747         qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
     748       }
     749     }
     750   }
     751
     752   return qe;
     753
     754 } /* QC_environ_new() */
     755
     756
     757
     758 /*++ QC_create()
     759
     760   try to parse the query and fill in the QC struct, setting
     761   qc->query_type accordingly.
     762
     763   by marek.
     764 ++++++++++++++++++++++++++++++++++++++*/
     765 Query_command *QC_create(char *input, Query_environ *qe)
         /* [<][>][^][v][top][bottom][index][help] */
     766 {
     767   Query_command *qc;
     768   /* allocate place for a copy of the input */
     769   char *copy = calloc(1,strlen(input)+1);
     770   unsigned char *ci, *co;
     771   int qt;
     772   /* clean the string from junk - allow only known chars, something like
     773      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
     774
     775      strip leading spaces too
     776   */
     777
     778   dieif(copy == NULL);
     779
     780   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
     781     /* EMPTY */
     782   }
     783
     784   for(co = (unsigned char *) copy; *ci != 0; ci++) {
     785     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
     786                "abcdefghijklmnopqrstuvwxyz"
     787                "0123456789-_:+=.,@/' \n", *ci) != NULL) {
     788       *(co++) = *ci;
     789     }
     790   }
     791
     792   /* now delete whitespace chars at the end */
     793   co--;
     794   while( isspace(*co) ) {
     795     *co = '\0';
     796     co--;
     797   }
     798
     799
     800   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
     801
     802   if ( strlen(copy) == 0) {
     803     /* An empty query (Ie return) was sent */
     804     qc->query_type = QC_EMPTY;
     805   }
     806   else {        /* else <==> input_length > 0 ) */
     807     /* parse query */
     808     qt = QC_fill(copy, qc, qe);
     809
     810     if( qt == QC_SYNERR || qt == QC_PARERR ) {
     811       qc->query_type = qt;
     812     }
     813     else {
     814       /* Update the query environment */
     815       /* qe = QC_environ_update(qc, qe); */
     816
     817       /* Only do a query if there are keys. */
     818       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
     819         if( strlen(qc->keys) == 0
     820             && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
     821           qc->query_type = QC_TEMPLATE;
     822         }
     823         else {
     824           qc->query_type = QC_NOKEY;
     825         }
     826       }
     827       else {
     828         if ( strcmp(qc->keys, "HELP") == 0 ) {
     829           qc->query_type = QC_HELP;
     830         }
     831         /* So, a real query */
     832         else if( qc->filtered ) {
     833           qc->query_type = QC_FILTERED;
     834         }
     835         else {
     836           qc->query_type = QC_REAL;
     837         }
     838       }
     839     }
     840   }
     841
     842   free(copy);
     843
     844   return qc;
     845 }
     846
     847
     848 char *QC_get_qrytype(qc_qtype_t qrytype) {
         /* [<][>][^][v][top][bottom][index][help] */
     849   dieif(qrytype >= QC_TYPE_MAX);
     850
     851   return qrytype_str[qrytype];
     852 }

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