## 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.38 $
       3
       4   Query command module (qc).  This is what the whois query gets stored as in
       5   memory.
       6
       7   Status: NOT REVUED, TESTED
       8
       9   ******************/ /******************
      10   Filename            : query_command.c
      11   Author              : ottrey@ripe.net
      12   Modifications by    : marek@ripe.net
      13   ******************/ /******************
      14   Copyright (c) 1999                              RIPE NCC
      15
      16   All Rights Reserved
      17
      18   Permission to use, copy, modify, and distribute this software and its
      19   documentation for any purpose and without fee is hereby granted,
      20   provided that the above copyright notice appear in all copies and that
      21   both that copyright notice and this permission notice appear in
      22   supporting documentation, and that the name of the author not be
      23   used in advertising or publicity pertaining to distribution of the
      24   software without specific, written prior permission.
      25
      26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
      27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
      28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
      29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      32   ***************************************/
      33 #include <stdlib.h>
      34 #include <stdio.h>
      35 #include <string.h>
      36 #include <ctype.h>
      37
      38 #define QC_IMPL
      39
      40 #include "query_command.h"
      41 #include "defs.h"
      42 #include "constants.h"
      43 #include "which_keytypes.h"
      44 #include "memwrap.h"
      45
      46 #include "ca_configFns.h"
      47 #include "ca_dictSyms.h"
      48 #include "ca_macros.h"
      49 #include "ca_srcAttribs.h"
      50
      51 #include "getopt.h"
      52
      53 #define MAX_OPT_ARG_C 20
      54
      55 /*+ String sizes +*/
      56 #define STR_S   63
      57 #define STR_M   255
      58 #define STR_L   1023
      59 #define STR_XL  4095
      60 #define STR_XXL 16383
      61
      62 /*
      63    make sources list (allocated string).
      64    expects list to hold source handles
      65 */
      66 char *
      67 qc_sources_list_to_string(GList *list)
         /* [<][>][^][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   char *inv_attrs_str = NULL;
     322   char *object_types_str = NULL;
     323   int opt_argc;
     324   gchar **opt_argv;
     325   char *value;
     326   char *tmp_query_str;
     327   int key_length;
     328   int i;
     329   int index;
     330   int type;
     331   int attr;
     332   char str_buf[STR_XL];
     333   getopt_state_t *gst = NULL;
     334
     335   query_command->e = 0;
     336   query_command->g = 0;
     337   query_command->inv_attrs_bitmap = MA_new(MA_END);
     338   query_command->recursive = 1;  /* Recursion is on by default. */
     339   query_command->l = 0;
     340   query_command->m = 0;
     341   query_command->q = -1;
     342   query_command->t = -1;
     343   query_command->v = -1;
     344   query_command->x = 0;
     345   query_command->fast = 0;
     346   query_command->filtered = 0;
     347   query_command->L = 0;
     348   query_command->M = 0;
     349   query_command->R = 0;
     350   query_command->S = 0;
     351   query_command->object_type_bitmap = MA_new(MA_END);
     352   /*
     353   query_command->keytypes_bitmap = MA_new(MA_END);
     354   */
     355   query_command->keys = NULL;
     356
     357   /* This is so Marek can't crash me :-) */
     358   /* Side Effect - query keys are subsequently cut short to STR_S size. */
     359
     360   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);
     361   strncpy(tmp_query_str, query_str, STR_S);
     362
     363   /* Create the arguments. */
     364   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
     365   opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
     366
     367   /* Determine the number of arguments. */
     368   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
     369
     370   dieif( (gst = mg_new(0)) == NULL );
     371
     372   while ((c = mg_getopt(opt_argc, opt_argv, "aegi:klrmq:s:t:v:xFKLMRST:V:",
     373                         gst)) != EOF) {
     374     switch (c) {
     375       case 'a':
     376         /* Remove any user specified sources from the sources list. */
     377         /* free the list only, do not touch the elements */
     378         g_list_free(qe->sources_list);
     379         qe->sources_list=NULL;
     380
     381         /* Add all the config sources to the sources list. */
     382         {
     383           int i;
     384           ca_dbSource_t *hdl;
     385
     386           for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
     387             qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
     388           }
     389         }
     390
     391
     392       break;
     393
     394       case 'e':
     395         query_command->e=1;
     396       break;
     397
     398       case 'g':
     399         query_command->g=1;
     400       break;
     401
     402       case 'i':
     403         if (gst->optarg != NULL) {
     404           char *hackstr = NULL;
     405
     406           inv_attrs_str = gst->optarg;
     407           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
     408           /* I particularly object to this because it references attributes that should only be
     409              defined in XML - but I don't see a simplier more robust way of doing this hack.
     410              :-( - ottrey 8/12/99
     411              ** removed a memory leak - MB, 1/08/00
     412              */
     413           if (   strcmp(inv_attrs_str, "pn") == 0
     414               || strcmp(inv_attrs_str, "ro") == 0) {
     415             wr_malloc( (void **)& hackstr, 24);  /* make a copy */
     416             strcpy(hackstr, "ac,tc,zc,ah");
     417             inv_attrs_str = hackstr;
     418           }
     419           while (*inv_attrs_str) {
     420             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
     421             if (index == -1) {
     422               attr = -1;
     423               strcpy(str_buf, "");
     424               sprintf(str_buf, "Unknown attribute encountered.\n");
     425               SK_cd_puts(&(qe->condat), str_buf);
     426               badparerr++;
     427             }
     428             else {
     429               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
     430               attr = DF_get_attribute_index(index);
     431               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
     432                 /* Add the attr to the bitmap. */
     433                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
     434               }
     435               else {
     436                 strcpy(str_buf, "");
     437                 sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]);
     438                 SK_cd_puts(&(qe->condat), str_buf);
     439                 badparerr++;
     440               }
     441             }
     442           } /* while () */
     443
     444           if( hackstr != NULL) {
     445             wr_free(hackstr);
     446           }
     447         } /* if () */
     448       break;
     449
     450       case 'k':
     451         /* triggering flag == a XOR operation */
     452         qe->k ^= 1;
     453       break;
     454
     455       case 'r':
     456         query_command->recursive=0;       /* Unset recursion */
     457       break;
     458
     459       case 'l':
     460         query_command->l=1;
     461       break;
     462
     463       case 'm':
     464         query_command->m=1;
     465       break;
     466
     467       case 'q':
     468         if (gst->optarg != NULL) {
     469           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
     470           if (index == -1) {
     471             synerrflg++;
     472           }
     473           else {
     474             query_command->q = index;
     475           }
     476         } /* if () */
     477       break;
     478
     479       case 's':
     480         if (gst->optarg != NULL) {
     481           char *token, *cursor = gst->optarg;
     482           ca_dbSource_t *handle;
     483
     484           /* Remove any sources from the sources list. */
     485           g_list_free(qe->sources_list);
     486           qe->sources_list=NULL;
     487
     488           /* go through specified sources */
     489           while( (token = strsep( &cursor, "," )) != NULL ) {
     490
     491             if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
     492               /* append */
     493               qe->sources_list
     494                 = g_list_append(qe->sources_list, (void *) handle );
     495             }
     496             else {
     497               /* bail out */
     498
     499               SK_cd_printf(&(qe->condat),
     500                            "%% Unknown source %s requested.\n",token );
     501
     502               /* XXX error */
     503               badparerr++;
     504
     505             } /* if handle not null */
     506           } /* while sources */
     507         } /* if argument present */
     508         break;
     509
     510       case 't':
     511         if (gst->optarg != NULL) {
     512           object_types_str = gst->optarg;
     513           while (*object_types_str) {
     514             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     515             if (index == -1) {
     516               strcpy(str_buf, "");
     517               sprintf(str_buf, "Unknown object encountered.\n");
     518               SK_cd_puts(&(qe->condat), str_buf);
     519               badparerr++;
     520             }
     521             else {
     522               type = DF_get_class_index(index);
     523               query_command->t=type;
     524             }
     525           }
     526         }
     527       break;
     528
     529       case 'v':
     530         if (gst->optarg != NULL) {
     531           object_types_str = gst->optarg;
     532           if (*object_types_str) {
     533             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     534             if (index == -1) {
     535               strcpy(str_buf, "");
     536               sprintf(str_buf, "Unknown object encountered.\n");
     537               SK_cd_puts(&(qe->condat), str_buf);
     538               badparerr++;
     539             }
     540             else {
     541               type = DF_get_class_index(index);
     542               query_command->v=type;
     543             }
     544           }
     545         }
     546       break;
     547
     548       case 'x':
     549         query_command->x=1;
     550       break;
     551
     552       case 'F':
     553         query_command->fast=1;
     554         query_command->recursive=0; /* implies no recursion */
     555       break;
     556
     557       case 'K':
     558         query_command->filtered=1;
     559         query_command->recursive=0; /* implies no recursion */
     560       break;
     561
     562       case 'L':
     563         query_command->L=1;
     564       break;
     565
     566       case 'M':
     567         query_command->M=1;
     568       break;
     569
     570       case 'R':
     571         query_command->R=1;
     572       break;
     573
     574       case 'S':
     575         query_command->S=1;
     576       break;
     577
     578       case 'T':
     579         if (gst->optarg != NULL) {
     580           object_types_str = gst->optarg;
     581           while (*object_types_str) {
     582             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
     583             if (index == -1) {
     584               strcpy(str_buf, "");
     585               sprintf(str_buf, "Unknown obejct type encountered.\n");
     586               SK_cd_puts(&(qe->condat), str_buf);
     587               badparerr++;
     588             }
     589             else {
     590               type = DF_get_class_index(index);
     591               /* Add the type to the bitmap. */
     592               MA_set(&(query_command->object_type_bitmap), type, 1);
     593             }
     594           }
     595         }
     596       break;
     597
     598       case 'V':
     599         if (qe->version != NULL) {
     600           /* free up the old client info */
     601           wr_free(qe->version);
     602         }
     603
     604         {
     605           char *token, *cursor = gst->optarg;
     606           while( (token = strsep( &cursor, "," )) != NULL ) {
     607             if(IP_addr_e2b( & (qe->pIP), token)
     608                != IP_OK ) {
     609               /* means it was not an IP -> it was a version */
     610               dieif( wr_malloc( (void **)&(qe->version),
     611                                 strlen(token)+1) != UT_OK);
     612               strcpy(qe->version, token);
     613             }
     614           }
     615         }
     616       break;
     617
     618       /* any other flag, including '?' and ':' errors */
     619       default:
     620         synerrflg++;
     621     }
     622   }
     623
     624   /* copy the key */
     625
     626   /* Work out the length of space needed */
     627   key_length = 1; /* for terminal '\0' */
     628   for (i=gst->optind ; i < opt_argc; i++) {
     629     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
     630     if (opt_argv[i] != NULL) {
     631       key_length += strlen(opt_argv[i])+1;
     632     }
     633   }
     634   /* allocate */
     635   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);
     636   /* copy */
     637   for (i=gst->optind; i < opt_argc; i++) {
     638     strcat(query_command->keys, opt_argv[i]);
     639     if ( (i + 1) < opt_argc) {
     640       strcat(query_command->keys, " ");
     641     }
     642   }
     643
     644   /* if no error, process the key, otherwise don't bother */
     645   if ( ! synerrflg && ! badparerr ) {
     646     /* convert the key to uppercase. */
     647     for (i=0; i <= key_length; i++) {
     648       query_command->keys[i] = toupper(query_command->keys[i]);
     649     }
     650
     651     /* make the keytypes_bitmap. */
     652     query_command->keytypes_bitmap = WK_new(query_command->keys);
     653
     654     /* tracing */
     655     log_command(tmp_query_str, query_command);
     656
     657   } /* if no error */
     658
     659   /* we don't need this anymore */
     660   wr_free(tmp_query_str);
     661   wr_free(gst);
     662
     663   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
     664     return QC_SYNERR;
     665   }
     666   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
     667     return QC_PARERR;
     668   }
     669   else {
     670     return 0;
     671   }
     672 } /* QC_fill() */
     673
     674 /* QC_environ_new() */
     675 /*++++++++++++++++++++++++++++++++++++++
     676   Create a new query environment.
     677
     678   More:
     679   +html+ <PRE>
     680   Authors:
     681         ottrey
     682   +html+ </PRE><DL COMPACT>
     683   +html+ <DT>Online References:
     684   +html+ <DD><UL>
     685   +html+ </UL></DL>
     686
     687   ++++++++++++++++++++++++++++++++++++++*/
     688 Query_environ *QC_environ_new(char *ip, unsigned sock) {
         /* [<][>][^][v][top][bottom][index][help] */
     689   Query_environ *qe;
     690
     691
     692   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);
     693   qe->condat.ip = ip;
     694   qe->condat.sock = sock;
     695
     696   /* The source is initialized to include only the deflook sources */
     697   {
     698     int i;
     699     ca_dbSource_t *hdl;
     700
     701     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
     702       if( ca_get_srcdeflook(hdl) ) {
     703         qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
     704       }
     705     }
     706   }
     707
     708   return qe;
     709
     710 } /* QC_environ_new() */
     711
     712
     713
     714 /*++ QC_create()
     715
     716   try to parse the query and fill in the QC struct, setting
     717   qc->query_type accordingly.
     718
     719   by marek.
     720 ++++++++++++++++++++++++++++++++++++++*/
     721 Query_command *QC_create(char *input, Query_environ *qe)
         /* [<][>][^][v][top][bottom][index][help] */
     722 {
     723   Query_command *qc;
     724   /* allocate place for a copy of the input */
     725   char *copy = calloc(1,strlen(input)+1);
     726   char *ci, *co;
     727   int qt;
     728   /* clean the string from junk - allow only known chars, something like
     729      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd;
     730
     731      strip leading spaces too
     732   */
     733
     734   dieif(copy == NULL);
     735
     736   for(ci = input; *ci != 0 && isspace(*ci); ci++) {
     737     /* EMPTY */
     738   }
     739
     740   for(co = copy; *ci != 0; ci++) {
     741     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
     742                "abcdefghijklmnopqrstuvwxyz"
     743                "0123456789-_:+=.,@/' \n", *ci) != NULL) {
     744       *(co++) = *ci;
     745     }
     746   }
     747
     748   /* now delete whitespace chars at the end */
     749   co--;
     750   while( isspace(*co) ) {
     751     *co = '\0';
     752     co--;
     753   }
     754
     755
     756   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
     757
     758   if ( strlen(copy) == 0) {
     759     /* An empty query (Ie return) was sent */
     760     qc->query_type = QC_EMPTY;
     761   }
     762   else {        /* else <==> input_length > 0 ) */
     763     /* parse query */
     764     qt = QC_fill(copy, qc, qe);
     765
     766     if( qt == QC_SYNERR || qt == QC_PARERR ) {
     767       qc->query_type = qt;
     768     }
     769     else {
     770       /* Update the query environment */
     771       /* qe = QC_environ_update(qc, qe); */
     772
     773       /* Only do a query if there are keys. */
     774       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
     775         if( strlen(qc->keys) == 0
     776             && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
     777           qc->query_type = QC_TEMPLATE;
     778         }
     779         else {
     780           qc->query_type = QC_NOKEY;
     781         }
     782       }
     783       else {
     784         if ( strcmp(qc->keys, "HELP") == 0 ) {
     785           qc->query_type = QC_HELP;
     786         }
     787         /* So, a real query */
     788         else if( qc->filtered ) {
     789           qc->query_type = QC_FILTERED;
     790         }
     791         else {
     792           qc->query_type = QC_REAL;
     793         }
     794       }
     795     }
     796   }
     797
     798   free(copy);
     799
     800   return qc;
     801 }
     802
     803
     804 char *QC_get_qrytype(qc_qtype_t qrytype) {
         /* [<][>][^][v][top][bottom][index][help] */
     805   dieif(qrytype >= QC_TYPE_MAX);
     806
     807   return qrytype_str[qrytype];
     808 }

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