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] */