📄 mod_test_util_uri.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * This module is intended to test the util_uri routines by parsing a * bunch of urls and comparing the results with what we expect to * see. * * Usage: * * <Location /test-util-uri> * SetHandler test-util-uri * </Location> * * Then make a request to /test-util-uri. An html table of errors will * be output... and a total count of errors. */#include "httpd.h"#include "http_protocol.h"#include "http_config.h"#include "http_main.h"typedef struct { const char *scheme; const char *user; const char *password; const char *hostname; const char *port_str; const char *path; const char *query; const char *fragment;} test_uri_t;#define T_scheme 0x01#define T_user 0x02#define T_password 0x04#define T_hostname 0x08#define T_port_str 0x10#define T_path 0x20#define T_query 0x40#define T_fragment 0x80#define T_MAX 0x100/* The idea is that we list here a bunch of url pieces that we want * stitched together in every way that's valid. */static const test_uri_t uri_tests[] = { { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" }, { "http", "", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" }, { "http", "userid", "", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" }, { "http", "userid", "passwd", "", "80", "/path/goes/here", "query-here", "frag-here" }, { "http", "userid", "passwd", "hostname.goes.here", "", "/path/goes/here", "query-here", "frag-here" },#if 0 /* An empty path means two different things depending on whether this is a * relative or an absolute uri... consider <a href="#frag"> versus "GET * http://hostname HTTP/1.1". So this is why parse_uri_components returns * a NULL for path when it doesn't find one, instead of returning an empty * string. * * We don't really need to test it explicitly since path has no explicit * character that indicates its precense, and so we test empty paths all * the time by varying T_path in the loop. It would just cost us extra * code to special case the empty path string... */ { "http", "userid", "passwd", "hostname.goes.here", "80", "", "query-here", "frag-here" },#endif { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "", "frag-here" }, { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "" }, { "https", "user@d", "pa:swd", "hostname.goes.here.", "", "/~path/goes/here", "query&query?crud", "frag-here?baby" }};static char *my_stpcpy(char *d, const char *s){ while((*d = *s)) { ++d; ++s; } return d;}/* return the number of failures */static unsigned iterate_pieces(request_rec *r, const test_uri_t *pieces, int row){ unsigned u; pool *sub; char *input_uri; char *strp; uri_components result; unsigned expect; int status; unsigned failures; failures = 0; input_uri = ap_palloc(r->pool, strlen(pieces->scheme) + 3 + strlen(pieces->user) + 1 + strlen(pieces->password) + 1 + strlen(pieces->hostname) + 1 + strlen(pieces->port_str) + 1 + strlen(pieces->path) + + strlen(pieces->query) + 1 + strlen(pieces->fragment) + 1 + 1); for (u = 0; u < T_MAX; ++u) { strp = input_uri; expect = 0; /* a scheme requires a hostinfo and vice versa */ /* a hostinfo requires a hostname */ if (u & (T_scheme|T_user|T_password|T_hostname|T_port_str)) { expect |= T_scheme; strp = my_stpcpy(strp, pieces->scheme); *strp++ = ':'; *strp++ = '/'; *strp++ = '/'; /* can't have password without user */ if (u & (T_user|T_password)) { expect |= T_user; strp = my_stpcpy(strp, pieces->user); if (u & T_password) { expect |= T_password; *strp++ = ':'; strp = my_stpcpy(strp, pieces->password); } *strp++ = '@'; } expect |= T_hostname; strp = my_stpcpy(strp, pieces->hostname); if (u & T_port_str) { expect |= T_port_str; *strp++ = ':'; strp = my_stpcpy(strp, pieces->port_str); } } if (u & T_path) { expect |= T_path; strp = my_stpcpy(strp, pieces->path); } if (u & T_query) { expect |= T_query; *strp++ = '?'; strp = my_stpcpy(strp, pieces->query); } if (u & T_fragment) { expect |= T_fragment; *strp++ = '#'; strp = my_stpcpy(strp, pieces->fragment); } *strp = 0; sub = ap_make_sub_pool(r->pool); status = ap_parse_uri_components(sub, input_uri, &result); if (status == HTTP_OK) {#define CHECK(f) \ if ((expect & T_##f) \ && (result.f == NULL || strcmp(result.f, pieces->f))) { \ status = HTTP_INTERNAL_SERVER_ERROR; \ } \ else if (!(expect & T_##f) && result.f != NULL) { \ status = HTTP_INTERNAL_SERVER_ERROR; \ } CHECK(scheme) CHECK(user) CHECK(password) CHECK(hostname) CHECK(port_str) CHECK(path) CHECK(query) CHECK(fragment)#undef CHECK } if (status != HTTP_OK) { ap_rprintf(r, "<tr><td>%d</td><td>0x%02x</td><td>0x%02x</td><td>%d</td><td>\"%s\"</td>", row, u, expect, status, input_uri);#define DUMP(f) \ if (result.f) { \ ap_rvputs(r, "<td>\"", result.f, "\"<br>", NULL); \ } \ else { \ ap_rputs("<td>NULL<br>", r); \ } \ if (expect & T_##f) { \ ap_rvputs(r, "\"", pieces->f, "\"</td>", NULL); \ } \ else { \ ap_rputs("NULL</td>", r); \ } DUMP(scheme); DUMP(user); DUMP(password); DUMP(hostname); DUMP(port_str); DUMP(path); DUMP(query); DUMP(fragment);#undef DUMP ap_rputs("</tr>\n", r); ++failures; } ap_destroy_pool(sub); } return failures;}static int test_util_uri(request_rec *r){ unsigned total_failures; int i; r->allowed |= (1 << M_GET); if (r->method_number != M_GET) return DECLINED; r->content_type = "text/html"; ap_send_http_header(r);#ifdef CHARSET_EBCDIC /* Server-generated response, converted */ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);#endif if(r->header_only) { return 0; } ap_hard_timeout("test_util_uri", r); ap_rputs(DOCTYPE_HTML_2_0 "<html><body><p>Key:<dl><dt>row<dd>entry number in the uri_tests array<dt>u<dd>fields under test<dt>expected<dd>fields expected in the result<dt>status<dd>response from parse_uri_components, or 500 if unexpected results<dt>input uri<dd>the uri given to parse_uri_components</dl><p>The remaining fields are the pieces returned from parse_uri_components, andthe values we expected for each piece (resp.).<p>Only failures are displayed.<p><table><tr><th>row</th><th>u</th><th>expect</th><th>status</th><th>input uri</th>", r);#define HEADER(f) ap_rprintf(r, "<th>" #f "<br>0x%02x</th>", T_##f) HEADER(scheme); HEADER(user); HEADER(password); HEADER(hostname); HEADER(port_str); HEADER(path); HEADER(query); HEADER(fragment);#undef HEADER if (r->args) { i = atoi(r->args); total_failures = iterate_pieces(r, &uri_tests[i], i); } else { total_failures = 0; for (i = 0; i < sizeof(uri_tests) / sizeof(uri_tests[0]); ++i) { total_failures += iterate_pieces(r, &uri_tests[i], i); if (total_failures > 256) { ap_rprintf(r, "</table>\n<b>Stopped early to save your browser " "from certain death!</b>\nTOTAL FAILURES = %u\n", total_failures); return OK; } } } ap_rprintf(r, "</table>\nTOTAL FAILURES = %u\n", total_failures); return OK;}static const handler_rec test_util_uri_handlers[] ={ {"test-util-uri", test_util_uri}, {NULL}};module test_util_uri_module = { STANDARD_MODULE_STUFF, NULL, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ NULL, /* command table */ test_util_uri_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL /* header parser */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -