1 | /*************************************** 2 | $Revision: 1.36 $ 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) 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) { 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) { 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) { 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) { 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) { 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, 315 | Query_command *query_command, 316 | Query_environ *qe) { 317 | 318 | int c; 319 | int errflg = 0; 320 | char *inv_attrs_str = NULL; 321 | char *object_types_str = NULL; 322 | char *sources_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 | GList *first_source; 336 | 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 | query_command->object_type_bitmap = MA_new(MA_END); 354 | /* 355 | query_command->keytypes_bitmap = MA_new(MA_END); 356 | */ 357 | query_command->keys = NULL; 358 | 359 | /* This is so Marek can't crash me :-) */ 360 | /* Side Effect - query keys are subsequently cut short to STR_S size. */ 361 | 362 | dieif( wr_calloc((void **)&tmp_query_str, 1, STR_S+1) != UT_OK); 363 | strncpy(tmp_query_str, query_str, STR_S); 364 | 365 | /* Create the arguments. */ 366 | /* This allows only a maximum of MAX_OPT_ARG_C words in the query. */ 367 | opt_argv = g_strsplit(tmp_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, "aegi: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 'g': 401 | query_command->g=1; 402 | break; 403 | 404 | case 'i': 405 | if (gst->optarg != NULL) { 406 | char *hackstr = NULL; 407 | 408 | inv_attrs_str = gst->optarg; 409 | /* Now a really stupid hard-coded hack to support "pn" being a synonym for "ac,tc,zc,ah" */ 410 | /* I particularly object to this because it references attributes that should only be 411 | defined in XML - but I don't see a simplier more robust way of doing this hack. 412 | :-( - ottrey 8/12/99 413 | ** removed a memory leak - MB, 1/08/00 414 | */ 415 | if ( strcmp(inv_attrs_str, "pn") == 0 416 | || strcmp(inv_attrs_str, "ro") == 0) { 417 | wr_malloc( (void **)& hackstr, 24); 418 | strcpy(hackstr, "ac,tc,zc,ah"); 419 | inv_attrs_str = hackstr; 420 | } 421 | while (*inv_attrs_str) { 422 | index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value); 423 | if (index == -1) { 424 | attr = -1; 425 | strcpy(str_buf, ""); 426 | sprintf(str_buf, "Unknown attribute encountered.\n"); 427 | SK_cd_puts(&(qe->condat), str_buf); 428 | errflg++; 429 | } 430 | else { 431 | mask_t inv_attr_mask = MA_new(INV_ATTR_MASK); 432 | attr = DF_get_attribute_index(index); 433 | if ( MA_isset(inv_attr_mask, attr) == 1 ) { 434 | /* Add the attr to the bitmap. */ 435 | MA_set(&(query_command->inv_attrs_bitmap), attr, 1); 436 | } 437 | else { 438 | strcpy(str_buf, ""); 439 | sprintf(str_buf, "\"%s\" does not belong to inv_attr.\n", (DF_get_attribute_aliases())[index]); 440 | SK_cd_puts(&(qe->condat), str_buf); 441 | errflg++; 442 | } 443 | } 444 | } /* while () */ 445 | 446 | if( hackstr != NULL) { 447 | wr_free(hackstr); 448 | } 449 | } /* if () */ 450 | break; 451 | 452 | case 'k': 453 | /* triggering flag == a XOR operation */ 454 | qe->k ^= 1; 455 | break; 456 | 457 | case 'r': 458 | query_command->recursive=0; /* Unset recursion */ 459 | break; 460 | 461 | case 'l': 462 | query_command->l=1; 463 | break; 464 | 465 | case 'm': 466 | query_command->m=1; 467 | break; 468 | 469 | case 'q': 470 | if (gst->optarg != NULL) { 471 | index = getsubopt(&gst->optarg, DF_get_server_queries(), &value); 472 | if (index == -1) { 473 | errflg++; 474 | } 475 | else { 476 | query_command->q = index; 477 | } 478 | } /* if () */ 479 | break; 480 | 481 | case 's': 482 | if (gst->optarg != NULL) { 483 | char *token, *cursor = gst->optarg; 484 | ca_dbSource_t *handle; 485 | 486 | /* Remove any sources from the sources list. */ 487 | g_list_free(qe->sources_list); 488 | qe->sources_list=NULL; 489 | 490 | /* go through specified sources */ 491 | while( (token = strsep( &cursor, "," )) != NULL ) { 492 | 493 | if( (handle = ca_get_SourceHandleByName(token)) != NULL ) { 494 | /* append */ 495 | qe->sources_list 496 | = g_list_append(qe->sources_list, (void *) handle ); 497 | } 498 | else { 499 | /* bail out */ 500 | strcpy(str_buf, ""); 501 | sprintf(str_buf, "Unknown source %s encountered.\n",token ); 502 | SK_cd_puts(&(qe->condat), str_buf); 503 | 504 | /* XXX error */ 505 | errflg++; 506 | 507 | } /* if handle not null */ 508 | } /* while sources */ 509 | } /* if argument present */ 510 | break; 511 | 512 | case 't': 513 | if (gst->optarg != NULL) { 514 | object_types_str = gst->optarg; 515 | while (*object_types_str) { 516 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 517 | if (index == -1) { 518 | strcpy(str_buf, ""); 519 | sprintf(str_buf, "Unknown object encountered.\n"); 520 | SK_cd_puts(&(qe->condat), str_buf); 521 | errflg++; 522 | } 523 | else { 524 | type = DF_get_class_index(index); 525 | query_command->t=type; 526 | } 527 | } 528 | } 529 | break; 530 | 531 | case 'v': 532 | if (gst->optarg != NULL) { 533 | object_types_str = gst->optarg; 534 | if (*object_types_str) { 535 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 536 | if (index == -1) { 537 | strcpy(str_buf, ""); 538 | sprintf(str_buf, "Unknown object encountered.\n"); 539 | SK_cd_puts(&(qe->condat), str_buf); 540 | errflg++; 541 | } 542 | else { 543 | type = DF_get_class_index(index); 544 | query_command->v=type; 545 | } 546 | } 547 | } 548 | break; 549 | 550 | case 'x': 551 | query_command->x=1; 552 | break; 553 | 554 | case 'F': 555 | query_command->fast=1; 556 | query_command->recursive=0; /* implies no recursion */ 557 | break; 558 | 559 | case 'K': 560 | query_command->filtered=1; 561 | query_command->recursive=0; /* implies no recursion */ 562 | break; 563 | 564 | case 'L': 565 | query_command->L=1; 566 | break; 567 | 568 | case 'M': 569 | query_command->M=1; 570 | break; 571 | 572 | case 'R': 573 | query_command->R=1; 574 | break; 575 | 576 | case 'S': 577 | query_command->S=1; 578 | break; 579 | 580 | case 'T': 581 | if (gst->optarg != NULL) { 582 | object_types_str = gst->optarg; 583 | while (*object_types_str) { 584 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 585 | if (index == -1) { 586 | strcpy(str_buf, ""); 587 | sprintf(str_buf, "Unknown class encountered.\n"); 588 | SK_cd_puts(&(qe->condat), str_buf); 589 | errflg++; 590 | } 591 | else { 592 | type = DF_get_class_index(index); 593 | /* Add the type to the bitmap. */ 594 | MA_set(&(query_command->object_type_bitmap), type, 1); 595 | } 596 | } 597 | } 598 | break; 599 | 600 | case 'V': 601 | if (qe->version != NULL) { 602 | /* free up the old client info */ 603 | wr_free(qe->version); 604 | } 605 | 606 | { 607 | char *token, *cursor = gst->optarg; 608 | while( (token = strsep( &cursor, "," )) != NULL ) { 609 | if(IP_addr_e2b( & (qe->pIP), token) 610 | != IP_OK ) { 611 | /* means it was not an IP -> it was a version */ 612 | dieif( wr_malloc( (void **)&(qe->version), 613 | strlen(token)+1) != UT_OK); 614 | strcpy(qe->version, token); 615 | } 616 | } 617 | } 618 | break; 619 | 620 | /* any other flag, including '?' and ':' errors */ 621 | default: 622 | errflg++; 623 | } 624 | } 625 | 626 | /* copy the key */ 627 | 628 | /* Work out the length of space needed */ 629 | key_length = 1; /* for terminal '\0' */ 630 | for (i=gst->optind ; i < opt_argc; i++) { 631 | /* length for the string + 1 for the '\0'+ 1 for the ' ' */ 632 | if (opt_argv[i] != NULL) { 633 | key_length += strlen(opt_argv[i])+1; 634 | } 635 | } 636 | /* allocate */ 637 | dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK); 638 | /* copy */ 639 | for (i=gst->optind; i < opt_argc; i++) { 640 | strcat(query_command->keys, opt_argv[i]); 641 | if ( (i + 1) < opt_argc) { 642 | strcat(query_command->keys, " "); 643 | } 644 | } 645 | 646 | /* if no error, process the key, otherwise don't bother */ 647 | if ( ! errflg ) { 648 | /* convert the key to uppercase. */ 649 | for (i=0; i <= key_length; i++) { 650 | query_command->keys[i] = toupper(query_command->keys[i]); 651 | } 652 | 653 | /* make the keytypes_bitmap. */ 654 | query_command->keytypes_bitmap = WK_new(query_command->keys); 655 | 656 | /* tracing */ 657 | if ( CO_get_comnd_logging() == 1 ) { 658 | log_command(tmp_query_str, query_command); 659 | } 660 | } /* if no error */ 661 | 662 | /* we don't need this anymore */ 663 | wr_free(tmp_query_str); 664 | wr_free(gst); 665 | 666 | return (errflg) ? -1 : 0; /* return -1 on error */ 667 | 668 | } /* QC_fill() */ 669 | 670 | /* QC_environ_new() */ 671 | /*++++++++++++++++++++++++++++++++++++++ 672 | Create a new query environment. 673 | 674 | More: 675 | +html+ <PRE> 676 | Authors: 677 | ottrey 678 | +html+ </PRE><DL COMPACT> 679 | +html+ <DT>Online References: 680 | +html+ <DD><UL> 681 | +html+ </UL></DL> 682 | 683 | ++++++++++++++++++++++++++++++++++++++*/ 684 | Query_environ *QC_environ_new(char *ip, unsigned sock) { 685 | Query_environ *qe; 686 | 687 | 688 | dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK); 689 | qe->condat.ip = ip; 690 | qe->condat.sock = sock; 691 | 692 | /* The source is initialized to include only the deflook sources */ 693 | { 694 | int i; 695 | ca_dbSource_t *hdl; 696 | 697 | for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) { 698 | if( ca_get_srcdeflook(hdl) ) { 699 | qe->sources_list = g_list_append(qe->sources_list, (void *)hdl); 700 | } 701 | } 702 | } 703 | 704 | return qe; 705 | 706 | } /* QC_environ_new() */ 707 | 708 | 709 | 710 | /*++ QC_create() 711 | 712 | try to parse the query and fill in the QC struct, setting 713 | qc->query_type accordingly. 714 | 715 | by marek. 716 | ++++++++++++++++++++++++++++++++++++++*/ 717 | Query_command *QC_create(char *input, Query_environ *qe) 718 | { 719 | Query_command *qc; 720 | /* allocate place for a copy of the input */ 721 | char *copy = calloc(1,strlen(input)+1); 722 | char *ci, *co; 723 | /* clean the string from junk - allow only known chars, something like 724 | tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd; 725 | */ 726 | 727 | dieif(copy == NULL); 728 | 729 | for(ci = input, co = copy; *ci != 0; ci++) { 730 | if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */ 731 | "abcdefghijklmnopqrstuvwxyz" 732 | "0123456789-_:+=.,@/' \n", *ci) != NULL) { 733 | *(co++) = *ci; 734 | } 735 | } 736 | 737 | /* now delete whitespace chars at the end */ 738 | co--; 739 | while( isspace(*co) ) { 740 | *co = '\0'; 741 | co--; 742 | } 743 | 744 | 745 | dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK); 746 | 747 | if ( strlen(copy) == 0) { 748 | /* An empty query (Ie return) was sent */ 749 | qc->query_type = QC_EMPTY; 750 | } 751 | else { /* else <==> input_length > 0 ) */ 752 | /* parse query */ 753 | 754 | if( QC_fill(copy, qc, qe) < 0 ) { 755 | qc->query_type = QC_ERROR; 756 | } 757 | else { 758 | /* Update the query environment */ 759 | /* qe = QC_environ_update(qc, qe); */ 760 | 761 | /* Only do a query if there are keys. */ 762 | if (qc->keys == NULL || strlen(qc->keys) == 0 ) { 763 | if( strlen(qc->keys) == 0 764 | && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) { 765 | qc->query_type = QC_TEMPLATE; 766 | } 767 | else { 768 | qc->query_type = QC_NOKEY; 769 | } 770 | } 771 | else { 772 | if ( strcmp(qc->keys, "HELP") == 0 ) { 773 | qc->query_type = QC_HELP; 774 | } 775 | /* So, a real query */ 776 | else if( qc->filtered ) { 777 | qc->query_type = QC_FILTERED; 778 | } 779 | else { 780 | qc->query_type = QC_REAL; 781 | } 782 | } 783 | } 784 | } 785 | 786 | free(copy); 787 | 788 | return qc; 789 | } 790 | 791 | 792 | char *QC_get_qrytype(qc_qtype_t qrytype) { 793 | dieif(qrytype >= QC_TYPE_MAX); 794 | 795 | return qrytype_str[qrytype]; 796 | }