int main(int argc, char **argv) { char *conffile; const char *p, *val; int i, len; FAILIF(argc < 2, "Usage: %s <conffile> [<variable> [<value>]]\n", argv[0]); conffile = codaconf_file(argv[1]); if (argc < 3) { if (!conffile) { fprintf(stdout, "/dev/null\n"); exit(EXIT_FAILURE); } fprintf(stdout, "%s\n", conffile); exit(EXIT_SUCCESS); } /* Hmm, should we really copy the template file on lookups as well. On one * hand it makes a 'readonly' operation 'write' data. On the other hand * there would otherwise be no other way to use the default template * without modifications */ if (!conffile) { copy_template(argv[1]); conffile = codaconf_file(argv[1]); FAILIF(!conffile, "Failed to copy template file to '%s'\n", argv[1]); } codaconf_init_one(conffile); val = codaconf_lookup(argv[2], NULL); if (argc < 4) { FAILIF(!val, "Variable '%s' not found in '%s'\n", argv[2], conffile); fprintf(stdout, "%s\n", val); exit(EXIT_SUCCESS); } /* argc >= 4 */ /* check if this value was already set */ if (val) { p = val; for (i = 3; i <= argc; i++) { len = strlen(argv[i]); if (strncmp(argv[i], p, len) != 0) break; p = p + len; if (*p != ' ') break; p++; } if (i == argc - 1 && *p == '\0') exit(EXIT_SUCCESS); } do_rewrite(conffile, argc, argv); exit(EXIT_SUCCESS); }
int use_toolkit(char *url, char *toolkit_id, t_toolkit_options *options) { t_url_toolkit *toolkit; t_toolkit_rule *rule; bool condition_met, url_replaced = false; int result, skip = 0; char *file, *qmark, *header; regmatch_t pmatch[REGEXEC_NMATCH]; struct stat fileinfo; t_http_header *headers; if (options == NULL) { return UT_ERROR; } options->new_url = NULL; if ((toolkit = select_toolkit(toolkit_id, options->url_toolkit)) == NULL) { return UT_ERROR; } rule = toolkit->toolkit_rule; while (rule != NULL) { condition_met = false; /* Skip lines */ if (skip > 0) { skip--; rule = rule->next; continue; } /* Condition */ switch (rule->condition) { case tc_none: /* None */ condition_met = true; break; case tc_match: /* Match */ if (regexec(&(rule->pattern), url, REGEXEC_NMATCH, pmatch, 0) == 0) { condition_met = true; } if (rule->neg_match) { condition_met = (condition_met == false); } break; case tc_header: /* Header */ if (rule->header == NULL) { headers = options->http_headers; while (headers != NULL) { if (regexec(&(rule->pattern), headers->data + headers->value_offset, REGEXEC_NMATCH, pmatch, 0) == 0) { condition_met = true; } if (rule->neg_match) { condition_met = (condition_met == false); } if (condition_met) { break; } headers = headers->next; } } else { if ((header = get_http_header(rule->header, options->http_headers)) == NULL) { break; } if (regexec(&(rule->pattern), header, REGEXEC_NMATCH, pmatch, 0) == 0) { condition_met = true; } if (rule->neg_match) { condition_met = (condition_met == false); } } break; case tc_method: /* Request method */ if (strcmp(options->method, rule->parameter) == 0) { condition_met = true; } if (rule->neg_match) { condition_met = (condition_met == false); } break; case tc_request_uri: /* Request URI */ if (valid_uri(url, false) == false) { break; } if ((file = make_path(options->website_root, url)) == NULL) { return UT_ERROR; } if ((qmark = strchr(file, '?')) != NULL) { *qmark = '\0'; } url_decode(file); if (stat(file, &fileinfo) != -1) { switch (rule->value) { case IU_EXISTS: if (S_ISDIR(fileinfo.st_mode) || S_ISREG(fileinfo.st_mode)) { condition_met = true; } break; case IU_ISFILE: if (S_ISREG(fileinfo.st_mode)) { condition_met = true; } break; case IU_ISDIR: if (S_ISDIR(fileinfo.st_mode)) { condition_met = true; } break; } } free(file); break; case tc_total_connections: /* Total connections reached? */ condition_met = options->total_connections >= rule->value; break; #ifdef ENABLE_TLS case tc_use_tls: /* Client connections uses TLS? */ condition_met = options->use_tls; break; #endif } /* Condition not met */ if (condition_met == false) { rule = rule->next; continue; } /* Operation */ switch (rule->operation) { case to_none: /* None */ break; case to_ban: /* Ban client */ options->ban = rule->value; break; case to_deny_access: /* Deny access */ return UT_DENY_ACCESS; case to_omit_request_log: /* Omit requeest log */ options->log_request = false; break; case to_expire: /* Send Expire HTTP header */ options->expire = rule->value; options->caco_private = rule->caco_private; break; case to_fastcgi: /* Use FastCGI server */ options->fastcgi_server = rule->parameter; break; case to_redirect: /* Redirect client */ if (rule->neg_match) { if ((options->new_url = strdup(rule->parameter)) == NULL) { return UT_ERROR; } } else if (do_rewrite(url, &(rule->pattern), pmatch, rule->parameter, &(options->new_url), rule->match_loop) == -1) { if (options->new_url != NULL) { free(options->new_url); options->new_url = NULL; } return UT_ERROR; } if (options->new_url != NULL) { if (url_replaced) { free(url); } return UT_REDIRECT; } else if (url_replaced) { options->new_url = url; } break; case to_rewrite: /* Rewrite */ if (rule->neg_match) { if ((options->new_url = strdup(rule->parameter)) == NULL) { return UT_ERROR; } } else if (do_rewrite(url, &(rule->pattern), pmatch, rule->parameter, &(options->new_url), rule->match_loop) == -1) { if (options->new_url != NULL) { free(options->new_url); options->new_url = NULL; } return UT_ERROR; } if (options->new_url != NULL) { if (url_replaced) { free(url); } url = options->new_url; url_replaced = true; } else if (url_replaced) { options->new_url = url; } break; case to_skip: /* Skip */ skip = rule->value; break; case to_sub: /* Subroutine */ if (++(options->sub_depth) > MAX_SUB_DEPTH) { return UT_ERROR; } if ((result = use_toolkit(url, rule->parameter, options)) == UT_ERROR) { if (options->new_url != NULL) { free(options->new_url); options->new_url = NULL; } return UT_ERROR; } options->sub_depth--; if (options->new_url != NULL) { if (url_replaced) { free(url); } url = options->new_url; url_replaced = true; } else if (url_replaced) { options->new_url = url; } if (result != UT_RETURN) { return result; } break; case to_use: /* Replace URL */ if (url_replaced) { free(url); } if ((options->new_url = strdup(rule->parameter)) == NULL) { return UT_ERROR; } break; } /* Flow */ switch (rule->flow) { case tf_continue: /* Continue */ break; case tf_exit: /* Exit */ return UT_EXIT; case tf_return: /* Return */ return UT_RETURN; } rule = rule->next; } return UT_RETURN; }