modules/qc/query_command.c

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

FUNCTIONS

This source file includes following functions.
  1. qc_sources_list_to_string
  2. QC_environ_to_string
  3. QC_query_command_to_string
  4. log_command
  5. QC_environ_free
  6. QC_free
  7. QC_fill
  8. QC_environ_new
  9. QC_create
  10. QC_get_qrytype

   1 /***************************************
   2   $Revision: 1.44 $
   3 
   4   Query command module (qc).  This is what the whois query gets stored as in
   5   memory.
   6 
   7   Status: NOT REVUED, TESTED
   8 
   9   ******************/ /******************
  10   Filename            : query_command.c
  11   Author              : ottrey@ripe.net
  12   Modifications by    : marek@ripe.net
  13   ******************/ /******************
  14   Copyright (c) 1999                              RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32   ***************************************/
  33 #include <stdlib.h>
  34 #include <stdio.h>
  35 #include <string.h>
  36 #include <ctype.h>
  37 
  38 #define QC_IMPL
  39 
  40 #include "query_command.h"
  41 #include "defs.h"
  42 #include "constants.h"
  43 #include "which_keytypes.h"
  44 #include "memwrap.h"
  45 
  46 #include "ca_configFns.h"
  47 #include "ca_dictSyms.h"
  48 #include "ca_macros.h"
  49 #include "ca_srcAttribs.h"
  50 
  51 #include "getopt.h"
  52 
  53 #define MAX_OPT_ARG_C 20
  54 
  55 /*+ String sizes +*/
  56 #define STR_S   63
  57 #define STR_M   255
  58 #define STR_L   1023
  59 #define STR_XL  4095
  60 #define STR_XXL 16383
  61 
  62 /* 
  63    make sources list (allocated string).
  64    expects list to hold source handles
  65 */
  66 char *
  67 qc_sources_list_to_string(GList *list)
     /* [<][>][^][v][top][bottom][index][help] */
  68 {
  69   char *result = NULL;
  70   int oldlen = 0;
  71   GList *qitem;
  72 
  73   for( qitem = g_list_first(list);
  74        qitem != NULL;
  75        qitem = g_list_next(qitem)) {
  76     ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data );
  77     char *srcname = ca_get_srcname( source_hdl );
  78     
  79     dieif( wr_realloc( (void **)& result, oldlen + strlen(srcname) + 2)
  80            != UT_OK);
  81     if(oldlen > 0) {
  82       strcat(result, ",");
  83     }
  84     strcat(result, srcname);
  85   }
  86 
  87   return result;
  88 }
  89 
  90 /* QC_environ_to_string() */
  91 /*++++++++++++++++++++++++++++++++++++++
  92   Convert the query_environ to a string.
  93 
  94   Query_environ *query_environ The query_environ to be converted.
  95    
  96   More:
  97   +html+ <PRE>
  98   Authors:
  99         ottrey
 100   +html+ </PRE><DL COMPACT>
 101   +html+ <DT>Online References:
 102   +html+ <DD><UL>
 103   +html+ </UL></DL>
 104 
 105   ++++++++++++++++++++++++++++++++++++++*/
 106 char *QC_environ_to_string(Query_environ qe) {
     /* [<][>][^][v][top][bottom][index][help] */
 107   char *result;
 108   char *str1;
 109   char str2[IP_ADDRSTR_MAX];
 110   char result_buf[STR_XL];
 111 
 112   str1 = qc_sources_list_to_string(qe.sources_list);
 113   
 114   if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) { 
 115     *str2 = '\0';
 116   }
 117   
 118   sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip, 
 119           qe.k?"on":"off", 
 120           str1, 
 121           (qe.version == NULL) ? "?" : qe.version,
 122           *str2 == '\0' ? "" : ", passedIP=",
 123           *str2 == '\0' ? "" : str2
 124           );
 125   
 126   wr_free(str1);
 127 
 128   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);  
 129 
 130   strcpy(result, result_buf);
 131   
 132   return result;
 133   
 134 } /* QC_environ_to_string() */
 135 
 136 /* QC_query_command_to_string() */
 137 /*++++++++++++++++++++++++++++++++++++++
 138   Convert the query_command to a string.
 139 
 140   Query_command *query_command The query_command to be converted.
 141    
 142   More:
 143   +html+ <PRE>
 144   Authors:
 145         ottrey
 146   +html+ </PRE><DL COMPACT>
 147   +html+ <DT>Online References:
 148   +html+ <DD><UL>
 149   +html+ </UL></DL>
 150 
 151   ++++++++++++++++++++++++++++++++++++++*/
 152 char *QC_query_command_to_string(Query_command *query_command) {
     /* [<][>][^][v][top][bottom][index][help] */
 153   char *result;
 154   char result_buf[STR_XL];
 155   char *str1;
 156   char *str2;
 157   char *str3;
 158 
 159   str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names());
 160   str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names());
 161   str3 = WK_to_string(query_command->keytypes_bitmap);
 162   
 163   sprintf(result_buf, "Query_command : inv_attrs=%s, recursive=%s, object_type=%s, (e=%d,g=%d,l=%d,m=%d,q=%d,t=%d,v=%d,x=%d,F=%d,K=%d,L=%d,M=%d,R=%d,S=%d), possible keytypes=%s, keys=[%s]",
 164           str1,
 165           query_command->recursive?"y":"n",
 166           str2,
 167           query_command->e,
 168           query_command->g,
 169           query_command->l,
 170           query_command->m,
 171           query_command->q,
 172           query_command->t,
 173           query_command->v,
 174           query_command->x,
 175           query_command->fast,
 176           query_command->filtered,
 177           query_command->L,
 178           query_command->M,
 179           query_command->R,
 180           query_command->S,
 181           str3,
 182           query_command->keys);
 183   wr_free(str1);
 184   wr_free(str2);
 185   wr_free(str3);
 186 
 187   dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);  
 188   strcpy(result, result_buf);
 189 
 190   return result;
 191   
 192 } /* QC_query_command_to_string() */
 193 
 194 /* log_command() */
 195 /*++++++++++++++++++++++++++++++++++++++
 196   Log the command.
 197   This is more to do with Tracing.  And should/will get merged with a tracing
 198   module (when it is finalized.)
 199 
 200   char *query_str
 201   
 202   Query_command *query_command
 203    
 204   More:
 205   +html+ <PRE>
 206   Authors:
 207         ottrey
 208   +html+ </PRE><DL COMPACT>
 209   +html+ <DT>Online References:
 210   +html+ <DD><UL>
 211   +html+ </UL></DL>
 212 
 213   ++++++++++++++++++++++++++++++++++++++*/
 214 static void log_command(char *query_str, Query_command *query_command) {
     /* [<][>][^][v][top][bottom][index][help] */
 215   char *str;
 216 
 217   if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) {
 218     str = QC_query_command_to_string(query_command);
 219     ER_dbg_va(FAC_QC, ASP_QC_BUILD,
 220               "query=[%s]   %s", query_str, str);
 221     wr_free(str);
 222   }
 223 } /* log_command() */
 224 
 225 /* QC_environ_free() */
 226 /*++++++++++++++++++++++++++++++++++++++
 227   Free the query_environ.
 228 
 229   Query_command *qc query_environ to be freed.
 230 
 231   More:
 232   +html+ <PRE>
 233   Authors:
 234         ottrey
 235   +html+ </PRE><DL COMPACT>
 236   +html+ <DT>Online References:
 237   +html+ <DD><UL>
 238   +html+ </UL></DL>
 239 
 240   ++++++++++++++++++++++++++++++++++++++*/
 241 void QC_environ_free(Query_environ *qe) {
     /* [<][>][^][v][top][bottom][index][help] */
 242   if (qe != NULL) {
 243     if (qe->version != NULL) {
 244       wr_free(qe->version);
 245     }
 246 
 247     if (qe->sources_list != NULL) {
 248       g_list_free(qe->sources_list); 
 249       qe->sources_list=NULL;
 250     }
 251     wr_free(qe);
 252   }
 253 } /* QC_environ_free() */
 254 
 255 /* QC_free() */
 256 /*++++++++++++++++++++++++++++++++++++++
 257   Free the query_command.
 258 
 259   Query_command *qc query_command to be freed.
 260 
 261   XXX I'm not sure the bitmaps will get freed.
 262   qc->inv_attrs_bitmap
 263   qc->object_type_bitmap
 264   qc->keytypes_bitmap
 265 
 266   More:
 267   +html+ <PRE>
 268   Authors:
 269         ottrey
 270   +html+ </PRE><DL COMPACT>
 271   +html+ <DT>Online References:
 272   +html+ <DD><UL>
 273   +html+ </UL></DL>
 274 
 275   ++++++++++++++++++++++++++++++++++++++*/
 276 void QC_free(Query_command *qc) {
     /* [<][>][^][v][top][bottom][index][help] */
 277   if (qc != NULL) {
 278     if (qc->keys != NULL) {
 279       wr_free(qc->keys);
 280     }
 281     wr_free(qc);
 282   }
 283 } /* QC_free() */
 284 
 285 
 286 
 287 /* QC_fill() */
 288 /*++++++++++++++++++++++++++++++++++++++
 289   Create a new query_command.
 290 
 291   
 292   
 293   char *query_str The garden variety whois query string.
 294 
 295   Query_environ *qe the environment
 296 
 297   Pre-condition: 
 298 
 299   Returns -1 when query incorrect, 0 otherwise
 300 
 301   More:
 302   +html+ <PRE>
 303   Authors:
 304         ottrey - original code
 305         marek - modified for my getopts, multiple sources;
 306                 and generally cleaned.
 307   +html+ </PRE><DL COMPACT>
 308   +html+ <DT>Online References:
 309   +html+ <DD><UL>
 310   +html+ </UL></DL>
 311 
 312   ++++++++++++++++++++++++++++++++++++++*/
 313 static
 314 int QC_fill(char *query_str, 
     /* [<][>][^][v][top][bottom][index][help] */
 315              Query_command *query_command,
 316              Query_environ *qe) {
 317   
 318   int c;
 319   int synerrflg = 0;
 320   int badparerr = 0;
 321   int minusk = 0;
 322   char *inv_attrs_str = NULL;
 323   char *object_types_str = NULL;
 324   int opt_argc;
 325   gchar **opt_argv;
 326   char *value;
 327   char *tmp_query_str;
 328   int key_length;
 329   int i;
 330   int index;
 331   int type;
 332   int attr;
 333   char str_buf[STR_XL];
 334   getopt_state_t *gst = NULL;
 335 
 336   query_command->d = 0;
 337   query_command->e = 0;
 338   query_command->g = 0;
 339   query_command->inv_attrs_bitmap = MA_new(MA_END);
 340   query_command->recursive = 1;  /* Recursion is on by default. */
 341   query_command->l = 0;
 342   query_command->m = 0;
 343   query_command->q = -1;
 344   query_command->t = -1;
 345   query_command->v = -1;
 346   query_command->x = 0;
 347   query_command->fast = 0;
 348   query_command->filtered = 0;
 349   query_command->L = 0;
 350   query_command->M = 0;
 351   query_command->R = 0;
 352   query_command->S = 0;
 353 
 354   /* XXX UGLY - "all zeros" in object_type_bitmap means the same as 
 355      "all ones". To limit the inconsistency, this is changed at the end 
 356      of this function, so outside "all zeros" is an illegal value. */
 357   query_command->object_type_bitmap = MA_new(MA_END);
 358   /*
 359   query_command->keytypes_bitmap = MA_new(MA_END);
 360   */
 361   query_command->keys = NULL;
 362 
 363   /* This is so Marek can't crash me :-) */
 364   /* Side Effect - query keys are subsequently cut short to STR_S size. */
 365 
 366   dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK);  
 367   strncpy(tmp_query_str, query_str, STR_S);
 368 
 369   /* Create the arguments. */
 370   /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */
 371   opt_argv = g_strsplit(tmp_query_str, " ", MAX_OPT_ARG_C);
 372 
 373   /* Determine the number of arguments. */
 374   for (opt_argc=0; opt_argv[opt_argc] != NULL; opt_argc++);
 375 
 376   dieif( (gst = mg_new(0)) == NULL );
 377   
 378   while ((c = mg_getopt(opt_argc, opt_argv, "adegi:klrmq:s:t:v:xFKLMRST:V:", 
 379                         gst)) != EOF) {
 380     switch (c) {
 381       case 'a':
 382         /* Remove any user specified sources from the sources list. */
 383         /* free the list only, do not touch the elements */
 384         g_list_free(qe->sources_list); 
 385         qe->sources_list=NULL;
 386 
 387         /* Add all the config sources to the sources list. */
 388         {
 389           int i;
 390           ca_dbSource_t *hdl;
 391           
 392           for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
 393             qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
 394           }
 395         }
 396 
 397 
 398       break;
 399 
 400       case 'e':
 401         query_command->e=1;
 402       break;
 403 
 404       case 'd':
 405         query_command->d=1;
 406       break;
 407 
 408       case 'g':
 409         query_command->g=1;
 410       break;
 411 
 412       case 'i':
 413         if (gst->optarg != NULL) {
 414           char *hackstr = NULL;
 415 
 416           inv_attrs_str = gst->optarg;
 417           /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */
 418           /* I particularly object to this because it references attributes that should only be 
 419              defined in XML - but I don't see a simplier more robust way of doing this hack.
 420              :-( - ottrey 8/12/99 
 421              ** removed a memory leak - MB, 1/08/00
 422              */
 423           if (   strcmp(inv_attrs_str, "pn") == 0 
 424               || strcmp(inv_attrs_str, "ro") == 0) {
 425             wr_malloc( (void **)& hackstr, 24);  /* make a copy */
 426             strcpy(hackstr, "ac,tc,zc,ah");      
 427             inv_attrs_str = hackstr;
 428           }
 429           while (*inv_attrs_str) {
 430             index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value);
 431             if (index == -1) {
 432               attr = -1;
 433               strcpy(str_buf, "");
 434               sprintf(str_buf, "Unknown attribute encountered.\n"); /* YYY configurable constant: text  */
 435               SK_cd_puts(&(qe->condat), str_buf);
 436               badparerr++;
 437             }
 438             else {
 439               mask_t inv_attr_mask = MA_new(INV_ATTR_MASK);
 440               attr = DF_get_attribute_index(index);
 441               if ( MA_isset(inv_attr_mask, attr) == 1 ) {
 442                 /* Add the attr to the bitmap. */
 443                 MA_set(&(query_command->inv_attrs_bitmap), attr, 1);
 444               }
 445               else {
 446                 strcpy(str_buf, "");
 447                 sprintf(str_buf, "\"%s\" is not an inverse searchable attribute.\n", (DF_get_attribute_aliases())[index]); /* YYY configurable constant: text  */
 448                 SK_cd_puts(&(qe->condat), str_buf);
 449                 badparerr++;
 450               }
 451             } 
 452           } /* while () */
 453 
 454           if( hackstr != NULL) {
 455             wr_free(hackstr);
 456           }
 457         } /* if () */
 458       break;
 459 
 460       case 'k':
 461         minusk = 1;
 462       break;
 463 
 464       case 'r':
 465         query_command->recursive=0;       /* Unset recursion */
 466       break;
 467 
 468       case 'l':
 469         query_command->l=1;
 470       break;
 471 
 472       case 'm':
 473         query_command->m=1;
 474       break;
 475 
 476       case 'q':
 477         if (gst->optarg != NULL) {
 478           index = getsubopt(&gst->optarg, DF_get_server_queries(), &value);
 479           if (index == -1) {
 480             synerrflg++;
 481           }
 482           else {
 483             query_command->q = index;
 484           } 
 485         } /* if () */
 486       break;
 487 
 488       case 's':
 489         if (gst->optarg != NULL) {
 490           char *token, *cursor = gst->optarg;
 491           ca_dbSource_t *handle;
 492           
 493           /* Remove any sources from the sources list. */
 494           g_list_free(qe->sources_list); 
 495           qe->sources_list=NULL;
 496           
 497           /* go through specified sources */
 498           while( (token = strsep( &cursor, "," )) != NULL ) {
 499             
 500             if( (handle = ca_get_SourceHandleByName(token)) != NULL ) {
 501               /* append */
 502               qe->sources_list 
 503                 = g_list_append(qe->sources_list, (void *) handle );
 504             }
 505             else {
 506               /* bail out */
 507               
 508               SK_cd_printf(&(qe->condat), 
 509                            "%% Unknown source %s requested.\n",token ); /* YYY configurable constant: text  */
 510               
 511               /* XXX error */
 512               badparerr++;
 513               
 514             } /* if handle not null */
 515           } /* while sources */
 516         } /* if argument present */
 517         break;
 518         
 519       case 't':
 520         if (gst->optarg != NULL) {
 521           object_types_str = gst->optarg;
 522           while (*object_types_str) {
 523             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
 524             if (index == -1) {
 525               strcpy(str_buf, "");
 526               sprintf(str_buf, "Unknown object encountered.\n"); /* YYY configurable constant: text  */
 527               SK_cd_puts(&(qe->condat), str_buf);
 528               badparerr++;
 529             }
 530             else {
 531               type = DF_get_class_index(index);
 532               query_command->t=type;
 533             }
 534           }
 535         }
 536       break;
 537 
 538       case 'v':
 539         if (gst->optarg != NULL) {
 540           object_types_str = gst->optarg;
 541           if (*object_types_str) {
 542             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
 543             if (index == -1) {
 544               strcpy(str_buf, "");
 545               sprintf(str_buf, "Unknown object encountered.\n"); /* YYY configurable constant: text  */
 546               SK_cd_puts(&(qe->condat), str_buf);
 547               badparerr++;
 548             }
 549             else {
 550               type = DF_get_class_index(index);
 551               query_command->v=type;
 552             }
 553           }
 554         }
 555       break;
 556 
 557       case 'x':
 558         query_command->x=1;
 559       break;
 560 
 561       case 'F':
 562         query_command->fast=1;
 563         query_command->recursive=0; /* implies no recursion */
 564       break;
 565 
 566       case 'K':
 567         query_command->filtered=1;
 568         query_command->recursive=0; /* implies no recursion */
 569       break;
 570 
 571       case 'L':
 572         query_command->L=1;
 573       break;
 574 
 575       case 'M':
 576         query_command->M=1;
 577       break;
 578 
 579       case 'R':
 580         query_command->R=1;
 581       break;
 582 
 583       case 'S':
 584         query_command->S=1;
 585       break;
 586 
 587       case 'T':
 588         if (gst->optarg != NULL) {
 589           /* parse the specification */
 590           object_types_str = gst->optarg;
 591           while (*object_types_str) {
 592             index = getsubopt(&object_types_str, DF_get_class_aliases(), &value);
 593             if (index == -1) {
 594               strcpy(str_buf, "");
 595               sprintf(str_buf, "Unknown object type encountered.\n"); /* YYY configurable constant: text  */
 596               SK_cd_puts(&(qe->condat), str_buf);
 597               badparerr++;
 598             }
 599             else {
 600               type = DF_get_class_index(index);
 601               /* Add the type to the bitmap. */
 602               MA_set(&(query_command->object_type_bitmap), type, 1);
 603             }
 604           }
 605         }
 606       break;
 607 
 608       case 'V':
 609         if (qe->version != NULL) {
 610           /* free up the old client info */
 611           wr_free(qe->version);
 612         }
 613         
 614         {
 615           char *token, *cursor = gst->optarg;
 616           while( (token = strsep( &cursor, "," )) != NULL ) {
 617             if(IP_addr_e2b( & (qe->pIP), token) 
 618                != IP_OK ) {
 619               /* means it was not an IP -> it was a version */
 620               dieif( wr_malloc( (void **)&(qe->version), 
 621                                 strlen(token)+1) != UT_OK);  
 622               strcpy(qe->version, token);
 623             }
 624           }
 625         }
 626       break;
 627 
 628       /* any other flag, including '?' and ':' errors */
 629       default:
 630         synerrflg++;
 631     }
 632   }
 633 
 634   /* copy the key */
 635 
 636   /* Work out the length of space needed */
 637   key_length = 1; /* for terminal '\0' */
 638   for (i=gst->optind ; i < opt_argc; i++) {
 639     /* length for the string + 1 for the '\0'+ 1 for the ' ' */
 640     if (opt_argv[i] != NULL) {
 641       key_length += strlen(opt_argv[i])+1;
 642     }
 643   }
 644   /* allocate */
 645   dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK);  
 646   /* copy */
 647   for (i=gst->optind; i < opt_argc; i++) {
 648     strcat(query_command->keys, opt_argv[i]);
 649     if ( (i + 1) < opt_argc) {
 650       strcat(query_command->keys, " ");
 651     }
 652   }
 653     
 654   /* if no error, process the key, otherwise don't bother */
 655   if ( ! synerrflg && ! badparerr ) { 
 656     /* convert the key to uppercase. */
 657     for (i=0; i <= key_length; i++) {
 658       query_command->keys[i] = toupper(query_command->keys[i]);
 659     }
 660     
 661     /* make the keytypes_bitmap. */
 662     query_command->keytypes_bitmap = WK_new(query_command->keys);
 663 
 664     /* fix the object type bitmap - turn "all zeros" into "all ones" */
 665     if( MA_bitcount(query_command->object_type_bitmap) == 0 ) {
 666       query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap);
 667     }
 668    
 669     /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then
 670        exclude the domains unless -d is set 
 671        XXX this must be kept in sync with new types */
 672     if( query_command->d == 0 
 673         && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS) 
 674              || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE )
 675              || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX )
 676              || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX )
 677              ) ) {
 678       
 679       MA_set(&(query_command->object_type_bitmap), C_DN , 0);
 680     }
 681 
 682     /* tracing */
 683     log_command(tmp_query_str, query_command);
 684 
 685     /* "keep connection" processing:
 686        when opening connection, -k may be alone or with a query
 687        later -k must appear alone (or there must be an empty line,
 688        or an error) for the connection to close.
 689     */
 690     if( minusk ) {
 691       if( qe->k == 0 ) { /* opening */ 
 692         qe->k = 1;
 693       }
 694       else { /* closing, if no key; otherwise keep open */
 695         if( key_length <= 1 ) {
 696           qe->k = 0;
 697         }
 698       }
 699     }
 700     
 701   } /* if no error */
 702 
 703   /* we don't need this anymore */
 704   wr_free(tmp_query_str);
 705   wr_free(gst);
 706 
 707   if(synerrflg > 0) { /* severe syntax error. Usage must be printed */
 708     return QC_SYNERR;
 709   }
 710   else if(badparerr > 0) { /* the requester has a clue. No Usage info */
 711     return QC_PARERR;
 712   }
 713   else {
 714     return 0;
 715   }
 716 } /* QC_fill() */
 717 
 718 /* QC_environ_new() */
 719 /*++++++++++++++++++++++++++++++++++++++
 720   Create a new query environment.
 721 
 722   More:
 723   +html+ <PRE>
 724   Authors:
 725         ottrey
 726   +html+ </PRE><DL COMPACT>
 727   +html+ <DT>Online References:
 728   +html+ <DD><UL>
 729   +html+ </UL></DL>
 730 
 731   ++++++++++++++++++++++++++++++++++++++*/
 732 Query_environ *QC_environ_new(char *ip, unsigned sock) {
     /* [<][>][^][v][top][bottom][index][help] */
 733   Query_environ *qe;
 734 
 735 
 736   dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK);  
 737   qe->condat.ip = ip;
 738   qe->condat.sock = sock;
 739 
 740   /* The source is initialized to include only the deflook sources */
 741   {
 742     int i;
 743     ca_dbSource_t *hdl;
 744     
 745     for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) {
 746       if( ca_get_srcdeflook(hdl) ) {
 747         qe->sources_list = g_list_append(qe->sources_list, (void *)hdl);
 748       }
 749     }
 750   }
 751   
 752   return qe;
 753 
 754 } /* QC_environ_new() */
 755 
 756 
 757 
 758 /*++ QC_create()
 759   
 760   try to parse the query and fill in the QC struct, setting 
 761   qc->query_type accordingly.
 762  
 763   by marek.
 764 ++++++++++++++++++++++++++++++++++++++*/
 765 Query_command *QC_create(char *input, Query_environ *qe)
     /* [<][>][^][v][top][bottom][index][help] */
 766 {
 767   Query_command *qc;
 768   /* allocate place for a copy of the input */
 769   char *copy = calloc(1,strlen(input)+1); 
 770   unsigned char *ci, *co;
 771   int qt;
 772   /* clean the string from junk - allow only known chars, something like
 773      tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd; 
 774 
 775      strip leading spaces too
 776   */
 777 
 778   dieif(copy == NULL);
 779 
 780   for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) {
 781     /* EMPTY */
 782   }
 783 
 784   for(co = (unsigned char *) copy; *ci != 0; ci++) {
 785     if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"     /* only those are allowed */
 786                "abcdefghijklmnopqrstuvwxyz"
 787                "0123456789-_:+=.,@/' \n", *ci) != NULL) {
 788       *(co++) = *ci;
 789     }
 790   }
 791 
 792   /* now delete whitespace chars at the end */
 793   co--;
 794   while( isspace(*co) ) {
 795     *co = '\0';
 796     co--;
 797   }
 798 
 799 
 800   dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK);
 801   
 802   if ( strlen(copy) == 0) {
 803     /* An empty query (Ie return) was sent */
 804     qc->query_type = QC_EMPTY;
 805   } 
 806   else {        /* else <==> input_length > 0 ) */
 807     /* parse query */
 808     qt = QC_fill(copy, qc, qe);
 809 
 810     if( qt == QC_SYNERR || qt == QC_PARERR ) {
 811       qc->query_type = qt;
 812     }
 813     else {
 814       /* Update the query environment */
 815       /* qe = QC_environ_update(qc, qe); */
 816 
 817       /* Only do a query if there are keys. */
 818       if (qc->keys == NULL || strlen(qc->keys) == 0 ) {
 819         if( strlen(qc->keys) == 0 
 820             && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) {
 821           qc->query_type = QC_TEMPLATE;
 822         }
 823         else {
 824           qc->query_type = QC_NOKEY;
 825         }
 826       }
 827       else {
 828         if ( strcmp(qc->keys, "HELP") == 0 ) {
 829           qc->query_type = QC_HELP;
 830         }
 831         /* So, a real query */
 832         else if( qc->filtered ) {
 833           qc->query_type = QC_FILTERED;
 834         }
 835         else {
 836           qc->query_type = QC_REAL;
 837         }
 838       }
 839     }
 840   }
 841 
 842   free(copy);
 843 
 844   return qc;
 845 }
 846 
 847 
 848 char *QC_get_qrytype(qc_qtype_t qrytype) {
     /* [<][>][^][v][top][bottom][index][help] */
 849   dieif(qrytype >= QC_TYPE_MAX);
 850 
 851   return qrytype_str[qrytype];
 852 }

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