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

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