1 | /*************************************** 2 | $Revision: 1.58 $ 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,2002 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) 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) 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) { 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, (c=%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->c_irt_search ? "TRUE" : "FALSE", 172 | query_command->e, 173 | query_command->g, 174 | query_command->l, 175 | query_command->m, 176 | query_command->q, 177 | query_command->t, 178 | query_command->v, 179 | query_command->x, 180 | query_command->fast, 181 | query_command->filtered, 182 | query_command->L, 183 | query_command->M, 184 | query_command->R, 185 | query_command->S, 186 | str3, 187 | query_command->keys); 188 | UT_free(str1); 189 | UT_free(str2); 190 | UT_free(str3); 191 | 192 | return UT_strdup(result_buf); 193 | 194 | } /* QC_query_command_to_string() */ 195 | 196 | /* log_command() */ 197 | /*++++++++++++++++++++++++++++++++++++++ 198 | Log the command. 199 | This is more to do with Tracing. And should/will get merged with a tracing 200 | module (when it is finalized.) 201 | 202 | char *query_str 203 | 204 | Query_command *query_command 205 | 206 | More: 207 | +html+ <PRE> 208 | Authors: 209 | ottrey 210 | +html+ </PRE><DL COMPACT> 211 | +html+ <DT>Online References: 212 | +html+ <DD><UL> 213 | +html+ </UL></DL> 214 | 215 | ++++++++++++++++++++++++++++++++++++++*/ 216 | static void log_command(char *query_str, Query_command *query_command) { 217 | char *str; 218 | 219 | if( ER_is_traced(FAC_QC, ASP_QC_BUILD) ) { 220 | str = QC_query_command_to_string(query_command); 221 | ER_dbg_va(FAC_QC, ASP_QC_BUILD, 222 | "query=[%s] %s", query_str, str); 223 | UT_free(str); 224 | } 225 | } /* log_command() */ 226 | 227 | /* QC_environ_free() */ 228 | /*++++++++++++++++++++++++++++++++++++++ 229 | Free the query_environ. 230 | 231 | Query_command *qc query_environ to be freed. 232 | 233 | More: 234 | +html+ <PRE> 235 | Authors: 236 | ottrey 237 | +html+ </PRE><DL COMPACT> 238 | +html+ <DT>Online References: 239 | +html+ <DD><UL> 240 | +html+ </UL></DL> 241 | 242 | ++++++++++++++++++++++++++++++++++++++*/ 243 | void QC_environ_free(Query_environ *qe) { 244 | if (qe != NULL) { 245 | UT_free(qe->version); 246 | 247 | if (qe->sources_list != NULL) { 248 | g_list_free(qe->sources_list); 249 | qe->sources_list=NULL; 250 | } 251 | UT_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 | UT_free(qc->keys); 280 | } 281 | UT_free(qc); 282 | } 283 | } /* QC_free() */ 284 | 285 | 286 | 287 | /* QC_fill() */ 288 | /*++++++++++++++++++++++++++++++++++++++ 289 | Create a new query_command. 290 | Returns 0 when OK, -1 when query incorrect. 291 | 292 | char *query_str The garden variety whois query string. 293 | 294 | Query_environ *qe the environment 295 | 296 | More: 297 | +html+ <PRE> 298 | Authors: 299 | ottrey - original code 300 | marek - modified for my getopts, multiple sources; 301 | and generally cleaned. 302 | +html+ </PRE><DL COMPACT> 303 | +html+ <DT>Online References: 304 | +html+ <DD><UL> 305 | +html+ </UL></DL> 306 | 307 | ++++++++++++++++++++++++++++++++++++++*/ 308 | static 309 | int QC_fill(char *query_str, 310 | Query_command *query_command, 311 | Query_environ *qe) { 312 | 313 | int c; 314 | int synerrflg = 0; 315 | int badparerr = 0; 316 | int minusk = 0; 317 | char *inv_attrs_str = NULL; 318 | char *object_types_str = NULL; 319 | int opt_argc; 320 | gchar **opt_argv; 321 | char *value; 322 | /* char *tmp_query_str;*/ 323 | unsigned key_length; 324 | int i; 325 | int index; 326 | C_Type_t type; 327 | A_Type_t attr; 328 | getopt_state_t *gst = NULL; 329 | 330 | query_command->c_irt_search = FALSE; 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, "acdegi: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 'c': 397 | query_command->c_irt_search = TRUE; 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 | /* 418 | Now a really stupid hard-coded hack to support "pn" being a 419 | synonym for "ac,tc,zc,ah". I particularly object to this because 420 | it references attributes that should only be defined in XML - but 421 | I don't see a simplier more robust way of doing this hack. 422 | :-( - ottrey 8/12/99 423 | 424 | ** removed a memory leak - MB, 1/08/00 425 | 426 | ** removed the use of "ro", added "person" - shane, 2002-01-23 427 | 428 | */ 429 | if ( strcmp(inv_attrs_str, "pn") == 0 430 | || strcmp(inv_attrs_str, "person") == 0) { 431 | hackstr = UT_strdup("ac,tc,zc,ah,cn"); 432 | inv_attrs_str = hackstr; 433 | } 434 | while (*inv_attrs_str) { 435 | index = getsubopt(&inv_attrs_str, DF_get_attribute_aliases(), &value); 436 | if (index == -1) { 437 | /* Unknown attribute encountered. */ 438 | char *rep = ca_get_qc_badattr ; 439 | SK_cd_puts(&(qe->condat), rep); 440 | UT_free(rep); 441 | 442 | attr = -1; 443 | badparerr++; 444 | } 445 | else { 446 | mask_t inv_attr_mask = MA_new(INV_ATTR_MASK); 447 | attr = DF_get_attribute_index(index); 448 | if ( MA_isset(inv_attr_mask, attr) == 1 ) { 449 | /* Add the attr to the bitmap. */ 450 | MA_set(&(query_command->inv_attrs_bitmap), attr, 1); 451 | } 452 | else { 453 | /* "%s" is not an inverse searchable attribute. */ 454 | char *rep = ca_get_qc_fmt_attrnotinv ; 455 | SK_cd_printf(&(qe->condat), rep, 456 | (DF_get_attribute_aliases())[index]); 457 | UT_free(rep); 458 | badparerr++; 459 | } 460 | } 461 | } /* while () */ 462 | 463 | if( hackstr != NULL) { 464 | UT_free(hackstr); 465 | } 466 | } /* if () */ 467 | break; 468 | 469 | case 'k': 470 | minusk = 1; 471 | break; 472 | 473 | case 'r': 474 | query_command->recursive=0; /* Unset recursion */ 475 | break; 476 | 477 | case 'l': 478 | query_command->l=1; 479 | break; 480 | 481 | case 'm': 482 | query_command->m=1; 483 | break; 484 | 485 | case 'q': 486 | if (gst->optarg != NULL) { 487 | index = getsubopt(&gst->optarg, DF_get_server_queries(), &value); 488 | if (index == -1) { 489 | synerrflg++; 490 | } 491 | else { 492 | query_command->q = index; 493 | } 494 | } /* if () */ 495 | break; 496 | 497 | case 's': 498 | if (gst->optarg != NULL) { 499 | char *token, *cursor = gst->optarg; 500 | ca_dbSource_t *handle; 501 | 502 | /* Remove any sources from the sources list. */ 503 | g_list_free(qe->sources_list); 504 | qe->sources_list=NULL; 505 | 506 | /* go through specified sources */ 507 | while( (token = strsep( &cursor, "," )) != NULL ) { 508 | 509 | if( (handle = ca_get_SourceHandleByName(token)) != NULL ) { 510 | /* append */ 511 | qe->sources_list 512 | = g_list_append(qe->sources_list, (void *) handle ); 513 | } 514 | else { 515 | /* bail out */ 516 | 517 | /* Unknown source %s requested. */ 518 | char *rep = ca_get_qc_fmt_badsource ; 519 | SK_cd_printf(&(qe->condat), rep, token ); 520 | UT_free(rep); 521 | 522 | /* XXX error */ 523 | badparerr++; 524 | 525 | } /* if handle not null */ 526 | } /* while sources */ 527 | } /* if argument present */ 528 | break; 529 | 530 | case 't': 531 | if (gst->optarg != NULL) { 532 | object_types_str = gst->optarg; 533 | while (*object_types_str) { 534 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 535 | if (index == -1) { 536 | /* Unknown object type encountered */ 537 | char *rep = ca_get_qc_badobjtype ; 538 | SK_cd_puts(&(qe->condat), rep); 539 | UT_free(rep); 540 | badparerr++; 541 | } 542 | else { 543 | type = DF_get_class_index(index); 544 | query_command->t=type; 545 | } 546 | } 547 | } 548 | break; 549 | 550 | case 'v': 551 | if (gst->optarg != NULL) { 552 | object_types_str = gst->optarg; 553 | if (*object_types_str) { 554 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 555 | if (index == -1) { 556 | /* Unknown object type encountered */ 557 | char *rep = ca_get_qc_badobjtype ; 558 | SK_cd_puts(&(qe->condat), rep); 559 | UT_free(rep); 560 | badparerr++; 561 | } 562 | else { 563 | type = DF_get_class_index(index); 564 | query_command->v=type; 565 | } 566 | } 567 | } 568 | break; 569 | 570 | case 'x': 571 | query_command->x=1; 572 | break; 573 | 574 | case 'F': 575 | query_command->fast=1; 576 | query_command->recursive=0; /* implies no recursion */ 577 | break; 578 | 579 | case 'K': 580 | query_command->filtered=1; 581 | query_command->recursive=0; /* implies no recursion */ 582 | break; 583 | 584 | case 'L': 585 | query_command->L=1; 586 | break; 587 | 588 | case 'M': 589 | query_command->M=1; 590 | break; 591 | 592 | case 'R': 593 | query_command->R=1; 594 | break; 595 | 596 | case 'S': 597 | query_command->S=1; 598 | break; 599 | 600 | case 'T': 601 | if (gst->optarg != NULL) { 602 | /* parse the specification */ 603 | object_types_str = gst->optarg; 604 | while (*object_types_str) { 605 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 606 | if (index == -1) { 607 | /* Unknown object type encountered */ 608 | char *rep = ca_get_qc_badobjtype ; 609 | SK_cd_puts(&(qe->condat), rep); 610 | UT_free(rep); 611 | badparerr++; 612 | } 613 | else { 614 | type = DF_get_class_index(index); 615 | /* Add the type to the bitmap. */ 616 | MA_set(&(query_command->object_type_bitmap), (unsigned) type, 1); 617 | } 618 | } 619 | } 620 | break; 621 | 622 | case 'V': 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 | UT_free(qe->version); 630 | qe->version = UT_strdup(token); 631 | } 632 | } 633 | } 634 | break; 635 | 636 | /* any other flag, including '?' and ':' errors */ 637 | default: 638 | synerrflg++; 639 | } 640 | } 641 | 642 | /* copy the key */ 643 | 644 | /* Work out the length of space needed */ 645 | key_length = 1; /* for terminal '\0' */ 646 | for (i=gst->optind ; i < opt_argc; i++) { 647 | /* length for the string + 1 for the '\0'+ 1 for the ' ' */ 648 | if (opt_argv[i] != NULL) { 649 | key_length += strlen(opt_argv[i])+1; 650 | } 651 | } 652 | /* allocate */ 653 | query_command->keys = (char *)UT_calloc(1, key_length+1); 654 | 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 | log_command(query_str, query_command); 694 | 695 | /* "keep connection" processing: 696 | when opening connection, -k may be alone or with a query 697 | later -k must appear alone (or there must be an empty line, 698 | or an error) for the connection to close. 699 | */ 700 | if( minusk ) { 701 | if( qe->k == 0 ) { /* opening */ 702 | qe->k = 1; 703 | } 704 | else { /* closing, if no key; otherwise keep open */ 705 | if( key_length <= 1 ) { 706 | qe->k = 0; 707 | } 708 | } 709 | } 710 | 711 | } /* if no error */ 712 | 713 | /* we don't need this anymore */ 714 | /* UT_free(tmp_query_str);*/ 715 | UT_free(gst); 716 | g_strfreev(opt_argv); 717 | 718 | if(synerrflg > 0) { /* severe syntax error. Usage must be printed */ 719 | return QC_SYNERR; 720 | } 721 | else if(badparerr > 0) { /* the requester has a clue. No Usage info */ 722 | return QC_PARERR; 723 | } 724 | else { 725 | return 0; 726 | } 727 | } /* QC_fill() */ 728 | 729 | /* QC_environ_new() */ 730 | /*++++++++++++++++++++++++++++++++++++++ 731 | Create a new query environment. 732 | 733 | More: 734 | +html+ <PRE> 735 | Authors: 736 | ottrey 737 | +html+ </PRE><DL COMPACT> 738 | +html+ <DT>Online References: 739 | +html+ <DD><UL> 740 | +html+ </UL></DL> 741 | 742 | ++++++++++++++++++++++++++++++++++++++*/ 743 | Query_environ *QC_environ_new(char *ip, int sock) { 744 | Query_environ *qe; 745 | 746 | qe = (Query_environ *)UT_calloc(1, sizeof(Query_environ)); 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 | UT_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 = UT_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 | for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) { 801 | /* EMPTY */ 802 | } 803 | 804 | for(co = (unsigned char *) copy; *ci != 0; ci++) { 805 | if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */ 806 | "abcdefghijklmnopqrstuvwxyz" 807 | "0123456789-_:+=.,@/?' \n", *ci) != NULL) { 808 | *(co++) = *ci; 809 | } 810 | } 811 | 812 | /* now delete whitespace chars at the end */ 813 | while( co != (unsigned char *)copy /* don't read past the beginning */ 814 | && isspace(*co) ) { 815 | *co = '\0'; 816 | co--; 817 | } 818 | 819 | 820 | qc = (Query_command *)UT_calloc(1, sizeof(Query_command)); 821 | 822 | if ( strlen(copy) == 0) { 823 | /* An empty query (Ie return) was sent */ 824 | qc->query_type = QC_EMPTY; 825 | } 826 | else { /* else <==> input_length > 0 ) */ 827 | /* parse query */ 828 | qt = QC_fill(copy, qc, qe); 829 | 830 | if( qt == QC_SYNERR || qt == QC_PARERR ) { 831 | qc->query_type = qt; 832 | } 833 | else { 834 | /* Update the query environment */ 835 | /* qe = QC_environ_update(qc, qe); */ 836 | 837 | /* Only do a query if there are keys. */ 838 | if (qc->keys == NULL || strlen(qc->keys) == 0 ) { 839 | if( strlen(qc->keys) == 0 840 | && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) { 841 | qc->query_type = QC_TEMPLATE; 842 | } 843 | else { 844 | qc->query_type = QC_NOKEY; 845 | } 846 | } 847 | else { 848 | if ( strcmp(qc->keys, "HELP") == 0 ) { 849 | qc->query_type = QC_HELP; 850 | } 851 | /* So, a real query */ 852 | else if( qc->filtered ) { 853 | qc->query_type = QC_FILTERED; 854 | } 855 | else { 856 | qc->query_type = QC_REAL; 857 | } 858 | } 859 | } 860 | } 861 | 862 | UT_free(copy); 863 | 864 | return qc; 865 | } 866 | 867 | 868 | /*++++++++++++++++++++++++++++++++++++++ 869 | 870 | Get the name of the given query type code. 871 | 872 | char *QC_get_qrytype returns a pointer to an element of array of static strings 873 | 874 | qc_qtype_t qrytype query type code 875 | 876 | ++++++++++++++++++++++++++++++++++++++*/ 877 | 878 | char *QC_get_qrytype(qc_qtype_t qrytype) { 879 | dieif(qrytype >= QC_TYPE_MAX); 880 | 881 | return qrytype_str[qrytype]; 882 | }