1 | /*************************************** 2 | $Revision: 1.44 $ 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 | int minusk = 0; 322 | char *inv_attrs_str = NULL; 323 | char *object_types_str = NULL; 324 | int opt_argc; 325 | gchar **opt_argv; 326 | char *value; 327 | char *tmp_query_str; 328 | int key_length; 329 | int i; 330 | int index; 331 | int type; 332 | int attr; 333 | char str_buf[STR_XL]; 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 | attr = -1; 433 | strcpy(str_buf, ""); 434 | sprintf(str_buf, "Unknown attribute encountered.\n"); /* YYY configurable constant: text */ 435 | SK_cd_puts(&(qe->condat), str_buf); 436 | badparerr++; 437 | } 438 | else { 439 | mask_t inv_attr_mask = MA_new(INV_ATTR_MASK); 440 | attr = DF_get_attribute_index(index); 441 | if ( MA_isset(inv_attr_mask, attr) == 1 ) { 442 | /* Add the attr to the bitmap. */ 443 | MA_set(&(query_command->inv_attrs_bitmap), attr, 1); 444 | } 445 | else { 446 | strcpy(str_buf, ""); 447 | sprintf(str_buf, "\"%s\" is not an inverse searchable attribute.\n", (DF_get_attribute_aliases())[index]); /* YYY configurable constant: text */ 448 | SK_cd_puts(&(qe->condat), str_buf); 449 | badparerr++; 450 | } 451 | } 452 | } /* while () */ 453 | 454 | if( hackstr != NULL) { 455 | wr_free(hackstr); 456 | } 457 | } /* if () */ 458 | break; 459 | 460 | case 'k': 461 | minusk = 1; 462 | break; 463 | 464 | case 'r': 465 | query_command->recursive=0; /* Unset recursion */ 466 | break; 467 | 468 | case 'l': 469 | query_command->l=1; 470 | break; 471 | 472 | case 'm': 473 | query_command->m=1; 474 | break; 475 | 476 | case 'q': 477 | if (gst->optarg != NULL) { 478 | index = getsubopt(&gst->optarg, DF_get_server_queries(), &value); 479 | if (index == -1) { 480 | synerrflg++; 481 | } 482 | else { 483 | query_command->q = index; 484 | } 485 | } /* if () */ 486 | break; 487 | 488 | case 's': 489 | if (gst->optarg != NULL) { 490 | char *token, *cursor = gst->optarg; 491 | ca_dbSource_t *handle; 492 | 493 | /* Remove any sources from the sources list. */ 494 | g_list_free(qe->sources_list); 495 | qe->sources_list=NULL; 496 | 497 | /* go through specified sources */ 498 | while( (token = strsep( &cursor, "," )) != NULL ) { 499 | 500 | if( (handle = ca_get_SourceHandleByName(token)) != NULL ) { 501 | /* append */ 502 | qe->sources_list 503 | = g_list_append(qe->sources_list, (void *) handle ); 504 | } 505 | else { 506 | /* bail out */ 507 | 508 | SK_cd_printf(&(qe->condat), 509 | "%% Unknown source %s requested.\n",token ); /* YYY configurable constant: text */ 510 | 511 | /* XXX error */ 512 | badparerr++; 513 | 514 | } /* if handle not null */ 515 | } /* while sources */ 516 | } /* if argument present */ 517 | break; 518 | 519 | case 't': 520 | if (gst->optarg != NULL) { 521 | object_types_str = gst->optarg; 522 | while (*object_types_str) { 523 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 524 | if (index == -1) { 525 | strcpy(str_buf, ""); 526 | sprintf(str_buf, "Unknown object encountered.\n"); /* YYY configurable constant: text */ 527 | SK_cd_puts(&(qe->condat), str_buf); 528 | badparerr++; 529 | } 530 | else { 531 | type = DF_get_class_index(index); 532 | query_command->t=type; 533 | } 534 | } 535 | } 536 | break; 537 | 538 | case 'v': 539 | if (gst->optarg != NULL) { 540 | object_types_str = gst->optarg; 541 | if (*object_types_str) { 542 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 543 | if (index == -1) { 544 | strcpy(str_buf, ""); 545 | sprintf(str_buf, "Unknown object encountered.\n"); /* YYY configurable constant: text */ 546 | SK_cd_puts(&(qe->condat), str_buf); 547 | badparerr++; 548 | } 549 | else { 550 | type = DF_get_class_index(index); 551 | query_command->v=type; 552 | } 553 | } 554 | } 555 | break; 556 | 557 | case 'x': 558 | query_command->x=1; 559 | break; 560 | 561 | case 'F': 562 | query_command->fast=1; 563 | query_command->recursive=0; /* implies no recursion */ 564 | break; 565 | 566 | case 'K': 567 | query_command->filtered=1; 568 | query_command->recursive=0; /* implies no recursion */ 569 | break; 570 | 571 | case 'L': 572 | query_command->L=1; 573 | break; 574 | 575 | case 'M': 576 | query_command->M=1; 577 | break; 578 | 579 | case 'R': 580 | query_command->R=1; 581 | break; 582 | 583 | case 'S': 584 | query_command->S=1; 585 | break; 586 | 587 | case 'T': 588 | if (gst->optarg != NULL) { 589 | /* parse the specification */ 590 | object_types_str = gst->optarg; 591 | while (*object_types_str) { 592 | index = getsubopt(&object_types_str, DF_get_class_aliases(), &value); 593 | if (index == -1) { 594 | strcpy(str_buf, ""); 595 | sprintf(str_buf, "Unknown object type encountered.\n"); /* YYY configurable constant: text */ 596 | SK_cd_puts(&(qe->condat), str_buf); 597 | badparerr++; 598 | } 599 | else { 600 | type = DF_get_class_index(index); 601 | /* Add the type to the bitmap. */ 602 | MA_set(&(query_command->object_type_bitmap), type, 1); 603 | } 604 | } 605 | } 606 | break; 607 | 608 | case 'V': 609 | if (qe->version != NULL) { 610 | /* free up the old client info */ 611 | wr_free(qe->version); 612 | } 613 | 614 | { 615 | char *token, *cursor = gst->optarg; 616 | while( (token = strsep( &cursor, "," )) != NULL ) { 617 | if(IP_addr_e2b( & (qe->pIP), token) 618 | != IP_OK ) { 619 | /* means it was not an IP -> it was a version */ 620 | dieif( wr_malloc( (void **)&(qe->version), 621 | strlen(token)+1) != UT_OK); 622 | strcpy(qe->version, token); 623 | } 624 | } 625 | } 626 | break; 627 | 628 | /* any other flag, including '?' and ':' errors */ 629 | default: 630 | synerrflg++; 631 | } 632 | } 633 | 634 | /* copy the key */ 635 | 636 | /* Work out the length of space needed */ 637 | key_length = 1; /* for terminal '\0' */ 638 | for (i=gst->optind ; i < opt_argc; i++) { 639 | /* length for the string + 1 for the '\0'+ 1 for the ' ' */ 640 | if (opt_argv[i] != NULL) { 641 | key_length += strlen(opt_argv[i])+1; 642 | } 643 | } 644 | /* allocate */ 645 | dieif( wr_calloc((void **)&(query_command->keys), 1, key_length+1) != UT_OK); 646 | /* copy */ 647 | for (i=gst->optind; i < opt_argc; i++) { 648 | strcat(query_command->keys, opt_argv[i]); 649 | if ( (i + 1) < opt_argc) { 650 | strcat(query_command->keys, " "); 651 | } 652 | } 653 | 654 | /* if no error, process the key, otherwise don't bother */ 655 | if ( ! synerrflg && ! badparerr ) { 656 | /* convert the key to uppercase. */ 657 | for (i=0; i <= key_length; i++) { 658 | query_command->keys[i] = toupper(query_command->keys[i]); 659 | } 660 | 661 | /* make the keytypes_bitmap. */ 662 | query_command->keytypes_bitmap = WK_new(query_command->keys); 663 | 664 | /* fix the object type bitmap - turn "all zeros" into "all ones" */ 665 | if( MA_bitcount(query_command->object_type_bitmap) == 0 ) { 666 | query_command->object_type_bitmap = MA_not(query_command->object_type_bitmap); 667 | } 668 | 669 | /* -d handling: if the keytype is IPv4/v6 address/prefix/range, then 670 | exclude the domains unless -d is set 671 | XXX this must be kept in sync with new types */ 672 | if( query_command->d == 0 673 | && ( MA_isset(query_command->keytypes_bitmap, WK_IPADDRESS) 674 | || MA_isset(query_command->keytypes_bitmap, WK_IPRANGE ) 675 | || MA_isset(query_command->keytypes_bitmap, WK_IPPREFIX ) 676 | || MA_isset(query_command->keytypes_bitmap, WK_IP6PREFIX ) 677 | ) ) { 678 | 679 | MA_set(&(query_command->object_type_bitmap), C_DN , 0); 680 | } 681 | 682 | /* tracing */ 683 | log_command(tmp_query_str, query_command); 684 | 685 | /* "keep connection" processing: 686 | when opening connection, -k may be alone or with a query 687 | later -k must appear alone (or there must be an empty line, 688 | or an error) for the connection to close. 689 | */ 690 | if( minusk ) { 691 | if( qe->k == 0 ) { /* opening */ 692 | qe->k = 1; 693 | } 694 | else { /* closing, if no key; otherwise keep open */ 695 | if( key_length <= 1 ) { 696 | qe->k = 0; 697 | } 698 | } 699 | } 700 | 701 | } /* if no error */ 702 | 703 | /* we don't need this anymore */ 704 | wr_free(tmp_query_str); 705 | wr_free(gst); 706 | 707 | if(synerrflg > 0) { /* severe syntax error. Usage must be printed */ 708 | return QC_SYNERR; 709 | } 710 | else if(badparerr > 0) { /* the requester has a clue. No Usage info */ 711 | return QC_PARERR; 712 | } 713 | else { 714 | return 0; 715 | } 716 | } /* QC_fill() */ 717 | 718 | /* QC_environ_new() */ 719 | /*++++++++++++++++++++++++++++++++++++++ 720 | Create a new query environment. 721 | 722 | More: 723 | +html+ <PRE> 724 | Authors: 725 | ottrey 726 | +html+ </PRE><DL COMPACT> 727 | +html+ <DT>Online References: 728 | +html+ <DD><UL> 729 | +html+ </UL></DL> 730 | 731 | ++++++++++++++++++++++++++++++++++++++*/ 732 | Query_environ *QC_environ_new(char *ip, unsigned sock) { 733 | Query_environ *qe; 734 | 735 | 736 | dieif( wr_calloc((void **)&qe, 1, sizeof(Query_environ)+1 ) != UT_OK); 737 | qe->condat.ip = ip; 738 | qe->condat.sock = sock; 739 | 740 | /* The source is initialized to include only the deflook sources */ 741 | { 742 | int i; 743 | ca_dbSource_t *hdl; 744 | 745 | for (i=0; (hdl = ca_get_SourceHandleByPosition(i)) != NULL; i++) { 746 | if( ca_get_srcdeflook(hdl) ) { 747 | qe->sources_list = g_list_append(qe->sources_list, (void *)hdl); 748 | } 749 | } 750 | } 751 | 752 | return qe; 753 | 754 | } /* QC_environ_new() */ 755 | 756 | 757 | 758 | /*++ QC_create() 759 | 760 | try to parse the query and fill in the QC struct, setting 761 | qc->query_type accordingly. 762 | 763 | by marek. 764 | ++++++++++++++++++++++++++++++++++++++*/ 765 | Query_command *QC_create(char *input, Query_environ *qe) 766 | { 767 | Query_command *qc; 768 | /* allocate place for a copy of the input */ 769 | char *copy = calloc(1,strlen(input)+1); 770 | unsigned char *ci, *co; 771 | int qt; 772 | /* clean the string from junk - allow only known chars, something like 773 | tr/A-Za-z0-9\-\_\:\+\=\.\,\@\/ \n//cd; 774 | 775 | strip leading spaces too 776 | */ 777 | 778 | dieif(copy == NULL); 779 | 780 | for(ci = (unsigned char *)input; *ci != 0 && isspace(*ci); ci++) { 781 | /* EMPTY */ 782 | } 783 | 784 | for(co = (unsigned char *) copy; *ci != 0; ci++) { 785 | if( strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* only those are allowed */ 786 | "abcdefghijklmnopqrstuvwxyz" 787 | "0123456789-_:+=.,@/' \n", *ci) != NULL) { 788 | *(co++) = *ci; 789 | } 790 | } 791 | 792 | /* now delete whitespace chars at the end */ 793 | co--; 794 | while( isspace(*co) ) { 795 | *co = '\0'; 796 | co--; 797 | } 798 | 799 | 800 | dieif( wr_calloc((void **)&qc, 1, sizeof(Query_command)+1) != UT_OK); 801 | 802 | if ( strlen(copy) == 0) { 803 | /* An empty query (Ie return) was sent */ 804 | qc->query_type = QC_EMPTY; 805 | } 806 | else { /* else <==> input_length > 0 ) */ 807 | /* parse query */ 808 | qt = QC_fill(copy, qc, qe); 809 | 810 | if( qt == QC_SYNERR || qt == QC_PARERR ) { 811 | qc->query_type = qt; 812 | } 813 | else { 814 | /* Update the query environment */ 815 | /* qe = QC_environ_update(qc, qe); */ 816 | 817 | /* Only do a query if there are keys. */ 818 | if (qc->keys == NULL || strlen(qc->keys) == 0 ) { 819 | if( strlen(qc->keys) == 0 820 | && ( qc->q != -1 || qc->t != -1 || qc->v != -1 ) ) { 821 | qc->query_type = QC_TEMPLATE; 822 | } 823 | else { 824 | qc->query_type = QC_NOKEY; 825 | } 826 | } 827 | else { 828 | if ( strcmp(qc->keys, "HELP") == 0 ) { 829 | qc->query_type = QC_HELP; 830 | } 831 | /* So, a real query */ 832 | else if( qc->filtered ) { 833 | qc->query_type = QC_FILTERED; 834 | } 835 | else { 836 | qc->query_type = QC_REAL; 837 | } 838 | } 839 | } 840 | } 841 | 842 | free(copy); 843 | 844 | return qc; 845 | } 846 | 847 | 848 | char *QC_get_qrytype(qc_qtype_t qrytype) { 849 | dieif(qrytype >= QC_TYPE_MAX); 850 | 851 | return qrytype_str[qrytype]; 852 | }