mirror of
https://github.com/cesanta/mongoose.git
synced 2025-06-29 17:37:51 +08:00
Options ssi_extensions, cgi_extensions became cgi_pattern, ssi_pattern
This commit is contained in:
parent
01c5ee0973
commit
ed70793670
61
mongoose.1
61
mongoose.1
@ -29,8 +29,22 @@ mongoose listen on HTTP port 80 and HTTPS port 443, one should start it as:
|
|||||||
.Pp
|
.Pp
|
||||||
Unlike other web servers,
|
Unlike other web servers,
|
||||||
.Nm
|
.Nm
|
||||||
does not expect CGI scripts to be put in a special directory. CGI scripts can
|
does not require CGI scripts be put in a special directory. CGI scripts can
|
||||||
be anywhere. CGI (and SSI) files are recognized by the file extension.
|
be anywhere. CGI (and SSI) files are recognized by the file name pattern.
|
||||||
|
.Nm
|
||||||
|
uses shell-like glob patterns with the following syntax:
|
||||||
|
.Bl -tag -compact -width indent
|
||||||
|
.It **
|
||||||
|
Matches everything
|
||||||
|
.It *
|
||||||
|
Matches everything but slash character, '/'
|
||||||
|
.It ?
|
||||||
|
Matches any character
|
||||||
|
.It |
|
||||||
|
Matches if pattern on the left side or the right side matches. Pattern on the
|
||||||
|
left side is matched first
|
||||||
|
.El
|
||||||
|
All other characters in the pattern match themselves.
|
||||||
.Pp
|
.Pp
|
||||||
If no arguments are given,
|
If no arguments are given,
|
||||||
.Nm
|
.Nm
|
||||||
@ -48,9 +62,11 @@ Add/edit user's password in the passwords file. Deleting users can be done
|
|||||||
with any text editor. Functionality is similar to Apache's
|
with any text editor. Functionality is similar to Apache's
|
||||||
.Ic htdigest
|
.Ic htdigest
|
||||||
utility.
|
utility.
|
||||||
.It Fl C Ar cgi_extensions
|
.It Fl C Ar cgi_pattern
|
||||||
Comma-separated list of CGI extensions. All files having these extensions
|
All files that fully match cgi_pattern are treated as CGI.
|
||||||
are treated as CGI scripts. Default: ".cgi,.pl,.php"
|
Default pattern allows CGI files be
|
||||||
|
anywhere. To restrict CGIs to certain directory, use e.g. "-C /cgi-bin/**.cgi".
|
||||||
|
Default: "**.cgi|**.pl|**.php"
|
||||||
.It Fl E Ar cgi_environment
|
.It Fl E Ar cgi_environment
|
||||||
Extra environment variables to be passed to the CGI script in addition to
|
Extra environment variables to be passed to the CGI script in addition to
|
||||||
standard ones. The list must be comma-separated list of X=Y pairs, like this:
|
standard ones. The list must be comma-separated list of X=Y pairs, like this:
|
||||||
@ -62,8 +78,8 @@ DELETE methods are used. Default: ""
|
|||||||
Use
|
Use
|
||||||
.Ar cgi_interpreter
|
.Ar cgi_interpreter
|
||||||
as a CGI interpreter for all CGI scripts regardless script extension.
|
as a CGI interpreter for all CGI scripts regardless script extension.
|
||||||
Default: "". Mongoose decides which interpreter to use by looking at
|
Mongoose decides which interpreter to use by looking at
|
||||||
the first line of a CGI script.
|
the first line of a CGI script. Default: "".
|
||||||
.It Fl M Ar max_request_size
|
.It Fl M Ar max_request_size
|
||||||
Maximum HTTP request size in bytes. Default: "16384"
|
Maximum HTTP request size in bytes. Default: "16384"
|
||||||
.It Fl P Ar protect_uri
|
.It Fl P Ar protect_uri
|
||||||
@ -71,10 +87,10 @@ Comma separated list of URI=PATH pairs, specifying that given URIs
|
|||||||
must be protected with respected password files. Default: ""
|
must be protected with respected password files. Default: ""
|
||||||
.It Fl R Ar authentication_domain
|
.It Fl R Ar authentication_domain
|
||||||
Authorization realm. Default: "mydomain.com"
|
Authorization realm. Default: "mydomain.com"
|
||||||
.It Fl S Ar ssi_extensions
|
.It Fl S Ar ssi_pattern
|
||||||
Comma separated list of SSI extensions. Unknown SSI directives are silently
|
All files that fully match ssi_pattern are treated as SSI.
|
||||||
ignored. Currently, two SSI directives supported, "include" and "exec".
|
Unknown SSI directives are silently ignored. Currently, two SSI directives
|
||||||
Default: "shtml,shtm"
|
are supported, "include" and "exec". Default: "**.shtml|**.shtm"
|
||||||
.It Fl a Ar access_log_file
|
.It Fl a Ar access_log_file
|
||||||
Access log file. Default: "", no logging is done.
|
Access log file. Default: "", no logging is done.
|
||||||
.It Fl d Ar enable_directory_listing
|
.It Fl d Ar enable_directory_listing
|
||||||
@ -109,17 +125,21 @@ prepended to the port number. For example, to bind to a loopback interface
|
|||||||
on port 80 and to all interfaces on HTTPS port 443, use
|
on port 80 and to all interfaces on HTTPS port 443, use
|
||||||
"mongoose -p 127.0.0.1:80,443s". Default: "8080"
|
"mongoose -p 127.0.0.1:80,443s". Default: "8080"
|
||||||
.It Fl r Ar document_root
|
.It Fl r Ar document_root
|
||||||
Location of the WWW root directory. A comma separated list of
|
Location of the WWW root directory. Default: "."
|
||||||
URI_PREFIX=DIRECTORY
|
|
||||||
pairs could be appended to it, allowing Mongoose to serve from multiple
|
|
||||||
directories. For example, "mongoose -p /var/www,/config=/etc,/garbage=/tmp".
|
|
||||||
Default: "."
|
|
||||||
.It Fl s Ar ssl_certificate
|
.It Fl s Ar ssl_certificate
|
||||||
Location of SSL certificate file. Default: ""
|
Location of SSL certificate file. Default: ""
|
||||||
.It Fl t Ar num_threads
|
.It Fl t Ar num_threads
|
||||||
Number of worker threads to start. Default: "10"
|
Number of worker threads to start. Default: "10"
|
||||||
.It Fl u Ar run_as_user
|
.It Fl u Ar run_as_user
|
||||||
Switch to given user's credentials after startup. Default: ""
|
Switch to given user's credentials after startup. Default: ""
|
||||||
|
.It Fl w Ar url_rewrite_patterns
|
||||||
|
Comma-separated list of URL rewrites in the form of
|
||||||
|
"pattern=substitution,..." If the "pattern" matches some prefix
|
||||||
|
of the requested URL, then matched prefix gets substituted with "substitution".
|
||||||
|
For example, "-w /config=/etc,**.doc|**.rtf=/cgi-bin/handle_doc.cgi"
|
||||||
|
will serve all URLs that start with "/config" from the "/etc" directory, and
|
||||||
|
call handle_doc.cgi script for .doc and .rtf file requests.
|
||||||
|
Default: ""
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
.Sh EMBEDDING
|
.Sh EMBEDDING
|
||||||
@ -131,13 +151,14 @@ for details.
|
|||||||
.Pp
|
.Pp
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Nm Fl r Ar /var/www,/aa=/tmp,/bb=/etc Fl s Ar /etc/cert.pem Fl p Ar 8080,8043s
|
.It Nm Fl r Ar /var/www Fl s Ar /etc/cert.pem Fl p Ar 8080,8043s
|
||||||
Start listening on port 8080 for HTTP, and 8043 for HTTPS connections.
|
Start serving files from /var/www. Listen on port 8080 for HTTP, and 8043
|
||||||
Use /etc/cert.pem as SSL certificate file. Web root is /var/www. In addition,
|
for HTTPS connections. Use /etc/cert.pem as SSL certificate file.
|
||||||
map directory /tmp to URI /aa, directory /etc to URI /bb.
|
|
||||||
.It Nm Fl l Ar -0.0.0.0/0,+10.0.0.0/8,+1.2.3.4
|
.It Nm Fl l Ar -0.0.0.0/0,+10.0.0.0/8,+1.2.3.4
|
||||||
Deny connections from everywhere, allow only IP address 1.2.3.4 and
|
Deny connections from everywhere, allow only IP address 1.2.3.4 and
|
||||||
all IP addresses from 10.0.0.0/8 subnet to connect.
|
all IP addresses from 10.0.0.0/8 subnet to connect.
|
||||||
|
.It Nm Fl w Ar **=/my/script.cgi
|
||||||
|
Invoke /my/script.cgi for every incoming request, regardless of the URL.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
.Sh COPYRIGHT
|
.Sh COPYRIGHT
|
||||||
|
137
mongoose.c
137
mongoose.c
@ -410,13 +410,13 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char *config_options[] = {
|
static const char *config_options[] = {
|
||||||
"C", "cgi_extensions", ".cgi,.pl,.php",
|
"C", "cgi_pattern", "**.cgi|**.pl|**.php",
|
||||||
"E", "cgi_environment", NULL,
|
"E", "cgi_environment", NULL,
|
||||||
"G", "put_delete_passwords_file", NULL,
|
"G", "put_delete_passwords_file", NULL,
|
||||||
"I", "cgi_interpreter", NULL,
|
"I", "cgi_interpreter", NULL,
|
||||||
"P", "protect_uri", NULL,
|
"P", "protect_uri", NULL,
|
||||||
"R", "authentication_domain", "mydomain.com",
|
"R", "authentication_domain", "mydomain.com",
|
||||||
"S", "ssi_extensions", ".shtml,.shtm",
|
"S", "ssi_pattern", "**.shtml|**.shtm",
|
||||||
"a", "access_log_file", NULL,
|
"a", "access_log_file", NULL,
|
||||||
"c", "ssl_chain_file", NULL,
|
"c", "ssl_chain_file", NULL,
|
||||||
"d", "enable_directory_listing", "yes",
|
"d", "enable_directory_listing", "yes",
|
||||||
@ -432,7 +432,7 @@ static const char *config_options[] = {
|
|||||||
"s", "ssl_certificate", NULL,
|
"s", "ssl_certificate", NULL,
|
||||||
"t", "num_threads", "10",
|
"t", "num_threads", "10",
|
||||||
"u", "run_as_user", NULL,
|
"u", "run_as_user", NULL,
|
||||||
"w", "rewrite", NULL,
|
"w", "url_rewrite_patterns", NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
#define ENTRIES_PER_CONFIG_OPTION 3
|
#define ENTRIES_PER_CONFIG_OPTION 3
|
||||||
@ -761,20 +761,45 @@ static const char *next_option(const char *list, struct vec *val,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int match_extension(const char *path, const char *ext_list) {
|
static int match_prefix(const char *pattern, int pattern_len, const char *str) {
|
||||||
struct vec ext_vec;
|
const char *or_str;
|
||||||
size_t path_len;
|
int i, j, len, res;
|
||||||
|
|
||||||
path_len = strlen(path);
|
if ((or_str = memchr(pattern, '|', pattern_len)) != NULL) {
|
||||||
|
res = match_prefix(pattern, or_str - pattern, str);
|
||||||
while ((ext_list = next_option(ext_list, &ext_vec, NULL)) != NULL)
|
return res > 0 ? res :
|
||||||
if (ext_vec.len < path_len &&
|
match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
|
||||||
mg_strncasecmp(path + path_len - ext_vec.len,
|
}
|
||||||
ext_vec.ptr, ext_vec.len) == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
|
i = j = res = 0;
|
||||||
|
for (; i < pattern_len; i++, j++) {
|
||||||
|
if (pattern[i] == '?' && str[j] != '\0') {
|
||||||
|
continue;
|
||||||
|
} else if (pattern[i] == '*') {
|
||||||
|
i++;
|
||||||
|
if (pattern[i] == '*') {
|
||||||
|
i++;
|
||||||
|
len = strlen(str + j);
|
||||||
|
} else {
|
||||||
|
len = strcspn(str + j, "/");
|
||||||
|
}
|
||||||
|
if (i == pattern_len) {
|
||||||
|
return j + len;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
res = match_prefix(pattern + i, pattern_len - i, str + j + len);
|
||||||
|
} while (res == 0 && len-- > 0);
|
||||||
|
return res == 0 ? 0 : j + res + len;
|
||||||
|
} else if (pattern[i] != str[j]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int full_match(const char *path, const char *pattern) {
|
||||||
|
return match_prefix(pattern, strlen(pattern), path) == (int) strlen(path);
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP 1.1 assumes keep alive if "Connection:" header is not set
|
// HTTP 1.1 assumes keep alive if "Connection:" header is not set
|
||||||
// This function must tolerate situations when connection info is not
|
// This function must tolerate situations when connection info is not
|
||||||
@ -1521,74 +1546,15 @@ int mg_get_cookie(const struct mg_connection *conn, const char *cookie_name,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mongoose allows to specify multiple directories to serve,
|
|
||||||
// like /var/www,/~bob=/home/bob. That means that root directory depends on URI.
|
|
||||||
// This function returns root dir for given URI.
|
|
||||||
static int get_document_root(const struct mg_connection *conn,
|
|
||||||
struct vec *document_root) {
|
|
||||||
const char *root, *uri;
|
|
||||||
int len_of_matched_uri;
|
|
||||||
struct vec uri_vec, path_vec;
|
|
||||||
|
|
||||||
uri = conn->request_info.uri;
|
|
||||||
len_of_matched_uri = 0;
|
|
||||||
root = next_option(conn->ctx->config[DOCUMENT_ROOT], document_root, NULL);
|
|
||||||
|
|
||||||
while ((root = next_option(root, &uri_vec, &path_vec)) != NULL) {
|
|
||||||
if (memcmp(uri, uri_vec.ptr, uri_vec.len) == 0) {
|
|
||||||
*document_root = path_vec;
|
|
||||||
len_of_matched_uri = uri_vec.len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len_of_matched_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int match_prefix(const char *pattern, int pattern_len, const char *str) {
|
|
||||||
const char *or_str;
|
|
||||||
int i, j, len, res;
|
|
||||||
|
|
||||||
if ((or_str = memchr(pattern, '|', pattern_len)) != NULL) {
|
|
||||||
res = match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
|
|
||||||
return res > 0 ? res : match_prefix(pattern, or_str - pattern, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = j = res = 0;
|
|
||||||
for (; i < pattern_len; i++, j++) {
|
|
||||||
if (pattern[i] == '?' && str[j] != '\0') {
|
|
||||||
continue;
|
|
||||||
} else if (pattern[i] == '*') {
|
|
||||||
i++;
|
|
||||||
if (pattern[i] == '*') {
|
|
||||||
i++;
|
|
||||||
len = strlen(str + j);
|
|
||||||
} else {
|
|
||||||
len = strcspn(str + j, "/");
|
|
||||||
}
|
|
||||||
if (i == pattern_len) {
|
|
||||||
return j + len;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
res = match_prefix(pattern + i, pattern_len - i, str + j + len);
|
|
||||||
} while (res == 0 && len-- > 0);
|
|
||||||
return res == 0 ? 0 : j + res + len;
|
|
||||||
} else if (pattern[i] != str[j]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void convert_uri_to_file_name(struct mg_connection *conn,
|
static void convert_uri_to_file_name(struct mg_connection *conn,
|
||||||
const char *uri, char *buf,
|
const char *uri, char *buf,
|
||||||
size_t buf_len) {
|
size_t buf_len) {
|
||||||
struct vec vec, a, b;
|
struct vec a, b;
|
||||||
const char *rewrite;
|
const char *rewrite;
|
||||||
int match_len;
|
int match_len;
|
||||||
|
|
||||||
match_len = get_document_root(conn, &vec);
|
mg_snprintf(conn, buf, buf_len, "%s%s", conn->ctx->config[DOCUMENT_ROOT],
|
||||||
mg_snprintf(conn, buf, buf_len, "%.*s%s", vec.len, vec.ptr, uri + match_len);
|
uri);
|
||||||
|
|
||||||
rewrite = conn->ctx->config[REWRITE];
|
rewrite = conn->ctx->config[REWRITE];
|
||||||
while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
|
while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
|
||||||
@ -2852,18 +2818,16 @@ static void prepare_cgi_environment(struct mg_connection *conn,
|
|||||||
const char *prog,
|
const char *prog,
|
||||||
struct cgi_env_block *blk) {
|
struct cgi_env_block *blk) {
|
||||||
const char *s, *slash;
|
const char *s, *slash;
|
||||||
struct vec var_vec, root;
|
struct vec var_vec;
|
||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
blk->len = blk->nvars = 0;
|
blk->len = blk->nvars = 0;
|
||||||
blk->conn = conn;
|
blk->conn = conn;
|
||||||
|
|
||||||
get_document_root(conn, &root);
|
|
||||||
|
|
||||||
addenv(blk, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
|
addenv(blk, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
|
||||||
addenv(blk, "SERVER_ROOT=%.*s", root.len, root.ptr);
|
addenv(blk, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
|
||||||
addenv(blk, "DOCUMENT_ROOT=%.*s", root.len, root.ptr);
|
addenv(blk, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
|
||||||
|
|
||||||
// Prepare the environment block
|
// Prepare the environment block
|
||||||
addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
|
addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
|
||||||
@ -3139,18 +3103,15 @@ static void send_ssi_file(struct mg_connection *, const char *, FILE *, int);
|
|||||||
static void do_ssi_include(struct mg_connection *conn, const char *ssi,
|
static void do_ssi_include(struct mg_connection *conn, const char *ssi,
|
||||||
char *tag, int include_level) {
|
char *tag, int include_level) {
|
||||||
char file_name[BUFSIZ], path[PATH_MAX], *p;
|
char file_name[BUFSIZ], path[PATH_MAX], *p;
|
||||||
struct vec root;
|
|
||||||
int is_ssi;
|
int is_ssi;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
get_document_root(conn, &root);
|
|
||||||
|
|
||||||
// sscanf() is safe here, since send_ssi_file() also uses buffer
|
// sscanf() is safe here, since send_ssi_file() also uses buffer
|
||||||
// of size BUFSIZ to get the tag. So strlen(tag) is always < BUFSIZ.
|
// of size BUFSIZ to get the tag. So strlen(tag) is always < BUFSIZ.
|
||||||
if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
|
if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
|
||||||
// File name is relative to the webserver root
|
// File name is relative to the webserver root
|
||||||
(void) mg_snprintf(conn, path, sizeof(path), "%.*s%c%s",
|
(void) mg_snprintf(conn, path, sizeof(path), "%s%c%s",
|
||||||
root.len, root.ptr, DIRSEP, file_name);
|
conn->ctx->config[DOCUMENT_ROOT], DIRSEP, file_name);
|
||||||
} else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1) {
|
} else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1) {
|
||||||
// File name is relative to the webserver working directory
|
// File name is relative to the webserver working directory
|
||||||
// or it is absolute system path
|
// or it is absolute system path
|
||||||
@ -3173,7 +3134,7 @@ static void do_ssi_include(struct mg_connection *conn, const char *ssi,
|
|||||||
tag, path, strerror(ERRNO));
|
tag, path, strerror(ERRNO));
|
||||||
} else {
|
} else {
|
||||||
set_close_on_exec(fileno(fp));
|
set_close_on_exec(fileno(fp));
|
||||||
is_ssi = match_extension(path, conn->ctx->config[SSI_EXTENSIONS]);
|
is_ssi = full_match(path, conn->ctx->config[SSI_EXTENSIONS]);
|
||||||
if (is_ssi) {
|
if (is_ssi) {
|
||||||
send_ssi_file(conn, path, fp, include_level + 1);
|
send_ssi_file(conn, path, fp, include_level + 1);
|
||||||
} else {
|
} else {
|
||||||
@ -3408,7 +3369,7 @@ static void handle_request(struct mg_connection *conn) {
|
|||||||
"Directory listing denied");
|
"Directory listing denied");
|
||||||
}
|
}
|
||||||
#if !defined(NO_CGI)
|
#if !defined(NO_CGI)
|
||||||
} else if (match_extension(path, conn->ctx->config[CGI_EXTENSIONS])) {
|
} else if (full_match(path, conn->ctx->config[CGI_EXTENSIONS])) {
|
||||||
if (strcmp(ri->request_method, "POST") &&
|
if (strcmp(ri->request_method, "POST") &&
|
||||||
strcmp(ri->request_method, "GET")) {
|
strcmp(ri->request_method, "GET")) {
|
||||||
send_http_error(conn, 501, "Not Implemented",
|
send_http_error(conn, 501, "Not Implemented",
|
||||||
@ -3417,7 +3378,7 @@ static void handle_request(struct mg_connection *conn) {
|
|||||||
handle_cgi_request(conn, path);
|
handle_cgi_request(conn, path);
|
||||||
}
|
}
|
||||||
#endif // !NO_CGI
|
#endif // !NO_CGI
|
||||||
} else if (match_extension(path, conn->ctx->config[SSI_EXTENSIONS])) {
|
} else if (full_match(path, conn->ctx->config[SSI_EXTENSIONS])) {
|
||||||
handle_ssi_file_request(conn, path);
|
handle_ssi_file_request(conn, path);
|
||||||
} else if (is_not_modified(conn, &st)) {
|
} else if (is_not_modified(conn, &st)) {
|
||||||
send_http_error(conn, 304, "Not Modified", "");
|
send_http_error(conn, 304, "Not Modified", "");
|
||||||
|
20
test/test.pl
20
test/test.pl
@ -150,6 +150,11 @@ if (scalar(@ARGV) > 0 and $ARGV[0] eq 'embedded') {
|
|||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scalar(@ARGV) > 0 and $ARGV[0] eq 'unit') {
|
||||||
|
do_unit_test();
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
# Make sure we load config file if no options are given.
|
# Make sure we load config file if no options are given.
|
||||||
# Command line options override config files settings
|
# Command line options override config files settings
|
||||||
write_file($config, "access_log_file access.log\nlistening_ports 12345\n");
|
write_file($config, "access_log_file access.log\nlistening_ports 12345\n");
|
||||||
@ -166,7 +171,7 @@ my $cmd = "$exe $config -listening_ports $port -access_log_file access.log ".
|
|||||||
"-extra_mime_types .bar=foo/bar,.tar.gz=blah,.baz=foo " .
|
"-extra_mime_types .bar=foo/bar,.tar.gz=blah,.baz=foo " .
|
||||||
'-put_delete_passwords_file test/passfile ' .
|
'-put_delete_passwords_file test/passfile ' .
|
||||||
'-access_control_list -0.0.0.0/0,+127.0.0.1 ' .
|
'-access_control_list -0.0.0.0/0,+127.0.0.1 ' .
|
||||||
"-document_root $root,/aiased=/etc/,/ta=$test_dir";
|
"-document_root $root -url_rewrite_patterns /aiased=/etc/,/ta=$test_dir";
|
||||||
$cmd .= ' -cgi_interpreter perl' if on_windows();
|
$cmd .= ' -cgi_interpreter perl' if on_windows();
|
||||||
spawn($cmd);
|
spawn($cmd);
|
||||||
|
|
||||||
@ -386,6 +391,7 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
|
|||||||
|
|
||||||
do_PUT_test();
|
do_PUT_test();
|
||||||
kill_spawned_child();
|
kill_spawned_child();
|
||||||
|
do_unit_test();
|
||||||
do_embedded_test();
|
do_embedded_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,6 +421,18 @@ sub do_PUT_test {
|
|||||||
"HTTP/1.1 100 Continue.+HTTP/1.1 200", 'PUT 100-Continue');
|
"HTTP/1.1 100 Continue.+HTTP/1.1 200", 'PUT 100-Continue');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub do_unit_test {
|
||||||
|
my $cmd = "cc -W -Wall -o $unit_test_exe $root/unit_test.c -I. ".
|
||||||
|
"-pthread -DNO_SSL ";
|
||||||
|
if (on_windows()) {
|
||||||
|
$cmd = "cl $root/embed.c mongoose.c /I. /nologo /DNO_SSL ".
|
||||||
|
"/DLISTENING_PORT=\\\"$port\\\" /link /out:$embed_exe.exe ws2_32.lib ";
|
||||||
|
}
|
||||||
|
print $cmd, "\n";
|
||||||
|
system($cmd) == 0 or fail("Cannot compile unit test");
|
||||||
|
system($unit_test_exe) == 0 or fail("Unit test failed!");
|
||||||
|
}
|
||||||
|
|
||||||
sub do_embedded_test {
|
sub do_embedded_test {
|
||||||
my $cmd = "cc -W -Wall -o $embed_exe $root/embed.c mongoose.c -I. ".
|
my $cmd = "cc -W -Wall -o $embed_exe $root/embed.c mongoose.c -I. ".
|
||||||
"-pthread -DNO_SSL -DLISTENING_PORT=\\\"$port\\\"";
|
"-pthread -DNO_SSL -DLISTENING_PORT=\\\"$port\\\"";
|
||||||
|
@ -8,6 +8,12 @@ int main(void) {
|
|||||||
assert(match_prefix("/*", 2, "/a/b/c") == 2);
|
assert(match_prefix("/*", 2, "/a/b/c") == 2);
|
||||||
assert(match_prefix("*/*", 3, "/a/b/c") == 2);
|
assert(match_prefix("*/*", 3, "/a/b/c") == 2);
|
||||||
assert(match_prefix("**/", 3, "/a/b/c") == 5);
|
assert(match_prefix("**/", 3, "/a/b/c") == 5);
|
||||||
|
assert(match_prefix("**.foo|**.bar", 13, "a.bar") == 5);
|
||||||
|
assert(match_prefix("a|b|cd", 6, "cdef") == 2);
|
||||||
|
assert(match_prefix("a|b|c?", 6, "cdef") == 2);
|
||||||
|
assert(match_prefix("a|?|cd", 6, "cdef") == 1);
|
||||||
|
assert(match_prefix("/a/**.cgi", 9, "/foo/bar/x.cgi") == 0);
|
||||||
|
assert(match_prefix("/a/**.cgi", 9, "/a/bar/x.cgi") == 12);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user