## 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.56 $
       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     if (qe->version != NULL) {
     246       UT_free(qe->version);
     247     }
     248
     249     if (qe->sources_list != NULL) {
     250       g_list_free(qe->sources_list);
     251       qe->sources_list=NULL;
     252     }
     253     UT_free(qe);
     254   }
     255 } /* QC_environ_free() */
     256
     257 /* QC_free() */
     258 /*++++++++++++++++++++++++++++++++++++++
     259   Free the query_command.
     260
     261   Query_command *qc query_command to be freed.
     262
     263   XXX I'm not sure the bitmaps will get freed.
     264   qc->inv_attrs_bitmap
     265   qc->object_type_bitmap
     266   qc->keytypes_bitmap
     267
     268   More:
     269   +html+ <PRE>
     270   Authors:
     271         ottrey
     272   +html+ </PRE><DL COMPACT>
     273   +html+ <DT>Online References:
     274   +html+ <DD><UL>
     275   +html+ </UL></DL>
     276
     277   ++++++++++++++++++++++++++++++++++++++*/
     278 void QC_free(Query_command *qc) {
         /* [<][>][^][v][top][bottom][index][help] */
     279   if (qc != NULL) {
     280     if (qc->keys != NULL) {
     281       UT_free(qc->keys);
     282     }
     283     UT_free(qc);
     284   }
     285 } /* QC_free() */
     286
     287
     288
     289 /* QC_fill() */
     290 /*++++++++++++++++++++++++++++++++++++++
     291   Create a new query_command.
     292   Returns 0 when OK, -1 when query incorrect.
     293
     294   char *query_str The garden variety whois query string.
     295
     296   Query_environ *qe the environment
     297
     298   More:
     299   +html+ <PRE>
     300   Authors:
     301         ottrey - original code
     302         marek - modified for my getopts, multiple sources;
     303                 and generally cleaned.
     304   +html+ </PRE><DL COMPACT>
     305   +html+ <DT>Online References:
     306   +html+ <DD><UL>
     307   +html+ </UL></DL>
     308
     309   ++++++++++++++++++++++++++++++++++++++*/
     310 static
     311 int QC_fill(char *query_str,
         /* [<][>][^][v][top][bottom][index][help] */
     312              Query_command *query_command,
     313              Query_environ *qe) {
     314
     315   int c;
     316   int synerrflg = 0;
     317   int badparerr = 0;
     318   int minusk = 0;
     319   char *inv_attrs_str = NULL;
     320   char *object_types_str = NULL;
     321   int opt_argc;
     322   gchar **opt_argv;
     323   char *value;
     324 /*  char *tmp_query_str;*/
     325   unsigned key_length;
     326   int i;
     327   int index;
     328   C_Type_t type;
     329   A_Type_t attr;
     330   getopt_state_t *gst = NULL;
     331
     332   query_command->c_irt_search = FALSE;
     333   query_command->d = 0;
     334   query_command->e = 0;
     335   query_command->g = 0;
     336   query_command->inv_attrs_bitmap = MA_new(MA_END);
     337   query_command->recursive = 1;  /* Recursion is on by default. */
     338   query_command->l = 0;
     339   query_command->m = 0;
     340   query_command->q = -1;
     341   query_command->t = -1;
     342   query_command->v = -1;
     343   query_command->x = 0;
     344   query_command->fast = 0;
     345   query_command->filtered = 0;
     346   query_command->L = 0;
     347   query_command->M = 0;
     348   query_command->R = 0;
     349   query_command->S = 0;
     350
     351   /* XXX UGLY - "all zeros" in object_type_bitmap means the same as
     352      "all ones". To limit the inconsistency, this is changed at the end
     353      of this function, so outside "all zeros" is an illegal value. */
     354   query_command->object_type_bitmap = MA_new(MA_END);
     355   /*
     356   query_command->keytypes_bitmap = MA_new(MA_END);
     357   */
     358   query_command->keys = NULL;
     359
     360   /* This is so Marek can't crash me :-) */
     361   /* Side Effect - query keys are subsequently cut short to STR_S size. */
     362
     363 /*  tmp_query_str = (char *)UT_calloc(1, STR_S+1);
     364   strncpy(tmp_query_str, query_str, STR_S);*/
     365
     366   /* Create the arguments. */
     367   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
     368 /*  opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);*/
     369   opt_argv = g_strsplit(query_str, " ", MAX_OPT_ARG_C);
     370
     371   /* Determine the number of arguments. */
     372   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
     373
     374   dieif( (gst = mg_new(0)) == NULL );
     375
     376   while ((c = mg_getopt(opt_argc, opt_argv, "acdegi:klrmq:s:t:v:xFKLMRST:V:",
     377                         gst)) != EOF) {
     378     switch (c) {
     379       case 'a':
     380         /* Remove any user specified sources from the sources list. */
     381         /* free the list only, do not touch the elements */
     382         g_list_free(qe->sources_list);
     383         qe->sources_list=NULL;
     384
     385         /* Add all the config sources to the sources list. */
     386         {
     387           int i;
     388           ca_dbSource_t *hdl;
     389
     390           for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
     391             qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
     392           }
     393         }
     394
     395
     396       break;
     397
     398       case 'c':
     399         query_command->c_irt_search = TRUE;
     400         break;
     401
     402       case 'e':
     403         query_command->e=1;
     404       break;
     405
     406       case 'd':
     407         query_command->d=1;
     408       break;
     409
     410       case 'g':
     411         query_command->g=1;
     412       break;
     413
     414       case 'i':
     415         if (gst->optarg != NULL) {
     416           char *hackstr = NULL;
     417
     418           inv_attrs_str = gst->optarg;
     419           /*
     420              Now a really stupid hard-coded hack to support "pn" being a
     421              synonym for "ac,tc,zc,ah".  I particularly object to this because
     422              it references attributes that should only be defined in XML - but
     423              I don't see a simplier more robust way of doing this hack.
     424              :-( - ottrey 8/12/99
     425
     426              ** removed a memory leak - MB, 1/08/00
     427
     428              ** removed the use of "ro", added "person" - shane, 2002-01-23
     429
     430              */
     431           if (   strcmp(inv_attrs_str, "pn") == 0
     432               || strcmp(inv_attrs_str, "person") == 0) {
     433             hackstr = UT_strdup("ac,tc,zc,ah,cn");
     434             inv_attrs_str = hackstr;
     435           }
     436           while (*inv_attrs_str) {
     437             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
     438             if (index == -1) {
     439               /* Unknown attribute encountered. */
     440               char *rep = ca_get_qc_badattr ;
     441               SK_cd_puts(&(qe->condat), rep);
     442               UT_free(rep);
     443
     444               attr = -1;
     445               badparerr++;
     446             }
     447             else {
     448               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
     449               attr = DF_get_attribute_index(index);
     450               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
     451                 /* Add the attr to the bitmap. */
     452                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
     453               }
     454               else {
     455                 /* "%s" is not an inverse searchable attribute. */
     456                 char *rep = ca_get_qc_fmt_attrnotinv ;
     457                 SK_cd_printf(&(qe->condat), rep,
     458                     (DF_get_attribute_aliases())[index]);
     459                 UT_free(rep);
     460                 badparerr++;
     461               }
     462             }
     463           } /* while () */
     464
     465           if( hackstr != NULL) {
     466             UT_free(hackstr);
     467           }
     468         } /* if () */
     469       break;
     470
     471       case 'k':
     472         minusk = 1;
     473       break;
     474
     475       case 'r':
     476         query_command->recursive=0;       /* Unset recursion */
     477       break;
     478
     479       case 'l':
     480         query_command->l=1;
     481       break;
     482
     483       case 'm':
     484         query_command->m=1;
     485       break;
     486
     487       case 'q':
     488         if (gst->optarg != NULL) {
     489           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
     490           if (index == -1) {
     491             synerrflg++;
     492           }
     493           else {
     494             query_command->q = index;
     495           }
     496         } /* if () */
     497       break;
     498
     499       case 's':
     500         if (gst->optarg != NULL) {
     501           char *token, *cursor = gst->optarg;
     502           ca_dbSource_t *handle;
     503
     504           /* Remove any sources from the sources list. */
     505           g_list_free(qe->sources_list);
     506           qe->sources_list=NULL;
     507
     508           /* go through specified sources */
     509           while( (token = strsep( &cursor, "," )) != NULL ) {
     510
     511             if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
     512               /* append */
     513               qe->sources_list
     514                 = g_list_append(qe->sources_list, (void *) handle );
     515             }
     516             else {
     517               /* bail out */
     518
     519               /* Unknown source %s requested. */
     520               char *rep = ca_get_qc_fmt_badsource ;
     521               SK_cd_printf(&(qe->condat), rep, token );
     522               UT_free(rep);
     523
     524               /* XXX error */
     525               badparerr++;
     526
     527             } /* if handle not null */
     528           } /* while sources */
     529         } /* if argument present */
     530         break;
     531
     532       case 't':
     533         if (gst->optarg != NULL) {
     534           object_types_str = gst->optarg;
     535           while (*object_types_str) {
     536             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     537             if (index == -1) {
     538               /* Unknown object type encountered */
     539               char *rep = ca_get_qc_badobjtype ;
     540               SK_cd_puts(&(qe->condat), rep);
     541               UT_free(rep);
     542               badparerr++;
     543             }
     544             else {
     545               type = DF_get_class_index(index);
     546               query_command->t=type;
     547             }
     548           }
     549         }
     550       break;
     551
     552       case 'v':
     553         if (gst->optarg != NULL) {
     554           object_types_str = gst->optarg;
     555           if (*object_types_str) {
     556             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     557             if (index == -1) {
     558               /* Unknown object type encountered */
     559               char *rep = ca_get_qc_badobjtype ;
     560               SK_cd_puts(&(qe->condat), rep);
     561               UT_free(rep);
     562               badparerr++;
     563             }
     564             else {
     565               type = DF_get_class_index(index);
     566               query_command->v=type;
     567             }
     568           }
     569         }
     570       break;
     571
     572       case 'x':
     573         query_command->x=1;
     574       break;
     575
     576       case 'F':
     577         query_command->fast=1;
     578         query_command->recursive=0; /* implies no recursion */
     579       break;
     580
     581       case 'K':
     582         query_command->filtered=1;
     583         query_command->recursive=0; /* implies no recursion */
     584       break;
     585
     586       case 'L':
     587         query_command->L=1;
     588       break;
     589
     590       case 'M':
     591         query_command->M=1;
     592       break;
     593
     594       case 'R':
     595         query_command->R=1;
     596       break;
     597
     598       case 'S':
     599         query_command->S=1;
     600       break;
     601
     602       case 'T':
     603         if (gst->optarg != NULL) {
     604           /* parse the specification */
     605           object_types_str = gst->optarg;
     606           while (*object_types_str) {
     607             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     608             if (index == -1) {
     609               /* Unknown object type encountered */
     610               char *rep = ca_get_qc_badobjtype ;
     611               SK_cd_puts(&(qe->condat), rep);
     612               UT_free(rep);
     613               badparerr++;
     614             }
     615             else {
     616               type = DF_get_class_index(index);
     617               /* Add the type to the bitmap. */
     618               MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1);
     619             }
     620           }
     621         }
     622       break;
     623
     624       case 'V':
     625         if (qe->version != NULL) {
     626           /* free up the old client info */
     627           UT_free(qe->version);
     628         }
     629
     630         {
     631           char *token, *cursor = gst->optarg;
     632           while( (token = strsep( &cursor, "," )) != NULL ) {
     633             if(IP_addr_e2b( & (qe->pIP), token)
     634                != IP_OK ) {
     635               /* means it was not an IP -> it was a version */
     636               qe->version = UT_strdup(token);
     637             }
     638           }
     639         }
     640       break;
     641
     642       /* any other flag, including '?' and ':' errors */
     643       default:
     644         synerrflg++;
     645     }
     646   }
     647
     648   /* copy the key */
     649
     650   /* Work out the length of space needed */
     651   key_length = 1; /* for terminal '\0' */
     652   for (i=gst->optind ; i < opt_argc; i++) {
     653     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
     654     if (opt_argv[i] != NULL) {
     655       key_length += strlen(opt_argv[i])+1;
     656     }
     657   }
     658   /* allocate */
     659   query_command->keys = (char *)UT_calloc(1, key_length+1);
     660
     661   /* copy */
     662   for (i=gst->optind; i < opt_argc; i++) {
     663     strcat(query_command->keys, opt_argv[i]);
     664     if ( (i + 1) < opt_argc) {
     665       strcat(query_command->keys, " ");
     666     }
     667   }
     668
     669   /* if no error, process the key, otherwise don't bother */
     670   if ( ! synerrflg && ! badparerr ) {
     671     /* convert the key to uppercase. */
     672     for (i=0; i <= key_length; i++) {
     673       query_command->keys[i] = toupper(query_command->keys[i]);
     674     }
     675
     676     /* make the keytypes_bitmap. */
     677     query_command->keytypes_bitmap = WK_new(query_command->keys);
     678
     679     /* fix the object type bitmap - turn "all zeros" into "all ones" */
     680     if( MA_bitcount(query_command->object_type_bitmap) == 0 ) {
     681       query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap);
     682     }
     683
     684     /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then
     685        exclude the domains unless -d is set
     686        XXX this must be kept in sync with new types */
     687     if( query_command->d == 0
     688         && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS)
     689              || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE )
     690              || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX )
     691              || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX )
     692              ) ) {
     693
     694       MA_set(&(query_command->object_type_bitmap), C_DN , 0);
     695     }
     696
     697     /* tracing */
     698 /*    log_command(tmp_query_str, query_command);*/
     699     log_command(query_str, query_command);
     700
     701     /* "keep connection" processing:
     702        when opening connection, -k may be alone or with a query
     703        later -k must appear alone (or there must be an empty line,
     704        or an error) for the connection to close.
     705     */
     706     if( minusk ) {
     707       if( qe->k == 0 ) { /* opening */
     708         qe->k = 1;
     709       }
     710       else { /* closing, if no key; otherwise keep open */
     711         if( key_length <= 1 ) {
     712           qe->k = 0;
     713         }
     714       }
     715     }
     716
     717   } /* if no error */
     718
     719   /* we don't need this anymore */
     720 /*  UT_free(tmp_query_str);*/
     721   UT_free(gst);
     722   g_strfreev(opt_argv);
     723
     724   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
     725     return QC_SYNERR;
     726   }
     727   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
     728     return QC_PARERR;
     729   }
     730   else {
     731     return 0;
     732   }
     733 } /* QC_fill() */
     734
     735 /* QC_environ_new() */
     736 /*++++++++++++++++++++++++++++++++++++++
     737   Create a new query environment.
     738
     739   More:
     740   +html+ <PRE>
     741   Authors:
     742         ottrey
     743   +html+ </PRE><DL COMPACT>
     744   +html+ <DT>Online References:
     745   +html+ <DD><UL>
     746   +html+ </UL></DL>
     747
     748   ++++++++++++++++++++++++++++++++++++++*/
     749 Query_environ *QC_environ_new(char *ip, int sock) {
         /* [<][>][^][v][top][bottom][index][help] */
     750   Query_environ *qe;
     751
     752   qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ));
     753   qe->condat.ip = ip;
     754   qe->condat.sock = sock;
     755
     756   /* The source is initialized to include only the deflook sources */
     757   {
     758     int i;
     759     ca_dbSource_t *hdl;
     760
     761     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
     762       char *amrmrulez = ca_get_srcdeflook(hdl);
     763       if( strcmp(amrmrulez, "y")==0 ) {
     764         qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
     765       }
     766       UT_free(amrmrulez);
     767     }
     768   }
     769
     770   return qe;
     771
     772 } /* QC_environ_new() */
     773
     774
     775
     776
     777 /* QC_create() */
     778 /*++++++++++++++++++++++++++++++++++++++
     779   try to parse the query and fill in the QC struct, setting
     780   qc->query_type accordingly.
     781
     782   Query_command *QC_create    returns allocated structure
     783
     784   char *input                 user query
     785
     786   Query_environ *qe           query environment structure
     787
     788   Author:
     789     marek.
     790
     791   ++++++++++++++++++++++++++++++++++++++*/
     792
     793 Query_command *QC_create(char *input, Query_environ *qe)
         /* [<][>][^][v][top][bottom][index][help] */
     794 {
     795   Query_command *qc;
     796   /* allocate place for a copy of the input */
     797   char *copy = UT_calloc(1,strlen(input)+1);
     798   unsigned char *ci, *co;
     799   int qt;
     800   /* clean the string from junk - allow only known chars, something like
     801      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
     802
     803      strip leading spaces too
     804   */
     805
     806   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
     807     /* EMPTY */
     808   }
     809
     810   for(co = (unsigned char *) copy; *ci != 0; ci++) {
     811     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
     812                "abcdefghijklmnopqrstuvwxyz"
     813                "0123456789-_:+=.,@/?' \n", *ci) != NULL) {
     814       *(co++) = *ci;
     815     }
     816   }
     817
     818   /* now delete whitespace chars at the end */
     819   while( co != (unsigned char *)copy /* don't read past the beginning */
     820          && isspace(*co) ) {
     821     *co = '\0';
     822     co--;
     823   }
     824
     825
     826   qc = (Query_command *)UT_calloc(1, sizeof(Query_command));
     827
     828   if ( strlen(copy) == 0) {
     829     /* An empty query (Ie return) was sent */
     830     qc->query_type = QC_EMPTY;
     831   }
     832   else {        /* else <==> input_length > 0 ) */
     833     /* parse query */
     834     qt = QC_fill(copy, qc, qe);
     835
     836     if( qt == QC_SYNERR || qt == QC_PARERR ) {
     837       qc->query_type = qt;
     838     }
     839     else {
     840       /* Update the query environment */
     841       /* qe = QC_environ_update(qc, qe); */
     842
     843       /* Only do a query if there are keys. */
     844       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
     845         if( strlen(qc->keys) == 0
     846             && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
     847           qc->query_type = QC_TEMPLATE;
     848         }
     849         else {
     850           qc->query_type = QC_NOKEY;
     851         }
     852       }
     853       else {
     854         if ( strcmp(qc->keys, "HELP") == 0 ) {
     855           qc->query_type = QC_HELP;
     856         }
     857         /* So, a real query */
     858         else if( qc->filtered ) {
     859           qc->query_type = QC_FILTERED;
     860         }
     861         else {
     862           qc->query_type = QC_REAL;
     863         }
     864       }
     865     }
     866   }
     867
     868   UT_free(copy);
     869
     870   return qc;
     871 }
     872
     873
     874 /*++++++++++++++++++++++++++++++++++++++
     875
     876   Get the name of the given query type code.
     877
     878   char *QC_get_qrytype   returns a pointer to an element of array of static strings
     879
     880   qc_qtype_t qrytype     query type code
     881
     882   ++++++++++++++++++++++++++++++++++++++*/
     883
     884 char *QC_get_qrytype(qc_qtype_t qrytype) {
         /* [<][>][^][v][top][bottom][index][help] */
     885   dieif(qrytype >= QC_TYPE_MAX);
     886
     887   return qrytype_str[qrytype];
     888 }

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