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) 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 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) { 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) 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) { 805 | dieif(qrytype >= QC_TYPE_MAX); 806 | 807 | return qrytype_str[qrytype]; 808 | }