1 | /*************************************** 2 | $Revision: 1.48 $ 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_dictionary.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 | /*++++++++++++++++++++++++++++++++++++++ 64 | make a list of sources. expects list to hold source handles 65 | 66 | char * 67 | qc_sources_list_to_string returns an allocated string, must be freed 68 | 69 | GList *list list of source handles (as defined by CA) 70 | 71 | ++++++++++++++++++++++++++++++++++++++*/ 72 | char * 73 | qc_sources_list_to_string(GList *list) 74 | { 75 | char *result = NULL; 76 | int oldlen = 0; 77 | GList *qitem; 78 | 79 | for( qitem = g_list_first(list); 80 | qitem != NULL; 81 | qitem = g_list_next(qitem)) { 82 | ca_dbSource_t *source_hdl = (ca_dbSource_t *) ( qitem->data ); 83 | char *srcname = ca_get_srcname( source_hdl ); 84 | 85 | dieif( wr_realloc( (void **)& result, oldlen + strlen(srcname) + 2) 86 | != UT_OK); 87 | if(oldlen > 0) { 88 | strcat(result, ","); 89 | } 90 | strcat(result, srcname); 91 | } 92 | 93 | return result; 94 | } 95 | 96 | /* QC_environ_to_string() */ 97 | /*++++++++++++++++++++++++++++++++++++++ 98 | Convert the query_environ to a string. 99 | 100 | Query_environ *query_environ The query_environ to be converted. 101 | 102 | More: 103 | +html+ <PRE> 104 | Authors: 105 | ottrey 106 | +html+ </PRE><DL COMPACT> 107 | +html+ <DT>Online References: 108 | +html+ <DD><UL> 109 | +html+ </UL></DL> 110 | 111 | ++++++++++++++++++++++++++++++++++++++*/ 112 | char *QC_environ_to_string(Query_environ qe) { 113 | char *result; 114 | char *str1; 115 | char str2[IP_ADDRSTR_MAX]; 116 | char result_buf[STR_XL]; 117 | 118 | str1 = qc_sources_list_to_string(qe.sources_list); 119 | 120 | if( IP_addr_b2a( &(qe.pIP), str2, IP_ADDRSTR_MAX) != IP_OK ) { 121 | *str2 = '\0'; 122 | } 123 | 124 | sprintf(result_buf, "host=%s, keep_connection=%s, sources=%s, version=%s%s%s", qe.condat.ip, 125 | qe.k?"on":"off", 126 | str1, 127 | (qe.version == NULL) ? "?" : qe.version, 128 | *str2 == '\0' ? "" : ", passedIP=", 129 | *str2 == '\0' ? "" : str2 130 | ); 131 | 132 | wr_free(str1); 133 | 134 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK); 135 | 136 | strcpy(result, result_buf); 137 | 138 | return result; 139 | 140 | } /* QC_environ_to_string() */ 141 | 142 | /* QC_query_command_to_string() */ 143 | /*++++++++++++++++++++++++++++++++++++++ 144 | Convert the query_command to a string. 145 | 146 | Query_command *query_command The query_command to be converted. 147 | 148 | More: 149 | +html+ <PRE> 150 | Authors: 151 | ottrey 152 | +html+ </PRE><DL COMPACT> 153 | +html+ <DT>Online References: 154 | +html+ <DD><UL> 155 | +html+ </UL></DL> 156 | 157 | ++++++++++++++++++++++++++++++++++++++*/ 158 | char *QC_query_command_to_string(Query_command *query_command) { 159 | char *result; 160 | char result_buf[STR_XL]; 161 | char *str1; 162 | char *str2; 163 | char *str3; 164 | 165 | str1 = MA_to_string(query_command->inv_attrs_bitmap, DF_get_attribute_names()); 166 | str2 = MA_to_string(query_command->object_type_bitmap, DF_get_class_names()); 167 | str3 = WK_to_string(query_command->keytypes_bitmap); 168 | 169 | 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]", 170 | str1, 171 | query_command->recursive?"y":"n", 172 | str2, 173 | query_command->e, 174 | query_command->g, 175 | query_command->l, 176 | query_command->m, 177 | query_command->q, 178 | query_command->t, 179 | query_command->v, 180 | query_command->x, 181 | query_command->fast, 182 | query_command->filtered, 183 | query_command->L, 184 | query_command->M, 185 | query_command->R, 186 | query_command->S, 187 | str3, 188 | query_command->keys); 189 | wr_free(str1); 190 | wr_free(str2); 191 | wr_free(str3); 192 | 193 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK); 194 | strcpy(result, result_buf); 195 | 196 | return result; 197 | 198 | } /* QC_query_command_to_string() */ 199 | 200 | /* log_command() */ 201 | /*++++++++++++++++++++++++++++++++++++++ 202 | Log the command. 203 | This is more to do with Tracing. And should/will get merged with a tracing 204 | module (when it is finalized.) 205 | 206 | char *query_str 207 | 208 | Query_command *query_command 209 | 210 | More: 211 | +html+ <PRE> 212 | Authors: 213 | ottrey 214 | +html+ </PRE><DL COMPACT> 215 | +html+ <DT>Online References: 216 | +html+ <DD><UL> 217 | +html+ </UL></DL> 218 | 219 | ++++++++++++++++++++++++++++++++++++++*/ 220 | static void log_command(char *query_str, Query_command *query_command) { 221 | char *str; 222 | 223 | if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) { 224 | str = QC_query_command_to_string(query_command); 225 | ER_dbg_va(FAC_QC, ASP_QC_BUILD, 226 | "query=[%s] %s", query_str, str); 227 | wr_free(str); 228 | } 229 | } /* log_command() */ 230 | 231 | /* QC_environ_free() */ 232 | /*++++++++++++++++++++++++++++++++++++++ 233 | Free the query_environ. 234 | 235 | Query_command *qc query_environ to be freed. 236 | 237 | More: 238 | +html+ <PRE> 239 | Authors: 240 | ottrey 241 | +html+ </PRE><DL COMPACT> 242 | +html+ <DT>Online References: 243 | +html+ <DD><UL> 244 | +html+ </UL></DL> 245 | 246 | ++++++++++++++++++++++++++++++++++++++*/ 247 | void QC_environ_free(Query_environ *qe) { 248 | if (qe != NULL) { 249 | if (qe->version != NULL) { 250 | wr_free(qe->version); 251 | } 252 | 253 | if (qe->sources_list != NULL) { 254 | g_list_free(qe->sources_list); 255 | qe->sources_list=NULL; 256 | } 257 | wr_free(qe); 258 | } 259 | } /* QC_environ_free() */ 260 | 261 | /* QC_free() */ 262 | /*++++++++++++++++++++++++++++++++++++++ 263 | Free the query_command. 264 | 265 | Query_command *qc query_command to be freed. 266 | 267 | XXX I'm not sure the bitmaps will get freed. 268 | qc->inv_attrs_bitmap 269 | qc->object_type_bitmap 270 | qc->keytypes_bitmap 271 | 272 | More: 273 | +html+ <PRE> 274 | Authors: 275 | ottrey 276 | +html+ </PRE><DL COMPACT> 277 | +html+ <DT>Online References: 278 | +html+ <DD><UL> 279 | +html+ </UL></DL> 280 | 281 | ++++++++++++++++++++++++++++++++++++++*/ 282 | void QC_free(Query_command *qc) { 283 | if (qc != NULL) { 284 | if (qc->keys != NULL) { 285 | wr_free(qc->keys); 286 | } 287 | wr_free(qc); 288 | } 289 | } /* QC_free() */ 290 | 291 | 292 | 293 | /* QC_fill() */ 294 | /*++++++++++++++++++++++++++++++++++++++ 295 | Create a new query_command. 296 | Returns 0 when OK, -1 when query incorrect. 297 | 298 | char *query_str The garden variety whois query string. 299 | 300 | Query_environ *qe the environment 301 | 302 | More: 303 | +html+ <PRE> 304 | Authors: 305 | ottrey - original code 306 | marek - modified for my getopts, multiple sources; 307 | and generally cleaned. 308 | +html+ </PRE><DL COMPACT> 309 | +html+ <DT>Online References: 310 | +html+ <DD><UL> 311 | +html+ </UL></DL> 312 | 313 | ++++++++++++++++++++++++++++++++++++++*/ 314 | static 315 | int QC_fill(char *query_str, 316 | Query_command *query_command, 317 | Query_environ *qe) { 318 | 319 | int c; 320 | int synerrflg = 0; 321 | int badparerr = 0; 322 | int minusk = 0; 323 | char *inv_attrs_str = NULL; 324 | char *object_types_str = NULL; 325 | int opt_argc; 326 | gchar **opt_argv; 327 | char *value; 328 | char *tmp_query_str; 329 | unsigned key_length; 330 | int i; 331 | int index; 332 | C_Type_t type; 333 | A_Type_t attr; 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 | /* Unknown attribute encountered. */ 433 | char *rep = ca_get_qc_badattr ; 434 | SK_cd_puts(&(qe->condat), rep); 435 | wr_free(rep); 436 | 437 | attr = -1; 438 | badparerr++; 439 | } 440 | else { 441 | mask_t inv_attr_mask = MA_new(INV_ATTR_MASK); 442 | attr = DF_get_attribute_index(index); 443 | if ( MA_isset(inv_attr_mask, attr) == 1 ) { 444 | /* Add the attr to the bitmap. */ 445 | MA_set(&(query_command->inv_attrs_bitmap), attr, 1); 446 | } 447 | else { 448 | /* "%s" is not an inverse searchable attribute. */ 449 | char *rep = ca_get_qc_fmt_attrnotinv ; 450 | SK_cd_printf(&(qe->condat), rep, 451 | (DF_get_attribute_aliases())[index]); 452 | wr_free(rep); 453 | badparerr++; 454 | } 455 | } 456 | } /* while () */ 457 | 458 | if( hackstr != NULL) { 459 | wr_free(hackstr); 460 | } 461 | } /* if () */ 462 | break; 463 | 464 | case 'k': 465 | minusk = 1; 466 | break; 467 | 468 | case 'r': 469 | query_command->recursive=0; /* Unset recursion */ 470 | break; 471 | 472 | case 'l': 473 | query_command->l=1; 474 | break; 475 | 476 | case 'm': 477 | query_command->m=1; 478 | break; 479 | 480 | case 'q': 481 | if (gst->optarg != NULL) { 482 | index = getsubopt(&gst->optarg, DF_get_server_queries(), &value); 483 | if (index == -1) { 484 | synerrflg++; 485 | } 486 | else { 487 | query_command->q = index; 488 | } 489 | } /* if () */ 490 | break; 491 | 492 | case 's': 493 | if (gst->optarg != NULL) { 494 | char *token, *cursor = gst->optarg; 495 | ca_dbSource_t *handle; 496 | 497 | /* Remove any sources from the sources list. */ 498 | g_list_free(qe->sources_list); 499 | qe->sources_list=NULL; 500 | 501 | /* go through specified sources */ 502 | while( (token = strsep( &cursor, "," )) != NULL ) { 503 | 504 | if( (handle = ca_get_SourceHandleByName(token)) != NULL ) { 505 | /* append */ 506 | qe->sources_list 507 | = g_list_append(qe->sources_list, (void *) handle ); 508 | } 509 | else { 510 | /* bail out */ 511 | 512 | /* Unknown source %s requested. */ 513 | char *rep = ca_get_qc_fmt_badsource ; 514 | SK_cd_printf(&(qe->condat), rep, token ); 515 | wr_free(rep); 516 | 517 | /* XXX error */ 518 | badparerr++; 519 | 520 | } /* if handle not null */ 521 | } /* while sources */ 522 | } /* if argument present */ 523 | break; 524 | 525 | case 't': 526 | if (gst->optarg != NULL) { 527 | object_types_str = gst->optarg; 528 | while (*object_types_str) { 529 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 530 | if (index == -1) { 531 | /* Unknown object type encountered */ 532 | char *rep = ca_get_qc_badobjtype ; 533 | SK_cd_puts(&(qe->condat), rep); 534 | wr_free(rep); 535 | badparerr++; 536 | } 537 | else { 538 | type = DF_get_class_index(index); 539 | query_command->t=type; 540 | } 541 | } 542 | } 543 | break; 544 | 545 | case 'v': 546 | if (gst->optarg != NULL) { 547 | object_types_str = gst->optarg; 548 | if (*object_types_str) { 549 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 550 | if (index == -1) { 551 | /* Unknown object type encountered */ 552 | char *rep = ca_get_qc_badobjtype ; 553 | SK_cd_puts(&(qe->condat), rep); 554 | wr_free(rep); 555 | badparerr++; 556 | } 557 | else { 558 | type = DF_get_class_index(index); 559 | query_command->v=type; 560 | } 561 | } 562 | } 563 | break; 564 | 565 | case 'x': 566 | query_command->x=1; 567 | break; 568 | 569 | case 'F': 570 | query_command->fast=1; 571 | query_command->recursive=0; /* implies no recursion */ 572 | break; 573 | 574 | case 'K': 575 | query_command->filtered=1; 576 | query_command->recursive=0; /* implies no recursion */ 577 | break; 578 | 579 | case 'L': 580 | query_command->L=1; 581 | break; 582 | 583 | case 'M': 584 | query_command->M=1; 585 | break; 586 | 587 | case 'R': 588 | query_command->R=1; 589 | break; 590 | 591 | case 'S': 592 | query_command->S=1; 593 | break; 594 | 595 | case 'T': 596 | if (gst->optarg != NULL) { 597 | /* parse the specification */ 598 | object_types_str = gst->optarg; 599 | while (*object_types_str) { 600 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 601 | if (index == -1) { 602 | /* Unknown object type encountered */ 603 | char *rep = ca_get_qc_badobjtype ; 604 | SK_cd_puts(&(qe->condat), rep); 605 | wr_free(rep); 606 | badparerr++; 607 | } 608 | else { 609 | type = DF_get_class_index(index); 610 | /* Add the type to the bitmap. */ 611 | MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1); 612 | } 613 | } 614 | } 615 | break; 616 | 617 | case 'V': 618 | if (qe->version != NULL) { 619 | /* free up the old client info */ 620 | wr_free(qe->version); 621 | } 622 | 623 | { 624 | char *token, *cursor = gst->optarg; 625 | while( (token = strsep( &cursor, "," )) != NULL ) { 626 | if(IP_addr_e2b( & (qe->pIP), token) 627 | != IP_OK ) { 628 | /* means it was not an IP -> it was a version */ 629 | dieif( wr_malloc( (void **)&(qe->version), 630 | strlen(token)+1) != UT_OK); 631 | strcpy(qe->version, token); 632 | } 633 | } 634 | } 635 | break; 636 | 637 | /* any other flag, including '?' and ':' errors */ 638 | default: 639 | synerrflg++; 640 | } 641 | } 642 | 643 | /* copy the key */ 644 | 645 | /* Work out the length of space needed */ 646 | key_length = 1; /* for terminal '\0' */ 647 | for (i=gst->optind ; i < opt_argc; i++) { 648 | /* length for the string + 1 for the '\0'+ 1 for the ' ' */ 649 | if (opt_argv[i] != NULL) { 650 | key_length += strlen(opt_argv[i])+1; 651 | } 652 | } 653 | /* allocate */ 654 | dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK); 655 | /* copy */ 656 | for (i=gst->optind; i < opt_argc; i++) { 657 | strcat(query_command->keys, opt_argv[i]); 658 | if ( (i + 1) < opt_argc) { 659 | strcat(query_command->keys, " "); 660 | } 661 | } 662 | 663 | /* if no error, process the key, otherwise don't bother */ 664 | if ( ! synerrflg && ! badparerr ) { 665 | /* convert the key to uppercase. */ 666 | for (i=0; i <= key_length; i++) { 667 | query_command->keys[i] = toupper(query_command->keys[i]); 668 | } 669 | 670 | /* make the keytypes_bitmap. */ 671 | query_command->keytypes_bitmap = WK_new(query_command->keys); 672 | 673 | /* fix the object type bitmap - turn "all zeros" into "all ones" */ 674 | if( MA_bitcount(query_command->object_type_bitmap) == 0 ) { 675 | query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap); 676 | } 677 | 678 | /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then 679 | exclude the domains unless -d is set 680 | XXX this must be kept in sync with new types */ 681 | if( query_command->d == 0 682 | && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS) 683 | || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE ) 684 | || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX ) 685 | || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX ) 686 | ) ) { 687 | 688 | MA_set(&(query_command->object_type_bitmap), C_DN , 0); 689 | } 690 | 691 | /* tracing */ 692 | log_command(tmp_query_str, query_command); 693 | 694 | /* "keep connection" processing: 695 | when opening connection, -k may be alone or with a query 696 | later -k must appear alone (or there must be an empty line, 697 | or an error) for the connection to close. 698 | */ 699 | if( minusk ) { 700 | if( qe->k == 0 ) { /* opening */ 701 | qe->k = 1; 702 | } 703 | else { /* closing, if no key; otherwise keep open */ 704 | if( key_length <= 1 ) { 705 | qe->k = 0; 706 | } 707 | } 708 | } 709 | 710 | } /* if no error */ 711 | 712 | /* we don't need this anymore */ 713 | wr_free(tmp_query_str); 714 | wr_free(gst); 715 | g_strfreev(opt_argv); 716 | 717 | if(synerrflg > 0) { /* severe syntax error. Usage must be printed */ 718 | return QC_SYNERR; 719 | } 720 | else if(badparerr > 0) { /* the requester has a clue. No Usage info */ 721 | return QC_PARERR; 722 | } 723 | else { 724 | return 0; 725 | } 726 | } /* QC_fill() */ 727 | 728 | /* QC_environ_new() */ 729 | /*++++++++++++++++++++++++++++++++++++++ 730 | Create a new query environment. 731 | 732 | More: 733 | +html+ <PRE> 734 | Authors: 735 | ottrey 736 | +html+ </PRE><DL COMPACT> 737 | +html+ <DT>Online References: 738 | +html+ <DD><UL> 739 | +html+ </UL></DL> 740 | 741 | ++++++++++++++++++++++++++++++++++++++*/ 742 | Query_environ *QC_environ_new(char *ip, int sock) { 743 | Query_environ *qe; 744 | 745 | 746 | dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK); 747 | qe->condat.ip = ip; 748 | qe->condat.sock = sock; 749 | 750 | /* The source is initialized to include only the deflook sources */ 751 | { 752 | int i; 753 | ca_dbSource_t *hdl; 754 | 755 | for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) { 756 | char *amrmrulez = ca_get_srcdeflook(hdl); 757 | if( strcmp(amrmrulez, "y")==0 ) { 758 | qe->sources_list = g_list_append(qe->sources_list, (void *)hdl); 759 | } 760 | free(amrmrulez); 761 | } 762 | } 763 | 764 | return qe; 765 | 766 | } /* QC_environ_new() */ 767 | 768 | 769 | 770 | 771 | /* QC_create() */ 772 | /*++++++++++++++++++++++++++++++++++++++ 773 | try to parse the query and fill in the QC struct, setting 774 | qc->query_type accordingly. 775 | 776 | Query_command *QC_create returns allocated structure 777 | 778 | char *input user query 779 | 780 | Query_environ *qe query environment structure 781 | 782 | Author: 783 | marek. 784 | 785 | ++++++++++++++++++++++++++++++++++++++*/ 786 | 787 | Query_command *QC_create(char *input, Query_environ *qe) 788 | { 789 | Query_command *qc; 790 | /* allocate place for a copy of the input */ 791 | char *copy = calloc(1,strlen(input)+1); 792 | unsigned char *ci, *co; 793 | int qt; 794 | /* clean the string from junk - allow only known chars, something like 795 | tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd; 796 | 797 | strip leading spaces too 798 | */ 799 | 800 | dieif(copy == NULL); 801 | 802 | for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) { 803 | /* EMPTY */ 804 | } 805 | 806 | for(co = (unsigned char *) copy; *ci != 0; ci++) { 807 | if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */ 808 | "abcdefghijklmnopqrstuvwxyz" 809 | "0123456789-_:+=.,@/' \n", *ci) != NULL) { 810 | *(co++) = *ci; 811 | } 812 | } 813 | 814 | /* now delete whitespace chars at the end */ 815 | while( co != (unsigned char *)copy /* don't read past the beginning */ 816 | && isspace(*co) ) { 817 | *co = '\0'; 818 | co--; 819 | } 820 | 821 | 822 | dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK); 823 | 824 | if ( strlen(copy) == 0) { 825 | /* An empty query (Ie return) was sent */ 826 | qc->query_type = QC_EMPTY; 827 | } 828 | else { /* else <==> input_length > 0 ) */ 829 | /* parse query */ 830 | qt = QC_fill(copy, qc, qe); 831 | 832 | if( qt == QC_SYNERR || qt == QC_PARERR ) { 833 | qc->query_type = qt; 834 | } 835 | else { 836 | /* Update the query environment */ 837 | /* qe = QC_environ_update(qc, qe); */ 838 | 839 | /* Only do a query if there are keys. */ 840 | if (qc->keys == NULL || strlen(qc->keys) == 0 ) { 841 | if( strlen(qc->keys) == 0 842 | && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) { 843 | qc->query_type = QC_TEMPLATE; 844 | } 845 | else { 846 | qc->query_type = QC_NOKEY; 847 | } 848 | } 849 | else { 850 | if ( strcmp(qc->keys, "HELP") == 0 ) { 851 | qc->query_type = QC_HELP; 852 | } 853 | /* So, a real query */ 854 | else if( qc->filtered ) { 855 | qc->query_type = QC_FILTERED; 856 | } 857 | else { 858 | qc->query_type = QC_REAL; 859 | } 860 | } 861 | } 862 | } 863 | 864 | free(copy); 865 | 866 | return qc; 867 | } 868 | 869 | 870 | /*++++++++++++++++++++++++++++++++++++++ 871 | 872 | Get the name of the given query type code. 873 | 874 | char *QC_get_qrytype returns a pointer to an element of array of static strings 875 | 876 | qc_qtype_t qrytype query type code 877 | 878 | ++++++++++++++++++++++++++++++++++++++*/ 879 | 880 | char *QC_get_qrytype(qc_qtype_t qrytype) { 881 | dieif(qrytype >= QC_TYPE_MAX); 882 | 883 | return qrytype_str[qrytype]; 884 | }