mirror of
https://github.com/sheumann/hush.git
synced 2025-03-09 05:32:01 +00:00
httpd: add optional support for error pages
(by Pierre Metras <genepi@sympatico.ca>)
This commit is contained in:
parent
45946f8b51
commit
e58e8d9444
@ -170,6 +170,19 @@ config FEATURE_HTTPD_ENCODE_URL_STR
|
|||||||
For example, httpd -e "<Hello World>" as
|
For example, httpd -e "<Hello World>" as
|
||||||
"<Hello World>".
|
"<Hello World>".
|
||||||
|
|
||||||
|
config FEATURE_HTTPD_ERROR_PAGES
|
||||||
|
bool "Enable support for custom error pages"
|
||||||
|
default n
|
||||||
|
depends on HTTPD
|
||||||
|
help
|
||||||
|
This option allows you to define custom error pages in
|
||||||
|
the configuration file instead of the default HTTP status
|
||||||
|
error pages. For instance, if you add the line:
|
||||||
|
E404:/path/e404.html
|
||||||
|
in the config file, the server will respond the specified
|
||||||
|
'/path/e404.html' file instead of the terse '404 NOT FOUND'
|
||||||
|
message.
|
||||||
|
|
||||||
config IFCONFIG
|
config IFCONFIG
|
||||||
bool "ifconfig"
|
bool "ifconfig"
|
||||||
default n
|
default n
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
* A:10.0.0.0/255.255.255.128 # Allow any address that previous set
|
* A:10.0.0.0/255.255.255.128 # Allow any address that previous set
|
||||||
* A:127.0.0.1 # Allow local loopback connections
|
* A:127.0.0.1 # Allow local loopback connections
|
||||||
* D:* # Deny from other IP connections
|
* D:* # Deny from other IP connections
|
||||||
|
* E404:/path/e404.html # /path/e404.html is the 404 (not found) error page
|
||||||
* /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
|
* /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
|
||||||
* /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
|
* /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
|
||||||
* /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
|
* /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
|
||||||
@ -84,6 +85,10 @@
|
|||||||
* subdir http request, any merge is discarded when the process exits. As a
|
* subdir http request, any merge is discarded when the process exits. As a
|
||||||
* result, the subdir settings only have a lifetime of a single request.
|
* result, the subdir settings only have a lifetime of a single request.
|
||||||
*
|
*
|
||||||
|
* Custom error pages can contain an absolute path or be relative to
|
||||||
|
* 'home_httpd'. Error pages are to be static files (no CGI or script). Error
|
||||||
|
* page can only be defined in the root configuration file and are not taken
|
||||||
|
* into account in local (directories) config files.
|
||||||
*
|
*
|
||||||
* If -c is not set, an attempt will be made to open the default
|
* If -c is not set, an attempt will be made to open the default
|
||||||
* root configuration file. If -c is set and the file is not found, the
|
* root configuration file. If -c is set and the file is not found, the
|
||||||
@ -131,6 +136,84 @@ typedef struct Htaccess_IP {
|
|||||||
int allow_deny;
|
int allow_deny;
|
||||||
} Htaccess_IP;
|
} Htaccess_IP;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HTTP_OK = 200,
|
||||||
|
HTTP_MOVED_TEMPORARILY = 302,
|
||||||
|
HTTP_BAD_REQUEST = 400, /* malformed syntax */
|
||||||
|
HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */
|
||||||
|
HTTP_NOT_FOUND = 404,
|
||||||
|
HTTP_FORBIDDEN = 403,
|
||||||
|
HTTP_REQUEST_TIMEOUT = 408,
|
||||||
|
HTTP_NOT_IMPLEMENTED = 501, /* used for unrecognized requests */
|
||||||
|
HTTP_INTERNAL_SERVER_ERROR = 500,
|
||||||
|
HTTP_CONTINUE = 100,
|
||||||
|
#if 0 /* future use */
|
||||||
|
HTTP_SWITCHING_PROTOCOLS = 101,
|
||||||
|
HTTP_CREATED = 201,
|
||||||
|
HTTP_ACCEPTED = 202,
|
||||||
|
HTTP_NON_AUTHORITATIVE_INFO = 203,
|
||||||
|
HTTP_NO_CONTENT = 204,
|
||||||
|
HTTP_MULTIPLE_CHOICES = 300,
|
||||||
|
HTTP_MOVED_PERMANENTLY = 301,
|
||||||
|
HTTP_NOT_MODIFIED = 304,
|
||||||
|
HTTP_PAYMENT_REQUIRED = 402,
|
||||||
|
HTTP_BAD_GATEWAY = 502,
|
||||||
|
HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */
|
||||||
|
HTTP_RESPONSE_SETSIZE = 0xffffffff
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint16_t http_response_type[] = {
|
||||||
|
HTTP_OK,
|
||||||
|
HTTP_MOVED_TEMPORARILY,
|
||||||
|
HTTP_REQUEST_TIMEOUT,
|
||||||
|
HTTP_NOT_IMPLEMENTED,
|
||||||
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
|
HTTP_UNAUTHORIZED,
|
||||||
|
#endif
|
||||||
|
HTTP_NOT_FOUND,
|
||||||
|
HTTP_BAD_REQUEST,
|
||||||
|
HTTP_FORBIDDEN,
|
||||||
|
HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
#if 0 /* not implemented */
|
||||||
|
HTTP_CREATED,
|
||||||
|
HTTP_ACCEPTED,
|
||||||
|
HTTP_NO_CONTENT,
|
||||||
|
HTTP_MULTIPLE_CHOICES,
|
||||||
|
HTTP_MOVED_PERMANENTLY,
|
||||||
|
HTTP_NOT_MODIFIED,
|
||||||
|
HTTP_BAD_GATEWAY,
|
||||||
|
HTTP_SERVICE_UNAVAILABLE,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
const char *name;
|
||||||
|
const char *info;
|
||||||
|
} http_response[ARRAY_SIZE(http_response_type)] = {
|
||||||
|
{ "OK", NULL },
|
||||||
|
{ "Found", "Directories must end with a slash" }, /* ?? */
|
||||||
|
{ "Request Timeout", "No request appeared within 60 seconds" },
|
||||||
|
{ "Not Implemented", "The requested method is not recognized" },
|
||||||
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
|
{ "Unauthorized", "" },
|
||||||
|
#endif
|
||||||
|
{ "Not Found", "The requested URL was not found" },
|
||||||
|
{ "Bad Request", "Unsupported method" },
|
||||||
|
{ "Forbidden", "" },
|
||||||
|
{ "Internal Server Error", "Internal Server Error" },
|
||||||
|
#if 0 /* not implemented */
|
||||||
|
{ "Created" },
|
||||||
|
{ "Accepted" },
|
||||||
|
{ "No Content" },
|
||||||
|
{ "Multiple Choices" },
|
||||||
|
{ "Moved Permanently" },
|
||||||
|
{ "Not Modified" },
|
||||||
|
{ "Bad Gateway", "" },
|
||||||
|
{ "Service Unavailable", "" },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct globals {
|
struct globals {
|
||||||
int verbose; /* must be int (used by getopt32) */
|
int verbose; /* must be int (used by getopt32) */
|
||||||
smallint flg_deny_all;
|
smallint flg_deny_all;
|
||||||
@ -167,6 +250,9 @@ struct globals {
|
|||||||
#define hdr_buf bb_common_bufsiz1
|
#define hdr_buf bb_common_bufsiz1
|
||||||
char *hdr_ptr;
|
char *hdr_ptr;
|
||||||
int hdr_cnt;
|
int hdr_cnt;
|
||||||
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
|
const char *http_error_page[ARRAY_SIZE(http_response_type)];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#define G (*ptr_to_globals)
|
#define G (*ptr_to_globals)
|
||||||
#define verbose (G.verbose )
|
#define verbose (G.verbose )
|
||||||
@ -192,6 +278,7 @@ struct globals {
|
|||||||
#define iobuf (G.iobuf )
|
#define iobuf (G.iobuf )
|
||||||
#define hdr_ptr (G.hdr_ptr )
|
#define hdr_ptr (G.hdr_ptr )
|
||||||
#define hdr_cnt (G.hdr_cnt )
|
#define hdr_cnt (G.hdr_cnt )
|
||||||
|
#define http_error_page (G.http_error_page )
|
||||||
#define INIT_G() do { \
|
#define INIT_G() do { \
|
||||||
PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
|
PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
|
||||||
USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
|
USE_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
|
||||||
@ -200,70 +287,13 @@ struct globals {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
HTTP_OK = 200,
|
|
||||||
HTTP_MOVED_TEMPORARILY = 302,
|
|
||||||
HTTP_BAD_REQUEST = 400, /* malformed syntax */
|
|
||||||
HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */
|
|
||||||
HTTP_NOT_FOUND = 404,
|
|
||||||
HTTP_FORBIDDEN = 403,
|
|
||||||
HTTP_REQUEST_TIMEOUT = 408,
|
|
||||||
HTTP_NOT_IMPLEMENTED = 501, /* used for unrecognized requests */
|
|
||||||
HTTP_INTERNAL_SERVER_ERROR = 500,
|
|
||||||
#if 0 /* future use */
|
|
||||||
HTTP_CONTINUE = 100,
|
|
||||||
HTTP_SWITCHING_PROTOCOLS = 101,
|
|
||||||
HTTP_CREATED = 201,
|
|
||||||
HTTP_ACCEPTED = 202,
|
|
||||||
HTTP_NON_AUTHORITATIVE_INFO = 203,
|
|
||||||
HTTP_NO_CONTENT = 204,
|
|
||||||
HTTP_MULTIPLE_CHOICES = 300,
|
|
||||||
HTTP_MOVED_PERMANENTLY = 301,
|
|
||||||
HTTP_NOT_MODIFIED = 304,
|
|
||||||
HTTP_PAYMENT_REQUIRED = 402,
|
|
||||||
HTTP_BAD_GATEWAY = 502,
|
|
||||||
HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */
|
|
||||||
HTTP_RESPONSE_SETSIZE = 0xffffffff
|
|
||||||
#endif
|
|
||||||
} HttpResponseNum;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
HttpResponseNum type;
|
|
||||||
const char *name;
|
|
||||||
const char *info;
|
|
||||||
} HttpEnumString;
|
|
||||||
|
|
||||||
static const HttpEnumString httpResponseNames[] = {
|
|
||||||
{ HTTP_OK, "OK", NULL },
|
|
||||||
{ HTTP_MOVED_TEMPORARILY, "Found", "Directories must end with a slash." },
|
|
||||||
{ HTTP_REQUEST_TIMEOUT, "Request Timeout",
|
|
||||||
"No request appeared within a reasonable time period." },
|
|
||||||
{ HTTP_NOT_IMPLEMENTED, "Not Implemented",
|
|
||||||
"The requested method is not recognized by this server." },
|
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
|
||||||
{ HTTP_UNAUTHORIZED, "Unauthorized", "" },
|
|
||||||
#endif
|
|
||||||
{ HTTP_NOT_FOUND, "Not Found",
|
|
||||||
"The requested URL was not found on this server." },
|
|
||||||
{ HTTP_BAD_REQUEST, "Bad Request", "Unsupported method." },
|
|
||||||
{ HTTP_FORBIDDEN, "Forbidden", "" },
|
|
||||||
{ HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
|
|
||||||
"Internal Server Error" },
|
|
||||||
#if 0 /* not implemented */
|
|
||||||
{ HTTP_CREATED, "Created" },
|
|
||||||
{ HTTP_ACCEPTED, "Accepted" },
|
|
||||||
{ HTTP_NO_CONTENT, "No Content" },
|
|
||||||
{ HTTP_MULTIPLE_CHOICES, "Multiple Choices" },
|
|
||||||
{ HTTP_MOVED_PERMANENTLY, "Moved Permanently" },
|
|
||||||
{ HTTP_NOT_MODIFIED, "Not Modified" },
|
|
||||||
{ HTTP_BAD_GATEWAY, "Bad Gateway", "" },
|
|
||||||
{ HTTP_SERVICE_UNAVAILABLE, "Service Unavailable", "" },
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
|
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
static void send_file_and_exit(const char *url, int headers) ATTRIBUTE_NORETURN;
|
||||||
|
|
||||||
static void free_llist(has_next_ptr **pptr)
|
static void free_llist(has_next_ptr **pptr)
|
||||||
{
|
{
|
||||||
has_next_ptr *cur = *pptr;
|
has_next_ptr *cur = *pptr;
|
||||||
@ -382,11 +412,13 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp)
|
|||||||
* .ext:mime/type # new mime type not compiled into httpd
|
* .ext:mime/type # new mime type not compiled into httpd
|
||||||
* [adAD]:from # ip address allow/deny, * for wildcard
|
* [adAD]:from # ip address allow/deny, * for wildcard
|
||||||
* /path:user:pass # username/password
|
* /path:user:pass # username/password
|
||||||
|
* Ennn:error.html # error page for status nnn
|
||||||
*
|
*
|
||||||
* Any previous IP rules are discarded.
|
* Any previous IP rules are discarded.
|
||||||
* If the flag argument is not SUBDIR_PARSE then all /path and mime rules
|
* If the flag argument is not SUBDIR_PARSE then all /path and mime rules
|
||||||
* are also discarded. That is, previous settings are retained if flag is
|
* are also discarded. That is, previous settings are retained if flag is
|
||||||
* SUBDIR_PARSE.
|
* SUBDIR_PARSE.
|
||||||
|
* Error pages are only parsed on the main config file.
|
||||||
*
|
*
|
||||||
* path Path where to look for httpd.conf (without filename).
|
* path Path where to look for httpd.conf (without filename).
|
||||||
* flag Type of the parse request.
|
* flag Type of the parse request.
|
||||||
@ -486,18 +518,6 @@ static void parse_conf(const char *path, int flag)
|
|||||||
|
|
||||||
if (*p0 == 'a')
|
if (*p0 == 'a')
|
||||||
*p0 = 'A';
|
*p0 = 'A';
|
||||||
else if (*p0 != 'D' && *p0 != 'A'
|
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
|
||||||
&& *p0 != '/'
|
|
||||||
#endif
|
|
||||||
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
|
|
||||||
&& *p0 != '.'
|
|
||||||
#endif
|
|
||||||
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
|
|
||||||
&& *p0 != '*'
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
continue;
|
|
||||||
if (*p0 == 'A' || *p0 == 'D') {
|
if (*p0 == 'A' || *p0 == 'D') {
|
||||||
/* storing current config IP line */
|
/* storing current config IP line */
|
||||||
pip = xzalloc(sizeof(Htaccess_IP));
|
pip = xzalloc(sizeof(Htaccess_IP));
|
||||||
@ -527,6 +547,30 @@ static void parse_conf(const char *path, int flag)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
|
if (flag == FIRST_PARSE && *p0 == 'E') {
|
||||||
|
int i;
|
||||||
|
/* error status code */
|
||||||
|
int status = atoi(++p0);
|
||||||
|
/* c already points at the character following ':' in parse loop */
|
||||||
|
// c = strchr(p0, ':'); c++;
|
||||||
|
if (status < HTTP_CONTINUE) {
|
||||||
|
bb_error_msg("config error '%s' in '%s'", buf, cf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* then error page; find matching status */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
|
||||||
|
if (http_response_type[i] == status) {
|
||||||
|
http_error_page[i] = concat_path_file((*c == '/') ? NULL : home_httpd, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
if (*p0 == '/') {
|
if (*p0 == '/') {
|
||||||
/* make full path from httpd root / current_path / config_line_path */
|
/* make full path from httpd root / current_path / config_line_path */
|
||||||
@ -813,24 +857,29 @@ static void log_and_exit(void)
|
|||||||
* IE will puke big-time if the headers are not sent in one packet and the
|
* IE will puke big-time if the headers are not sent in one packet and the
|
||||||
* second packet is delayed for any reason.
|
* second packet is delayed for any reason.
|
||||||
* responseNum - the result code to send.
|
* responseNum - the result code to send.
|
||||||
* Return result of write().
|
|
||||||
*/
|
*/
|
||||||
static void send_headers(HttpResponseNum responseNum)
|
static void send_headers(int responseNum)
|
||||||
{
|
{
|
||||||
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
|
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
|
||||||
|
|
||||||
const char *responseString = "";
|
const char *responseString = "";
|
||||||
const char *infoString = NULL;
|
const char *infoString = NULL;
|
||||||
const char *mime_type;
|
const char *mime_type;
|
||||||
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
|
const char *error_page = 0;
|
||||||
|
#endif
|
||||||
unsigned i;
|
unsigned i;
|
||||||
time_t timer = time(0);
|
time_t timer = time(0);
|
||||||
char tmp_str[80];
|
char tmp_str[80];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(httpResponseNames); i++) {
|
for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
|
||||||
if (httpResponseNames[i].type == responseNum) {
|
if (http_response_type[i] == responseNum) {
|
||||||
responseString = httpResponseNames[i].name;
|
responseString = http_response[i].name;
|
||||||
infoString = httpResponseNames[i].info;
|
infoString = http_response[i].info;
|
||||||
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
|
error_page = http_error_page[i];
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -862,6 +911,20 @@ static void send_headers(HttpResponseNum responseNum)
|
|||||||
(g_query ? g_query : ""));
|
(g_query ? g_query : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
|
if (error_page && !access(error_page, R_OK)) {
|
||||||
|
strcat(iobuf, "\r\n");
|
||||||
|
len += 2;
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
fprintf(stderr, "headers: '%s'\n", iobuf);
|
||||||
|
full_write(1, iobuf, len);
|
||||||
|
if (DEBUG)
|
||||||
|
fprintf(stderr, "writing error page: '%s'\n", error_page);
|
||||||
|
return send_file_and_exit(error_page, FALSE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ContentLength != -1) { /* file */
|
if (ContentLength != -1) { /* file */
|
||||||
strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod));
|
strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod));
|
||||||
len += sprintf(iobuf + len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
|
len += sprintf(iobuf + len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
|
||||||
@ -885,8 +948,8 @@ static void send_headers(HttpResponseNum responseNum)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_headers_and_exit(HttpResponseNum responseNum) ATTRIBUTE_NORETURN;
|
static void send_headers_and_exit(int responseNum) ATTRIBUTE_NORETURN;
|
||||||
static void send_headers_and_exit(HttpResponseNum responseNum)
|
static void send_headers_and_exit(int responseNum)
|
||||||
{
|
{
|
||||||
send_headers(responseNum);
|
send_headers(responseNum);
|
||||||
log_and_exit();
|
log_and_exit();
|
||||||
@ -1279,9 +1342,12 @@ static void send_cgi_and_exit(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a file response to a HTTP request, and exit
|
* Send a file response to a HTTP request, and exit
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* const char *url The requested URL (with leading /).
|
||||||
|
* headers Don't send headers before if FALSE.
|
||||||
*/
|
*/
|
||||||
static void send_file_and_exit(const char *url) ATTRIBUTE_NORETURN;
|
static void send_file_and_exit(const char *url, int headers)
|
||||||
static void send_file_and_exit(const char *url)
|
|
||||||
{
|
{
|
||||||
static const char *const suffixTable[] = {
|
static const char *const suffixTable[] = {
|
||||||
/* Warning: shorter equivalent suffix in one line must be first */
|
/* Warning: shorter equivalent suffix in one line must be first */
|
||||||
@ -1350,9 +1416,11 @@ static void send_file_and_exit(const char *url)
|
|||||||
if (f < 0) {
|
if (f < 0) {
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
bb_perror_msg("cannot open '%s'", url);
|
bb_perror_msg("cannot open '%s'", url);
|
||||||
|
if (headers)
|
||||||
send_headers_and_exit(HTTP_NOT_FOUND);
|
send_headers_and_exit(HTTP_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers)
|
||||||
send_headers(HTTP_OK);
|
send_headers(HTTP_OK);
|
||||||
|
|
||||||
/* If you want to know about EPIPE below
|
/* If you want to know about EPIPE below
|
||||||
@ -1789,7 +1857,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
send_file_and_exit(tptr);
|
send_file_and_exit(tptr, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user