## modules/qc/query_command.c

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

## DEFINITIONS

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.58 $
       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,2000,2001,2002               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
      34 #define QC_IMPL
      35 #include "rip.h"
      36
      37 #include <stdlib.h>
      38 #include <stdio.h>
      39 #include <string.h>
      40 #include <ctype.h>
      41
      42
      43 #define MAX_OPT_ARG_C 20
      44
      45 extern char *suboptarg;
      46 extern int getsubopt(char **optionp, char * const *tokens, char **valuep);
      47
      48 /*++++++++++++++++++++++++++++++++++++++
      49   make a list of sources. expects list to hold source handles
      50
      51   char *
      52   qc_sources_list_to_string     returns an allocated string, must be freed
      53
      54   GList *list                   list of source handles (as defined by CA)
      55
      56   ++++++++++++++++++++++++++++++++++++++*/
      57 char *
      58 qc_sources_list_to_string(GList *list)
         /* [<][>][^][v][top][bottom][index][help] */
      59 {
      60     GString *tmp;
      61     GList *qitem;
      62     char *result;
      63
      64     /* use GString for the result, because it resizes magically */
      65     tmp = g_string_sized_new(STR_L);
      66
      67     /* loop through the list, creating a string with the names of the
      68        sources separated by commas */
      69     qitem = g_list_first(list);
      70     if (qitem != NULL) {
      71         for (;;) {
      72             ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data );
      73             char *srcname = ca_get_srcname( source_hdl );
      74             g_string_append(tmp, srcname);
      75
      76             qitem = g_list_next(qitem);
      77             if (qitem == NULL) {
      78                 break;
      79             }
      80
      81             g_string_append_c(tmp, ',');
      82         }
      83     }
      84
      85     /* move to a new buffer for the return */
      86     result = UT_strdup(tmp->str);
      87     g_string_free(tmp, TRUE);
      88     return result;
      89 }
      90
      91 /* QC_environ_to_string() */
      92 /*++++++++++++++++++++++++++++++++++++++
      93   Convert the query_environ to a string.
      94
      95   Query_environ *query_environ The query_environ to be converted.
      96
      97   More:
      98   +html+ <PRE>
      99   Authors:
     100         ottrey
     101   +html+ </PRE><DL COMPACT>
     102   +html+ <DT>Online References:
     103   +html+ <DD><UL>
     104   +html+ </UL></DL>
     105
     106   ++++++++++++++++++++++++++++++++++++++*/
     107 char *
     108 QC_environ_to_string(Query_environ qe)
         /* [<][>][^][v][top][bottom][index][help] */
     109 {
     110   char *sources;
     111   char passed_addr[IP_ADDRSTR_MAX];
     112   GString *tmp;
     113   char *result;
     114
     115   /* convert the sources and the passed address (if any) to printable strings */
     116   sources = qc_sources_list_to_string(qe.sources_list);
     117   if( IP_addr_b2a( &(qe.pIP), passed_addr, IP_ADDRSTR_MAX) != IP_OK ) {
     118     passed_addr[0] = '\0';
     119   }
     120
     121   /* format the environment info */
     122   tmp = g_string_sized_new(STR_L);
     123   g_string_sprintf(tmp,
     124                    "host=%s, keep_connection=%s, sources=%s, version=%s%s%s",
     125                    qe.condat.ip,
     126                    qe.k ? "on" : "off",
     127                    sources,
     128                    (qe.version == NULL) ? "?" : qe.version,
     129                    passed_addr[0] == '\0' ? "" : ", passedIP=",
     130                    passed_addr);
     131
     132   /* move result to return buffer, and free up memory */
     133   result = UT_strdup(tmp->str);
     134   g_string_free(tmp, TRUE);
     135   UT_free(sources);
     136
     137   return result;
     138
     139 } /* QC_environ_to_string() */
     140
     141 /* QC_query_command_to_string() */
     142 /*++++++++++++++++++++++++++++++++++++++
     143   Convert the query_command to a string.
     144
     145   Query_command *query_command The query_command to be converted.
     146
     147   More:
     148   +html+ <PRE>
     149   Authors:
     150         ottrey
     151   +html+ </PRE><DL COMPACT>
     152   +html+ <DT>Online References:
     153   +html+ <DD><UL>
     154   +html+ </UL></DL>
     155
     156   ++++++++++++++++++++++++++++++++++++++*/
     157 char *QC_query_command_to_string(Query_command *query_command) {
         /* [<][>][^][v][top][bottom][index][help] */
     158   char result_buf[STR_XL];
     159   char *str1;
     160   char *str2;
     161   char *str3;
     162
     163   str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
     164   str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
     165   str3 = WK_to_string(query_command->keytypes_bitmap);
     166
     167   sprintf(result_buf, "Query_command : inv_attrs=%s, recursive=%s, object_type=%s, (c=%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]",
     168           str1,
     169           query_command->recursive?"y":"n",
     170           str2,
     171           query_command->c_irt_search ? "TRUE" : "FALSE",
     172           query_command->e,
     173           query_command->g,
     174           query_command->l,
     175           query_command->m,
     176           query_command->q,
     177           query_command->t,
     178           query_command->v,
     179           query_command->x,
     180           query_command->fast,
     181           query_command->filtered,
     182           query_command->L,
     183           query_command->M,
     184           query_command->R,
     185           query_command->S,
     186           str3,
     187           query_command->keys);
     188   UT_free(str1);
     189   UT_free(str2);
     190   UT_free(str3);
     191
     192   return UT_strdup(result_buf);
     193
     194 } /* QC_query_command_to_string() */
     195
     196 /* log_command() */
     197 /*++++++++++++++++++++++++++++++++++++++
     198   Log the command.
     199   This is more to do with Tracing.  And should/will get merged with a tracing
     200   module (when it is finalized.)
     201
     202   char *query_str
     203
     204   Query_command *query_command
     205
     206   More:
     207   +html+ <PRE>
     208   Authors:
     209         ottrey
     210   +html+ </PRE><DL COMPACT>
     211   +html+ <DT>Online References:
     212   +html+ <DD><UL>
     213   +html+ </UL></DL>
     214
     215   ++++++++++++++++++++++++++++++++++++++*/
     216 static void log_command(char *query_str, Query_command *query_command) {
         /* [<][>][^][v][top][bottom][index][help] */
     217   char *str;
     218
     219   if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
     220     str = QC_query_command_to_string(query_command);
     221     ER_dbg_va(FAC_QC, ASP_QC_BUILD,
     222               "query=[%s]   %s", query_str, str);
     223     UT_free(str);
     224   }
     225 } /* log_command() */
     226
     227 /* QC_environ_free() */
     228 /*++++++++++++++++++++++++++++++++++++++
     229   Free the query_environ.
     230
     231   Query_command *qc query_environ to be freed.
     232
     233   More:
     234   +html+ <PRE>
     235   Authors:
     236         ottrey
     237   +html+ </PRE><DL COMPACT>
     238   +html+ <DT>Online References:
     239   +html+ <DD><UL>
     240   +html+ </UL></DL>
     241
     242   ++++++++++++++++++++++++++++++++++++++*/
     243 void QC_environ_free(Query_environ *qe) {
         /* [<][>][^][v][top][bottom][index][help] */
     244   if (qe != NULL) {
     245     UT_free(qe->version);
     246
     247     if (qe->sources_list != NULL) {
     248       g_list_free(qe->sources_list);
     249       qe->sources_list=NULL;
     250     }
     251     UT_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       UT_free(qc->keys);
     280     }
     281     UT_free(qc);
     282   }
     283 } /* QC_free() */
     284
     285
     286
     287 /* QC_fill() */
     288 /*++++++++++++++++++++++++++++++++++++++
     289   Create a new query_command.
     290   Returns 0 when OK, -1 when query incorrect.
     291
     292   char *query_str The garden variety whois query string.
     293
     294   Query_environ *qe the environment
     295
     296   More:
     297   +html+ <PRE>
     298   Authors:
     299         ottrey - original code
     300         marek - modified for my getopts, multiple sources;
     301                 and generally cleaned.
     302   +html+ </PRE><DL COMPACT>
     303   +html+ <DT>Online References:
     304   +html+ <DD><UL>
     305   +html+ </UL></DL>
     306
     307   ++++++++++++++++++++++++++++++++++++++*/
     308 static
     309 int QC_fill(char *query_str,
         /* [<][>][^][v][top][bottom][index][help] */
     310              Query_command *query_command,
     311              Query_environ *qe) {
     312
     313   int c;
     314   int synerrflg = 0;
     315   int badparerr = 0;
     316   int minusk = 0;
     317   char *inv_attrs_str = NULL;
     318   char *object_types_str = NULL;
     319   int opt_argc;
     320   gchar **opt_argv;
     321   char *value;
     322 /*  char *tmp_query_str;*/
     323   unsigned key_length;
     324   int i;
     325   int index;
     326   C_Type_t type;
     327   A_Type_t attr;
     328   getopt_state_t *gst = NULL;
     329
     330   query_command->c_irt_search = FALSE;
     331   query_command->d = 0;
     332   query_command->e = 0;
     333   query_command->g = 0;
     334   query_command->inv_attrs_bitmap = MA_new(MA_END);
     335   query_command->recursive = 1;  /* Recursion is on by default. */
     336   query_command->l = 0;
     337   query_command->m = 0;
     338   query_command->q = -1;
     339   query_command->t = -1;
     340   query_command->v = -1;
     341   query_command->x = 0;
     342   query_command->fast = 0;
     343   query_command->filtered = 0;
     344   query_command->L = 0;
     345   query_command->M = 0;
     346   query_command->R = 0;
     347   query_command->S = 0;
     348
     349   /* XXX UGLY - "all zeros" in object_type_bitmap means the same as
     350      "all ones". To limit the inconsistency, this is changed at the end
     351      of this function, so outside "all zeros" is an illegal value. */
     352   query_command->object_type_bitmap = MA_new(MA_END);
     353   /*
     354   query_command->keytypes_bitmap = MA_new(MA_END);
     355   */
     356   query_command->keys = NULL;
     357
     358   /* This is so Marek can't crash me :-) */
     359   /* Side Effect - query keys are subsequently cut short to STR_S size. */
     360
     361 /*  tmp_query_str = (char *)UT_calloc(1, STR_S+1);
     362   strncpy(tmp_query_str, query_str, STR_S);*/
     363
     364   /* Create the arguments. */
     365   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
     366 /*  opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);*/
     367   opt_argv = g_strsplit(query_str, " ", MAX_OPT_ARG_C);
     368
     369   /* Determine the number of arguments. */
     370   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
     371
     372   dieif( (gst = mg_new(0)) == NULL );
     373
     374   while ((c = mg_getopt(opt_argc, opt_argv, "acdegi:klrmq:s:t:v:xFKLMRST:V:",
     375                         gst)) != EOF) {
     376     switch (c) {
     377       case 'a':
     378         /* Remove any user specified sources from the sources list. */
     379         /* free the list only, do not touch the elements */
     380         g_list_free(qe->sources_list);
     381         qe->sources_list=NULL;
     382
     383         /* Add all the config sources to the sources list. */
     384         {
     385           int i;
     386           ca_dbSource_t *hdl;
     387
     388           for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
     389             qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
     390           }
     391         }
     392
     393
     394       break;
     395
     396       case 'c':
     397         query_command->c_irt_search = TRUE;
     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           /*
     418              Now a really stupid hard-coded hack to support "pn" being a
     419              synonym for "ac,tc,zc,ah".  I particularly object to this because
     420              it references attributes that should only be defined in XML - but
     421              I don't see a simplier more robust way of doing this hack.
     422              :-( - ottrey 8/12/99
     423
     424              ** removed a memory leak - MB, 1/08/00
     425
     426              ** removed the use of "ro", added "person" - shane, 2002-01-23
     427
     428              */
     429           if (   strcmp(inv_attrs_str, "pn") == 0
     430               || strcmp(inv_attrs_str, "person") == 0) {
     431             hackstr = UT_strdup("ac,tc,zc,ah,cn");
     432             inv_attrs_str = hackstr;
     433           }
     434           while (*inv_attrs_str) {
     435             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
     436             if (index == -1) {
     437               /* Unknown attribute encountered. */
     438               char *rep = ca_get_qc_badattr ;
     439               SK_cd_puts(&(qe->condat), rep);
     440               UT_free(rep);
     441
     442               attr = -1;
     443               badparerr++;
     444             }
     445             else {
     446               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
     447               attr = DF_get_attribute_index(index);
     448               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
     449                 /* Add the attr to the bitmap. */
     450                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
     451               }
     452               else {
     453                 /* "%s" is not an inverse searchable attribute. */
     454                 char *rep = ca_get_qc_fmt_attrnotinv ;
     455                 SK_cd_printf(&(qe->condat), rep,
     456                     (DF_get_attribute_aliases())[index]);
     457                 UT_free(rep);
     458                 badparerr++;
     459               }
     460             }
     461           } /* while () */
     462
     463           if( hackstr != NULL) {
     464             UT_free(hackstr);
     465           }
     466         } /* if () */
     467       break;
     468
     469       case 'k':
     470         minusk = 1;
     471       break;
     472
     473       case 'r':
     474         query_command->recursive=0;       /* Unset recursion */
     475       break;
     476
     477       case 'l':
     478         query_command->l=1;
     479       break;
     480
     481       case 'm':
     482         query_command->m=1;
     483       break;
     484
     485       case 'q':
     486         if (gst->optarg != NULL) {
     487           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
     488           if (index == -1) {
     489             synerrflg++;
     490           }
     491           else {
     492             query_command->q = index;
     493           }
     494         } /* if () */
     495       break;
     496
     497       case 's':
     498         if (gst->optarg != NULL) {
     499           char *token, *cursor = gst->optarg;
     500           ca_dbSource_t *handle;
     501
     502           /* Remove any sources from the sources list. */
     503           g_list_free(qe->sources_list);
     504           qe->sources_list=NULL;
     505
     506           /* go through specified sources */
     507           while( (token = strsep( &cursor, "," )) != NULL ) {
     508
     509             if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
     510               /* append */
     511               qe->sources_list
     512                 = g_list_append(qe->sources_list, (void *) handle );
     513             }
     514             else {
     515               /* bail out */
     516
     517               /* Unknown source %s requested. */
     518               char *rep = ca_get_qc_fmt_badsource ;
     519               SK_cd_printf(&(qe->condat), rep, token );
     520               UT_free(rep);
     521
     522               /* XXX error */
     523               badparerr++;
     524
     525             } /* if handle not null */
     526           } /* while sources */
     527         } /* if argument present */
     528         break;
     529
     530       case 't':
     531         if (gst->optarg != NULL) {
     532           object_types_str = gst->optarg;
     533           while (*object_types_str) {
     534             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     535             if (index == -1) {
     536               /* Unknown object type encountered */
     537               char *rep = ca_get_qc_badobjtype ;
     538               SK_cd_puts(&(qe->condat), rep);
     539               UT_free(rep);
     540               badparerr++;
     541             }
     542             else {
     543               type = DF_get_class_index(index);
     544               query_command->t=type;
     545             }
     546           }
     547         }
     548       break;
     549
     550       case 'v':
     551         if (gst->optarg != NULL) {
     552           object_types_str = gst->optarg;
     553           if (*object_types_str) {
     554             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     555             if (index == -1) {
     556               /* Unknown object type encountered */
     557               char *rep = ca_get_qc_badobjtype ;
     558               SK_cd_puts(&(qe->condat), rep);
     559               UT_free(rep);
     560               badparerr++;
     561             }
     562             else {
     563               type = DF_get_class_index(index);
     564               query_command->v=type;
     565             }
     566           }
     567         }
     568       break;
     569
     570       case 'x':
     571         query_command->x=1;
     572       break;
     573
     574       case 'F':
     575         query_command->fast=1;
     576         query_command->recursive=0; /* implies no recursion */
     577       break;
     578
     579       case 'K':
     580         query_command->filtered=1;
     581         query_command->recursive=0; /* implies no recursion */
     582       break;
     583
     584       case 'L':
     585         query_command->L=1;
     586       break;
     587
     588       case 'M':
     589         query_command->M=1;
     590       break;
     591
     592       case 'R':
     593         query_command->R=1;
     594       break;
     595
     596       case 'S':
     597         query_command->S=1;
     598       break;
     599
     600       case 'T':
     601         if (gst->optarg != NULL) {
     602           /* parse the specification */
     603           object_types_str = gst->optarg;
     604           while (*object_types_str) {
     605             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     606             if (index == -1) {
     607               /* Unknown object type encountered */
     608               char *rep = ca_get_qc_badobjtype ;
     609               SK_cd_puts(&(qe->condat), rep);
     610               UT_free(rep);
     611               badparerr++;
     612             }
     613             else {
     614               type = DF_get_class_index(index);
     615               /* Add the type to the bitmap. */
     616               MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
     617             }
     618           }
     619         }
     620       break;
     621
     622       case 'V':
     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               UT_free(qe->version);
     630               qe->version = UT_strdup(token);
     631             }
     632           }
     633         }
     634       break;
     635
     636       /* any other flag, including '?' and ':' errors */
     637       default:
     638         synerrflg++;
     639     }
     640   }
     641
     642   /* copy the key */
     643
     644   /* Work out the length of space needed */
     645   key_length = 1; /* for terminal '\0' */
     646   for (i=gst->optind ; i < opt_argc; i++) {
     647     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
     648     if (opt_argv[i] != NULL) {
     649       key_length += strlen(opt_argv[i])+1;
     650     }
     651   }
     652   /* allocate */
     653   query_command->keys = (char *)UT_calloc(1, key_length+1);
     654
     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     log_command(query_str, query_command);
     694
     695     /* "keep connection" processing:
     696        when opening connection, -k may be alone or with a query
     697        later -k must appear alone (or there must be an empty line,
     698        or an error) for the connection to close.
     699     */
     700     if( minusk ) {
     701       if( qe->k == 0 ) { /* opening */
     702         qe->k = 1;
     703       }
     704       else { /* closing, if no key; otherwise keep open */
     705         if( key_length <= 1 ) {
     706           qe->k = 0;
     707         }
     708       }
     709     }
     710
     711   } /* if no error */
     712
     713   /* we don't need this anymore */
     714 /*  UT_free(tmp_query_str);*/
     715   UT_free(gst);
     716   g_strfreev(opt_argv);
     717
     718   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
     719     return QC_SYNERR;
     720   }
     721   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
     722     return QC_PARERR;
     723   }
     724   else {
     725     return 0;
     726   }
     727 } /* QC_fill() */
     728
     729 /* QC_environ_new() */
     730 /*++++++++++++++++++++++++++++++++++++++
     731   Create a new query environment.
     732
     733   More:
     734   +html+ <PRE>
     735   Authors:
     736         ottrey
     737   +html+ </PRE><DL COMPACT>
     738   +html+ <DT>Online References:
     739   +html+ <DD><UL>
     740   +html+ </UL></DL>
     741
     742   ++++++++++++++++++++++++++++++++++++++*/
     743 Query_environ *QC_environ_new(char *ip, int sock) {
         /* [<][>][^][v][top][bottom][index][help] */
     744   Query_environ *qe;
     745
     746   qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ));
     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       UT_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 = UT_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   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
     801     /* EMPTY */
     802   }
     803
     804   for(co = (unsigned char *) copy; *ci != 0; ci++) {
     805     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
     806                "abcdefghijklmnopqrstuvwxyz"
     807                "0123456789-_:+=.,@/?' \n", *ci) != NULL) {
     808       *(co++) = *ci;
     809     }
     810   }
     811
     812   /* now delete whitespace chars at the end */
     813   while( co != (unsigned char *)copy /* don't read past the beginning */
     814          && isspace(*co) ) {
     815     *co = '\0';
     816     co--;
     817   }
     818
     819
     820   qc = (Query_command *)UT_calloc(1, sizeof(Query_command));
     821
     822   if ( strlen(copy) == 0) {
     823     /* An empty query (Ie return) was sent */
     824     qc->query_type = QC_EMPTY;
     825   }
     826   else {        /* else <==> input_length > 0 ) */
     827     /* parse query */
     828     qt = QC_fill(copy, qc, qe);
     829
     830     if( qt == QC_SYNERR || qt == QC_PARERR ) {
     831       qc->query_type = qt;
     832     }
     833     else {
     834       /* Update the query environment */
     835       /* qe = QC_environ_update(qc, qe); */
     836
     837       /* Only do a query if there are keys. */
     838       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
     839         if( strlen(qc->keys) == 0
     840             && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
     841           qc->query_type = QC_TEMPLATE;
     842         }
     843         else {
     844           qc->query_type = QC_NOKEY;
     845         }
     846       }
     847       else {
     848         if ( strcmp(qc->keys, "HELP") == 0 ) {
     849           qc->query_type = QC_HELP;
     850         }
     851         /* So, a real query */
     852         else if( qc->filtered ) {
     853           qc->query_type = QC_FILTERED;
     854         }
     855         else {
     856           qc->query_type = QC_REAL;
     857         }
     858       }
     859     }
     860   }
     861
     862   UT_free(copy);
     863
     864   return qc;
     865 }
     866
     867
     868 /*++++++++++++++++++++++++++++++++++++++
     869
     870   Get the name of the given query type code.
     871
     872   char *QC_get_qrytype   returns a pointer to an element of array of static strings
     873
     874   qc_qtype_t qrytype     query type code
     875
     876   ++++++++++++++++++++++++++++++++++++++*/
     877
     878 char *QC_get_qrytype(qc_qtype_t qrytype) {
         /* [<][>][^][v][top][bottom][index][help] */
     879   dieif(qrytype >= QC_TYPE_MAX);
     880
     881   return qrytype_str[qrytype];
     882 }

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