1 %token_prefix TK_ 2 %extra_argument {config_t *ctx} 3 %name configparser 4 5 %include { 6 #include "first.h" 7 #include "base.h" 8 #include "configfile.h" 9 #include "buffer.h" 10 #include "array.h" 11 #include "http_header.h" /* http_header_hkey_get() */ 12 #include "request.h" /* http_request_host_normalize() */ 13 14 #include <ctype.h> 15 #include <errno.h> 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 20 static data_config * configparser_get_data_config(const array *a, const char *k, const size_t klen) { 21 return (data_config *)array_get_data_unset(a, k, klen); 22 } 23 24 static void configparser_push(config_t *ctx, data_config *dc, int isnew) { 25 if (isnew) { 26 dc->context_ndx = ctx->all_configs->used; 27 force_assert(dc->context_ndx > ctx->current->context_ndx); 28 array_insert_unique(ctx->all_configs, (data_unset *)dc); 29 dc->parent = ctx->current; 30 vector_config_weak_push(&dc->parent->children, dc); 31 } 32 if (ctx->configs_stack.used > 0 && ctx->current->context_ndx == 0) { 33 fprintf(stderr, "Cannot use conditionals inside a global { ... } block\n"); 34 exit(-1); 35 } 36 vector_config_weak_push(&ctx->configs_stack, ctx->current); 37 ctx->current = dc; 38 } 39 40 static data_config *configparser_pop(config_t *ctx) { 41 data_config *old = ctx->current; 42 ctx->current = vector_config_weak_pop(&ctx->configs_stack); 43 return old; 44 } 45 46 /* return a copied variable */ 47 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) { 48 const data_unset *du; 49 data_config *dc; 50 51 #if 0 52 fprintf(stderr, "get var %s\n", key->ptr); 53 #endif 54 for (dc = ctx->current; dc; dc = dc->parent) { 55 #if 0 56 fprintf(stderr, "get var on block: %s\n", dc->key.ptr); 57 array_print(dc->value, 0); 58 #endif 59 if (NULL != (du = array_get_element_klen(dc->value, CONST_BUF_LEN(key)))) { 60 data_unset *du_copy = du->fn->copy(du); 61 buffer_clear(&du_copy->key); 62 return du_copy; 63 } 64 } 65 return NULL; 66 } 67 68 /* op1 is to be eat/return by this function if success, op1->key is not cared 69 op2 is left untouch, unreferenced 70 */ 71 static data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) { 72 /* type mismatch */ 73 if (op1->type != op2->type) { 74 if (op1->type == TYPE_STRING && op2->type == TYPE_INTEGER) { 75 data_string *ds = (data_string *)op1; 76 buffer_append_int(&ds->value, ((data_integer*)op2)->value); 77 return op1; 78 } else if (op1->type == TYPE_INTEGER && op2->type == TYPE_STRING) { 79 data_string *ds = data_string_init(); 80 buffer_append_int(&ds->value, ((data_integer*)op1)->value); 81 buffer_append_string_buffer(&ds->value, &((data_string*)op2)->value); 82 op1->fn->free(op1); 83 return (data_unset *)ds; 84 } else { 85 fprintf(stderr, "data type mismatch, cannot merge\n"); 86 op1->fn->free(op1); 87 return NULL; 88 } 89 } 90 91 switch (op1->type) { 92 case TYPE_STRING: 93 buffer_append_string_buffer(&((data_string *)op1)->value, &((data_string *)op2)->value); 94 break; 95 case TYPE_INTEGER: 96 ((data_integer *)op1)->value += ((data_integer *)op2)->value; 97 break; 98 case TYPE_ARRAY: { 99 array *dst = &((data_array *)op1)->value; 100 array *src = &((data_array *)op2)->value; 101 data_unset *du; 102 size_t i; 103 104 for (i = 0; i < src->used; i ++) { 105 du = (data_unset *)src->data[i]; 106 if (du) { 107 if (buffer_is_empty(&du->key) || !array_get_element_klen(dst, CONST_BUF_LEN(&du->key))) { 108 array_insert_unique(dst, du->fn->copy(du)); 109 } else { 110 fprintf(stderr, "Duplicate array-key '%s'\n", du->key.ptr); 111 op1->fn->free(op1); 112 return NULL; 113 } 114 } 115 } 116 break; 117 default: 118 force_assert(0); 119 break; 120 } 121 } 122 return op1; 123 } 124 125 static int configparser_remoteip_normalize_compat(buffer *rvalue) { 126 /* $HTTP["remoteip"] IPv6 accepted with or without '[]' for config compat 127 * http_request_host_normalize() expects IPv6 with '[]', 128 * and config processing at runtime expects COMP_HTTP_REMOTE_IP 129 * compared without '[]', so strip '[]' after normalization */ 130 buffer *b = buffer_init(); 131 int rc; 132 133 if (rvalue->ptr[0] != '[') { 134 buffer_append_string_len(b, CONST_STR_LEN("[")); 135 buffer_append_string_buffer(b, rvalue); 136 buffer_append_string_len(b, CONST_STR_LEN("]")); 137 } else { 138 buffer_append_string_buffer(b, rvalue); 139 } 140 141 rc = http_request_host_normalize(b, 0); 142 143 if (0 == rc) { 144 /* remove surrounding '[]' */ 145 size_t blen = buffer_string_length(b); 146 if (blen > 1) buffer_copy_string_len(rvalue, b->ptr+1, blen-2); 147 } 148 149 buffer_free(b); 150 return rc; 151 } 152 153 } 154 155 %parse_failure { 156 ctx->ok = 0; 157 } 158 159 input ::= metalines. 160 metalines ::= metalines metaline. 161 metalines ::= . 162 metaline ::= varline. 163 metaline ::= global. 164 metaline ::= condlines(A) EOL. { A = NULL; } 165 metaline ::= include. 166 metaline ::= include_shell. 167 metaline ::= EOL. 168 169 %type value {data_unset *} 170 %type expression {data_unset *} 171 %type aelement {data_unset *} 172 %type condline {data_config *} 173 %type cond_else {data_config *} 174 %type condlines {data_config *} 175 %type aelements {array *} 176 %type array {array *} 177 %type key {buffer *} 178 %type stringop {buffer *} 179 180 %type cond {config_cond_t } 181 182 %destructor value { if ($$) $$->fn->free($$); } 183 %destructor expression { if ($$) $$->fn->free($$); } 184 %destructor aelement { if ($$) $$->fn->free($$); } 185 %destructor aelements { array_free($$); } 186 %destructor array { array_free($$); } 187 %destructor key { buffer_free($$); } 188 %destructor stringop { buffer_free($$); } 189 190 %token_type {buffer *} 191 %token_destructor { buffer_free($$); } 192 193 varline ::= key(A) ASSIGN expression(B). { 194 if (ctx->ok) { 195 buffer_copy_buffer(&B->key, A); 196 if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) { 197 fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n", 198 ctx->current->context_ndx, 199 ctx->current->key.ptr, A->ptr); 200 ctx->ok = 0; 201 } else if (NULL == array_get_element_klen(ctx->current->value, CONST_BUF_LEN(&B->key))) { 202 array_insert_unique(ctx->current->value, B); 203 B = NULL; 204 } else { 205 fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n", 206 ctx->current->context_ndx, 207 ctx->current->key.ptr, B->key.ptr); 208 ctx->ok = 0; 209 } 210 } 211 buffer_free(A); 212 A = NULL; 213 if (B) B->fn->free(B); 214 B = NULL; 215 } 216 217 varline ::= key(A) FORCE_ASSIGN expression(B). { 218 if (ctx->ok) { 219 if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) { 220 fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n", 221 ctx->current->context_ndx, 222 ctx->current->key.ptr, A->ptr); 223 ctx->ok = 0; 224 } else { 225 buffer_copy_buffer(&B->key, A); 226 array_replace(ctx->current->value, B); 227 B = NULL; 228 } 229 } 230 buffer_free(A); 231 A = NULL; 232 if (B) B->fn->free(B); 233 B = NULL; 234 } 235 236 varline ::= key(A) APPEND expression(B). { 237 if (ctx->ok) { 238 array *vars = ctx->current->value; 239 data_unset *du; 240 241 if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) { 242 fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n", 243 ctx->current->context_ndx, 244 ctx->current->key.ptr, A->ptr); 245 ctx->ok = 0; 246 } else if (NULL != (du = array_extract_element_klen(vars, CONST_BUF_LEN(A))) || NULL != (du = configparser_get_variable(ctx, A))) { 247 du = configparser_merge_data(du, B); 248 if (NULL == du) { 249 ctx->ok = 0; 250 } 251 else { 252 buffer_copy_buffer(&du->key, A); 253 array_insert_unique(ctx->current->value, du); 254 } 255 } else { 256 buffer_copy_buffer(&B->key, A); 257 array_insert_unique(ctx->current->value, B); 258 B = NULL; 259 } 260 } 261 buffer_free(A); 262 A = NULL; 263 if (B) B->fn->free(B); 264 B = NULL; 265 } 266 267 key(A) ::= LKEY(B). { 268 if (strchr(B->ptr, '.') == NULL) { 269 A = buffer_init_string("var."); 270 buffer_append_string_buffer(A, B); 271 } else { 272 A = B; 273 B = NULL; 274 } 275 buffer_free(B); 276 B = NULL; 277 } 278 279 expression(A) ::= expression(B) PLUS value(C). { 280 A = NULL; 281 if (ctx->ok) { 282 A = configparser_merge_data(B, C); 283 B = NULL; 284 if (NULL == A) { 285 ctx->ok = 0; 286 } 287 } 288 if (B) B->fn->free(B); 289 B = NULL; 290 if (C) C->fn->free(C); 291 C = NULL; 292 } 293 294 expression(A) ::= value(B). { 295 A = B; 296 B = NULL; 297 } 298 299 value(A) ::= key(B). { 300 A = NULL; 301 if (ctx->ok) { 302 if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) { 303 char *env; 304 305 if (NULL != (env = getenv(B->ptr + 4))) { 306 data_string *ds; 307 ds = data_string_init(); 308 buffer_append_string(&ds->value, env); 309 A = (data_unset *)ds; 310 } 311 else { 312 fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4); 313 ctx->ok = 0; 314 } 315 } else if (NULL == (A = configparser_get_variable(ctx, B))) { 316 fprintf(stderr, "Undefined config variable: %s\n", B->ptr); 317 ctx->ok = 0; 318 } 319 } 320 buffer_free(B); 321 B = NULL; 322 } 323 324 value(A) ::= STRING(B). { 325 A = (data_unset *)data_string_init(); 326 buffer_copy_buffer(&((data_string *)A)->value, B); 327 } 328 329 value(A) ::= INTEGER(B). { 330 char *endptr; 331 A = (data_unset *)data_integer_init(); 332 errno = 0; 333 ((data_integer *)(A))->value = strtol(B->ptr, &endptr, 10); 334 /* skip trailing whitespace */ 335 if (endptr != B->ptr) while (isspace(*(unsigned char *)endptr)) endptr++; 336 if (0 != errno || *endptr != '\0') { 337 fprintf(stderr, "error parsing number: '%s'\n", B->ptr); 338 ctx->ok = 0; 339 } 340 buffer_free(B); 341 B = NULL; 342 } 343 value(A) ::= array(B). { 344 A = (data_unset *)data_array_init(); 345 array_copy_array(&((data_array *)(A))->value, B); 346 B = NULL; 347 } 348 array(A) ::= LPARAN RPARAN. { 349 A = array_init(8); 350 } 351 array(A) ::= LPARAN aelements(B) RPARAN. { 352 A = B; 353 B = NULL; 354 } 355 356 aelements(A) ::= aelements(C) COMMA aelement(B). { 357 A = NULL; 358 if (ctx->ok) { 359 if (buffer_is_empty(&B->key) || 360 NULL == array_get_element_klen(C, CONST_BUF_LEN(&B->key))) { 361 array_insert_unique(C, B); 362 B = NULL; 363 } else { 364 fprintf(stderr, "Error: duplicate array-key: %s. Please get rid of the duplicate entry.\n", 365 B->key.ptr); 366 ctx->ok = 0; 367 } 368 369 A = C; 370 C = NULL; 371 } 372 array_free(C); 373 C = NULL; 374 if (B) B->fn->free(B); 375 B = NULL; 376 } 377 378 aelements(A) ::= aelements(C) COMMA. { 379 A = C; 380 C = NULL; 381 } 382 383 aelements(A) ::= aelement(B). { 384 A = NULL; 385 if (ctx->ok) { 386 A = array_init(4); 387 array_insert_unique(A, B); 388 B = NULL; 389 } 390 if (B) B->fn->free(B); 391 B = NULL; 392 } 393 394 aelement(A) ::= expression(B). { 395 A = B; 396 B = NULL; 397 } 398 aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). { 399 A = NULL; 400 if (ctx->ok) { 401 buffer_copy_buffer(&C->key, B); 402 403 A = C; 404 C = NULL; 405 } 406 if (C) C->fn->free(C); 407 C = NULL; 408 buffer_free(B); 409 B = NULL; 410 } 411 412 eols ::= EOL. 413 eols ::= . 414 415 globalstart ::= GLOBAL. { 416 data_config *dc; 417 dc = configparser_get_data_config(ctx->srv->config_context, CONST_STR_LEN("global")); 418 force_assert(dc); 419 configparser_push(ctx, dc, 0); 420 } 421 422 global ::= globalstart LCURLY metalines RCURLY. { 423 force_assert(ctx->current); 424 configparser_pop(ctx); 425 force_assert(ctx->current); 426 } 427 428 condlines(A) ::= condlines(B) eols ELSE condline(C). { 429 A = NULL; 430 if (ctx->ok) { 431 if (B->context_ndx >= C->context_ndx) { 432 fprintf(stderr, "unreachable else condition\n"); 433 ctx->ok = 0; 434 } 435 if (B->cond == CONFIG_COND_ELSE) { 436 fprintf(stderr, "unreachable condition following else catch-all\n"); 437 ctx->ok = 0; 438 } 439 C->prev = B; 440 B->next = C; 441 A = C; 442 } 443 B = NULL; 444 C = NULL; 445 } 446 447 condlines(A) ::= condlines(B) eols ELSE cond_else(C). { 448 A = NULL; 449 if (ctx->ok) { 450 if (B->context_ndx >= C->context_ndx) { 451 fprintf(stderr, "unreachable else condition\n"); 452 ctx->ok = 0; 453 } 454 if (B->cond == CONFIG_COND_ELSE) { 455 fprintf(stderr, "unreachable condition following else catch-all\n"); 456 ctx->ok = 0; 457 } 458 } 459 if (ctx->ok) { 460 size_t pos; 461 data_config *dc; 462 dc = (data_config *)array_extract_element_klen(ctx->all_configs, CONST_BUF_LEN(&C->key)); 463 force_assert(C == dc); 464 buffer_copy_buffer(&C->key, &B->key); 465 C->comp = B->comp; 466 /*buffer_copy_buffer(C->comp_key, B->comp_key);*/ 467 /*buffer_copy_buffer(&C->string, &B->string);*/ 468 pos = buffer_string_length(&C->key)-buffer_string_length(&B->string)-2; 469 switch(B->cond) { 470 case CONFIG_COND_NE: 471 C->key.ptr[pos] = '='; /* opposite cond */ 472 /*buffer_copy_string_len(C->op, CONST_STR_LEN("=="));*/ 473 break; 474 case CONFIG_COND_EQ: 475 C->key.ptr[pos] = '!'; /* opposite cond */ 476 /*buffer_copy_string_len(C->op, CONST_STR_LEN("!="));*/ 477 break; 478 case CONFIG_COND_NOMATCH: 479 C->key.ptr[pos] = '='; /* opposite cond */ 480 /*buffer_copy_string_len(C->op, CONST_STR_LEN("=~"));*/ 481 break; 482 case CONFIG_COND_MATCH: 483 C->key.ptr[pos] = '!'; /* opposite cond */ 484 /*buffer_copy_string_len(C->op, CONST_STR_LEN("!~"));*/ 485 break; 486 default: /* should not happen; CONFIG_COND_ELSE checked further above */ 487 force_assert(0); 488 } 489 490 if (NULL == (dc = configparser_get_data_config(ctx->all_configs, CONST_BUF_LEN(&C->key)))) { 491 /* re-insert into ctx->all_configs with new C->key */ 492 array_insert_unique(ctx->all_configs, (data_unset *)C); 493 C->prev = B; 494 B->next = C; 495 } else { 496 fprintf(stderr, "unreachable else condition\n"); 497 ctx->ok = 0; 498 C->fn->free((data_unset *)C); 499 C = dc; 500 } 501 502 A = C; 503 } 504 B = NULL; 505 C = NULL; 506 } 507 508 condlines(A) ::= condline(B). { 509 A = B; 510 B = NULL; 511 } 512 513 condline(A) ::= context LCURLY metalines RCURLY. { 514 A = NULL; 515 if (ctx->ok) { 516 data_config *cur; 517 518 cur = ctx->current; 519 configparser_pop(ctx); 520 521 force_assert(cur && ctx->current); 522 523 A = cur; 524 } 525 } 526 527 cond_else(A) ::= context_else LCURLY metalines RCURLY. { 528 A = NULL; 529 if (ctx->ok) { 530 data_config *cur; 531 532 cur = ctx->current; 533 configparser_pop(ctx); 534 535 force_assert(cur && ctx->current); 536 537 A = cur; 538 } 539 } 540 541 context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expression(D). { 542 data_config *dc; 543 buffer *b = NULL, *rvalue; 544 const char *op = NULL; 545 546 if (ctx->ok && D->type != TYPE_STRING) { 547 fprintf(stderr, "rvalue must be string"); 548 ctx->ok = 0; 549 } 550 551 if (ctx->ok) { 552 switch(E) { 553 case CONFIG_COND_NE: 554 op = "!="; 555 break; 556 case CONFIG_COND_EQ: 557 op = "=="; 558 break; 559 case CONFIG_COND_NOMATCH: 560 op = "!~"; 561 break; 562 case CONFIG_COND_MATCH: 563 op = "=~"; 564 break; 565 default: 566 force_assert(0); 567 return; /* unreachable */ 568 } 569 570 b = buffer_init(); 571 buffer_copy_buffer(b, &ctx->current->key); 572 buffer_append_string_len(b, CONST_STR_LEN("/")); 573 buffer_append_string_buffer(b, B); 574 buffer_append_string_buffer(b, C); 575 buffer_append_string_len(b, op, 2); 576 rvalue = &((data_string*)D)->value; 577 buffer_append_string_buffer(b, rvalue); 578 579 if (NULL != (dc = configparser_get_data_config(ctx->all_configs, CONST_BUF_LEN(b)))) { 580 configparser_push(ctx, dc, 0); 581 } else { 582 static const struct { 583 comp_key_t comp; 584 char *comp_key; 585 size_t len; 586 } comps[] = { 587 { COMP_SERVER_SOCKET, CONST_STR_LEN("SERVER[\"socket\"]" ) }, 588 { COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) }, 589 { COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) }, 590 { COMP_HTTP_REQUEST_HEADER,CONST_STR_LEN("HTTP[\"referer\"]" ) }, 591 { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) }, 592 { COMP_HTTP_REQUEST_HEADER,CONST_STR_LEN("HTTP[\"user-agent\"]" ) }, 593 { COMP_HTTP_LANGUAGE, CONST_STR_LEN("HTTP[\"language\"]" ) }, 594 { COMP_HTTP_REQUEST_HEADER,CONST_STR_LEN("HTTP[\"cookie\"]" ) }, 595 { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) }, 596 { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) }, 597 { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") }, 598 { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") }, 599 { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") }, 600 { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) }, 601 { COMP_UNSET, NULL, 0 }, 602 }; 603 size_t i; 604 605 dc = data_config_init(); 606 607 buffer_copy_buffer(&dc->key, b); 608 dc->op = op; 609 buffer_copy_buffer(dc->comp_tag, C); 610 buffer_copy_buffer(dc->comp_key, B); 611 buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\"")); 612 buffer_append_string_buffer(dc->comp_key, C); 613 buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]")); 614 dc->cond = E; 615 616 for (i = 0; comps[i].comp_key; i ++) { 617 if (buffer_is_equal_string( 618 dc->comp_key, comps[i].comp_key, comps[i].len)) { 619 dc->comp = comps[i].comp; 620 break; 621 } 622 } 623 if (COMP_UNSET == dc->comp) { 624 if (buffer_is_equal_string(B, CONST_STR_LEN("REQUEST_HEADER"))) { 625 dc->comp = COMP_HTTP_REQUEST_HEADER; 626 } 627 else { 628 fprintf(stderr, "error comp_key %s", dc->comp_key->ptr); 629 ctx->ok = 0; 630 } 631 } 632 else if (COMP_HTTP_LANGUAGE == dc->comp) { 633 dc->comp = COMP_HTTP_REQUEST_HEADER; 634 buffer_copy_string_len(dc->comp_tag, CONST_STR_LEN("Accept-Language")); 635 } 636 else if (COMP_HTTP_USER_AGENT == dc->comp) { 637 dc->comp = COMP_HTTP_REQUEST_HEADER; 638 buffer_copy_string_len(dc->comp_tag, CONST_STR_LEN("User-Agent")); 639 } 640 else if (COMP_HTTP_REMOTE_IP == dc->comp 641 && (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE)) { 642 char * const slash = strchr(rvalue->ptr, '/'); /* CIDR mask */ 643 char * const colon = strchr(rvalue->ptr, ':'); /* IPv6 */ 644 if (NULL != slash && slash == rvalue->ptr){/*(skip AF_UNIX /path/file)*/ 645 } 646 else if (NULL != slash) { 647 char *nptr; 648 const unsigned long nm_bits = strtoul(slash + 1, &nptr, 10); 649 if (*nptr || 0 == nm_bits || nm_bits > (NULL != colon ? 128 : 32)) { 650 /*(also rejects (slash+1 == nptr) which results in nm_bits = 0)*/ 651 fprintf(stderr, "invalid or missing netmask: %s\n", rvalue->ptr); 652 ctx->ok = 0; 653 } 654 else { 655 int rc; 656 buffer_string_set_length(rvalue, (size_t)(slash - rvalue->ptr)); /*(truncate)*/ 657 rc = (NULL == colon) 658 ? http_request_host_normalize(rvalue, 0) 659 : configparser_remoteip_normalize_compat(rvalue); 660 buffer_append_string_len(rvalue, CONST_STR_LEN("/")); 661 buffer_append_int(rvalue, (int)nm_bits); 662 if (0 != rc) { 663 fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr); 664 ctx->ok = 0; 665 } 666 } 667 } 668 else { 669 int rc = (NULL == colon) 670 ? http_request_host_normalize(rvalue, 0) 671 : configparser_remoteip_normalize_compat(rvalue); 672 if (0 != rc) { 673 fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr); 674 ctx->ok = 0; 675 } 676 } 677 } 678 else if (COMP_SERVER_SOCKET == dc->comp) { 679 /*(redundant with parsing in network.c; not actually required here)*/ 680 if (rvalue->ptr[0] != ':' /*(network.c special-cases ":" and "[]")*/ 681 && !(rvalue->ptr[0] == '[' && rvalue->ptr[1] == ']')) { 682 if (http_request_host_normalize(rvalue, 0)) { 683 fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr); 684 ctx->ok = 0; 685 } 686 } 687 } 688 else if (COMP_HTTP_HOST == dc->comp) { 689 if (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE) { 690 if (http_request_host_normalize(rvalue, 0)) { 691 fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr); 692 ctx->ok = 0; 693 } 694 } 695 } 696 697 if (COMP_HTTP_REQUEST_HEADER == dc->comp) { 698 dc->ext = http_header_hkey_get(CONST_BUF_LEN(dc->comp_tag)); 699 } 700 701 buffer_copy_buffer(&dc->string, rvalue); 702 703 if (ctx->ok) switch(E) { 704 case CONFIG_COND_NE: 705 case CONFIG_COND_EQ: 706 break; 707 case CONFIG_COND_NOMATCH: 708 case CONFIG_COND_MATCH: { 709 if (!data_config_pcre_compile(dc)) { 710 ctx->ok = 0; 711 } 712 break; 713 } 714 715 default: 716 fprintf(stderr, "unknown condition for $%s[%s]\n", 717 B->ptr, C->ptr); 718 ctx->ok = 0; 719 break; 720 } 721 722 if (ctx->ok) { 723 configparser_push(ctx, dc, 1); 724 } else { 725 dc->fn->free((data_unset*) dc); 726 } 727 } 728 } 729 730 buffer_free(b); 731 buffer_free(B); 732 B = NULL; 733 buffer_free(C); 734 C = NULL; 735 if (D) D->fn->free(D); 736 D = NULL; 737 } 738 739 context_else ::= . { 740 if (ctx->ok) { 741 data_config *dc = data_config_init(); 742 buffer_copy_buffer(&dc->key, &ctx->current->key); 743 buffer_append_string_len(&dc->key, CONST_STR_LEN("/")); 744 buffer_append_string_len(&dc->key, CONST_STR_LEN("else_tmp_token")); 745 dc->cond = CONFIG_COND_ELSE; 746 configparser_push(ctx, dc, 1); 747 } 748 } 749 750 cond(A) ::= EQ. { 751 A = CONFIG_COND_EQ; 752 } 753 cond(A) ::= MATCH. { 754 A = CONFIG_COND_MATCH; 755 } 756 cond(A) ::= NE. { 757 A = CONFIG_COND_NE; 758 } 759 cond(A) ::= NOMATCH. { 760 A = CONFIG_COND_NOMATCH; 761 } 762 763 stringop(A) ::= expression(B). { 764 A = NULL; 765 if (ctx->ok) { 766 if (B->type == TYPE_STRING) { 767 A = buffer_init_buffer(&((data_string*)B)->value); 768 } else if (B->type == TYPE_INTEGER) { 769 A = buffer_init(); 770 buffer_append_int(A, ((data_integer *)B)->value); 771 } else { 772 fprintf(stderr, "operand must be string"); 773 ctx->ok = 0; 774 } 775 } 776 if (B) B->fn->free(B); 777 B = NULL; 778 } 779 780 include ::= INCLUDE stringop(A). { 781 if (ctx->ok) { 782 if (0 != config_parse_file(ctx->srv, ctx, A->ptr)) { 783 ctx->ok = 0; 784 } 785 } 786 buffer_free(A); 787 A = NULL; 788 } 789 790 include_shell ::= INCLUDE_SHELL stringop(A). { 791 if (ctx->ok) { 792 if (0 != config_parse_cmd(ctx->srv, ctx, A->ptr)) { 793 ctx->ok = 0; 794 } 795 } 796 buffer_free(A); 797 A = NULL; 798 } 799