mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Backport the CSS security fixes to Apache 2.0a. Or is that forward
port? My sense of direction is all confused. PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84751 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -245,6 +245,15 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
unsigned d_is_fnmatch : 1;
|
unsigned d_is_fnmatch : 1;
|
||||||
|
|
||||||
|
/* should we force a charset on any outgoing parameterless content-type?
|
||||||
|
* if so, which charset?
|
||||||
|
*/
|
||||||
|
#define ADD_DEFAULT_CHARSET_OFF (0)
|
||||||
|
#define ADD_DEFAULT_CHARSET_ON (1)
|
||||||
|
#define ADD_DEFAULT_CHARSET_UNSET (2)
|
||||||
|
unsigned add_default_charset : 2;
|
||||||
|
char *add_default_charset_name;
|
||||||
|
|
||||||
unsigned long limit_req_body; /* limit on bytes in request msg body */
|
unsigned long limit_req_body; /* limit on bytes in request msg body */
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
|
@@ -943,6 +943,9 @@ static int handle_echo(ap_file_t *in, request_rec *r, const char *error)
|
|||||||
{
|
{
|
||||||
char tag[MAX_STRING_LEN];
|
char tag[MAX_STRING_LEN];
|
||||||
char *tag_val;
|
char *tag_val;
|
||||||
|
enum {E_NONE, E_URL, E_ENTITY} encode;
|
||||||
|
|
||||||
|
encode = E_ENTITY;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
|
if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) {
|
||||||
@@ -952,8 +955,16 @@ static int handle_echo(ap_file_t *in, request_rec *r, const char *error)
|
|||||||
const char *val = ap_table_get(r->subprocess_env, tag_val);
|
const char *val = ap_table_get(r->subprocess_env, tag_val);
|
||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
|
if (encode == E_NONE) {
|
||||||
ap_rputs(val, r);
|
ap_rputs(val, r);
|
||||||
}
|
}
|
||||||
|
else if (encode == E_URL) {
|
||||||
|
ap_rputs(ap_escape_uri(r->pool, val), r);
|
||||||
|
}
|
||||||
|
else if (encode == E_ENTITY) {
|
||||||
|
ap_rputs(ap_escape_html(r->pool, val), r);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
ap_rputs("(none)", r);
|
ap_rputs("(none)", r);
|
||||||
}
|
}
|
||||||
@@ -961,6 +972,19 @@ static int handle_echo(ap_file_t *in, request_rec *r, const char *error)
|
|||||||
else if (!strcmp(tag, "done")) {
|
else if (!strcmp(tag, "done")) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(tag, "encoding")) {
|
||||||
|
if (!strcasecmp(tag_val, "none")) encode = E_NONE;
|
||||||
|
else if (!strcasecmp(tag_val, "url")) encode = E_URL;
|
||||||
|
else if (!strcasecmp(tag_val, "entity")) encode = E_ENTITY;
|
||||||
|
else {
|
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
|
||||||
|
"unknown value \"%s\" to parameter \"encoding\" of "
|
||||||
|
"tag echo in %s",
|
||||||
|
tag_val, r->filename);
|
||||||
|
ap_rputs(error, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
|
||||||
"unknown parameter \"%s\" to tag echo in %s",
|
"unknown parameter \"%s\" to tag echo in %s",
|
||||||
@@ -2138,7 +2162,8 @@ static int handle_printenv(ap_file_t *in, request_rec *r, const char *error)
|
|||||||
}
|
}
|
||||||
else if (!strcmp(tag, "done")) {
|
else if (!strcmp(tag, "done")) {
|
||||||
for (i = 0; i < arr->nelts; ++i) {
|
for (i = 0; i < arr->nelts; ++i) {
|
||||||
ap_rvputs(r, elts[i].key, "=", elts[i].val, "\n", NULL);
|
ap_rvputs(r, ap_escape_html(r->pool, elts[i].key), "=",
|
||||||
|
ap_escape_html(r->pool, elts[i].val), "\n", NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -690,7 +690,7 @@ struct ent {
|
|||||||
|
|
||||||
static char *find_item(request_rec *r, ap_array_header_t *list, int path_only)
|
static char *find_item(request_rec *r, ap_array_header_t *list, int path_only)
|
||||||
{
|
{
|
||||||
const char *content_type = r->content_type;
|
const char *content_type = ap_field_noparam(r->pool, r->content_type);
|
||||||
const char *content_encoding = r->content_encoding;
|
const char *content_encoding = r->content_encoding;
|
||||||
char *path = r->filename;
|
char *path = r->filename;
|
||||||
|
|
||||||
|
@@ -146,6 +146,9 @@ static void *create_core_dir_config(ap_context_t *a, char *dir)
|
|||||||
|
|
||||||
conf->server_signature = srv_sig_unset;
|
conf->server_signature = srv_sig_unset;
|
||||||
|
|
||||||
|
conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
|
||||||
|
conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
|
||||||
|
|
||||||
return (void *)conf;
|
return (void *)conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,6 +260,14 @@ static void *merge_core_dir_configs(ap_context_t *a, void *basev, void *newv)
|
|||||||
conf->server_signature = new->server_signature;
|
conf->server_signature = new->server_signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new->add_default_charset != ADD_DEFAULT_CHARSET_UNSET) {
|
||||||
|
conf->add_default_charset = new->add_default_charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new->add_default_charset_name) {
|
||||||
|
conf->add_default_charset_name = new->add_default_charset_name;
|
||||||
|
}
|
||||||
|
|
||||||
return (void*)conf;
|
return (void*)conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1000,6 +1011,27 @@ static const char *set_gprof_dir(cmd_parms *cmd, void *dummy, char *arg)
|
|||||||
}
|
}
|
||||||
#endif /*GPROF*/
|
#endif /*GPROF*/
|
||||||
|
|
||||||
|
static const char *set_add_default_charset(cmd_parms *cmd,
|
||||||
|
core_dir_config *d, char *arg)
|
||||||
|
{
|
||||||
|
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
|
||||||
|
if (err != NULL) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (!strcasecmp(arg, "Off")) {
|
||||||
|
d->add_default_charset = ADD_DEFAULT_CHARSET_OFF;
|
||||||
|
}
|
||||||
|
else if (!strcasecmp(arg, "On")) {
|
||||||
|
d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
|
||||||
|
d->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d->add_default_charset = ADD_DEFAULT_CHARSET_ON;
|
||||||
|
d->add_default_charset_name = arg;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg)
|
static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg)
|
||||||
{
|
{
|
||||||
void *sconf = cmd->server->module_config;
|
void *sconf = cmd->server->module_config;
|
||||||
@@ -2294,6 +2326,8 @@ static const command_rec core_cmds[] = {
|
|||||||
{ "GprofDir", set_gprof_dir, NULL, RSRC_CONF, TAKE1,
|
{ "GprofDir", set_gprof_dir, NULL, RSRC_CONF, TAKE1,
|
||||||
"Directory to plop gmon.out files" },
|
"Directory to plop gmon.out files" },
|
||||||
#endif
|
#endif
|
||||||
|
{ "AddDefaultCharset", set_add_default_charset, NULL, OR_FILEINFO,
|
||||||
|
TAKE1, "The name of the default charset to add to any Content-Type without one or 'Off' to disable" },
|
||||||
|
|
||||||
/* Old resource config file commands */
|
/* Old resource config file commands */
|
||||||
|
|
||||||
|
@@ -90,6 +90,43 @@ HOOK_STRUCT(
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Builds the content-type that should be sent to the client from the
|
||||||
|
* content-type specified. The following rules are followed:
|
||||||
|
* - if type is NULL, type is set to ap_default_type(r)
|
||||||
|
* - if charset adding is disabled, stop processing and return type.
|
||||||
|
* - then, if there are no parameters on type, add the default charset
|
||||||
|
* - return type
|
||||||
|
*/
|
||||||
|
static const char *make_content_type(request_rec *r, const char *type) {
|
||||||
|
char *needcset[] = {
|
||||||
|
"text/plain",
|
||||||
|
"text/html",
|
||||||
|
NULL };
|
||||||
|
char **pcset;
|
||||||
|
core_dir_config *conf = (core_dir_config *)ap_get_module_config(
|
||||||
|
r->per_dir_config, &core_module);
|
||||||
|
if (!type) type = ap_default_type(r);
|
||||||
|
if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) return type;
|
||||||
|
|
||||||
|
if (ap_strcasestr(type, "charset=") != NULL) {
|
||||||
|
/* already has parameter, do nothing */
|
||||||
|
/* XXX we don't check the validity */
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
/* see if it makes sense to add the charset. At present,
|
||||||
|
* we only add it if the Content-type is one of needcset[]
|
||||||
|
*/
|
||||||
|
for (pcset = needcset; *pcset ; pcset++)
|
||||||
|
if (ap_strcasestr(type, *pcset) != NULL) {
|
||||||
|
type = ap_pstrcat(r->pool, type, "; charset=",
|
||||||
|
conf->add_default_charset_name, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_byterange(char *range, long clength, long *start, long *end)
|
static int parse_byterange(char *range, long clength, long *start, long *end)
|
||||||
{
|
{
|
||||||
char *dash = strchr(range, '-');
|
char *dash = strchr(range, '-');
|
||||||
@@ -240,7 +277,7 @@ static int internal_byterange(int realreq, long *tlength, request_rec *r,
|
|||||||
length);
|
length);
|
||||||
|
|
||||||
if (r->byterange > 1) {
|
if (r->byterange > 1) {
|
||||||
const char *ct = r->content_type ? r->content_type : ap_default_type(r);
|
const char *ct = make_content_type(r, r->content_type);
|
||||||
char ts[MAX_STRING_LEN];
|
char ts[MAX_STRING_LEN];
|
||||||
|
|
||||||
ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
|
ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
|
||||||
@@ -897,7 +934,7 @@ static void get_mime_headers(request_rec *r)
|
|||||||
r->status = HTTP_BAD_REQUEST;
|
r->status = HTTP_BAD_REQUEST;
|
||||||
ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
|
ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
|
||||||
"Size of a request header field exceeds server limit.<P>\n"
|
"Size of a request header field exceeds server limit.<P>\n"
|
||||||
"<PRE>\n", field, "</PRE>\n", NULL));
|
"<PRE>\n", ap_escape_html(r->pool, field), "</PRE>\n", NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
copy = ap_palloc(r->pool, len + 1);
|
copy = ap_palloc(r->pool, len + 1);
|
||||||
@@ -907,7 +944,7 @@ static void get_mime_headers(request_rec *r)
|
|||||||
r->status = HTTP_BAD_REQUEST; /* or abort the bad request */
|
r->status = HTTP_BAD_REQUEST; /* or abort the bad request */
|
||||||
ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
|
ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
|
||||||
"Request header field is missing colon separator.<P>\n"
|
"Request header field is missing colon separator.<P>\n"
|
||||||
"<PRE>\n", copy, "</PRE>\n", NULL));
|
"<PRE>\n", ap_escape_html(r->pool, copy), "</PRE>\n", NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1604,10 +1641,8 @@ API_EXPORT(void) ap_send_http_header(request_rec *r)
|
|||||||
ap_table_setn(r->headers_out, "Content-Type",
|
ap_table_setn(r->headers_out, "Content-Type",
|
||||||
ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
|
ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
|
||||||
"byteranges; boundary=", r->boundary, NULL));
|
"byteranges; boundary=", r->boundary, NULL));
|
||||||
else if (r->content_type)
|
else ap_table_setn(r->headers_out, "Content-Type", make_content_type(r,
|
||||||
ap_table_setn(r->headers_out, "Content-Type", r->content_type);
|
r->content_type));
|
||||||
else
|
|
||||||
ap_table_setn(r->headers_out, "Content-Type", ap_default_type(r));
|
|
||||||
|
|
||||||
if (r->content_encoding)
|
if (r->content_encoding)
|
||||||
ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
|
ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
|
||||||
@@ -2493,7 +2528,7 @@ API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error)
|
|||||||
r->content_languages = NULL;
|
r->content_languages = NULL;
|
||||||
r->content_encoding = NULL;
|
r->content_encoding = NULL;
|
||||||
r->clength = 0;
|
r->clength = 0;
|
||||||
r->content_type = "text/html";
|
r->content_type = "text/html; charset=iso-8859-1";
|
||||||
|
|
||||||
if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
|
if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
|
||||||
ap_table_setn(r->headers_out, "Allow", make_allow(r));
|
ap_table_setn(r->headers_out, "Allow", make_allow(r));
|
||||||
|
@@ -364,7 +364,7 @@ static const char *log_header_out(request_rec *r, char *a)
|
|||||||
{
|
{
|
||||||
const char *cp = ap_table_get(r->headers_out, a);
|
const char *cp = ap_table_get(r->headers_out, a);
|
||||||
if (!strcasecmp(a, "Content-type") && r->content_type) {
|
if (!strcasecmp(a, "Content-type") && r->content_type) {
|
||||||
cp = r->content_type;
|
cp = ap_field_noparam(r->pool, r->content_type);
|
||||||
}
|
}
|
||||||
if (cp) {
|
if (cp) {
|
||||||
return cp;
|
return cp;
|
||||||
|
@@ -159,7 +159,8 @@ static int action_handler(request_rec *r)
|
|||||||
{
|
{
|
||||||
action_dir_config *conf = (action_dir_config *)
|
action_dir_config *conf = (action_dir_config *)
|
||||||
ap_get_module_config(r->per_dir_config, &action_module);
|
ap_get_module_config(r->per_dir_config, &action_module);
|
||||||
const char *t, *action = r->handler ? r->handler : r->content_type;
|
const char *t, *action = r->handler ? r->handler :
|
||||||
|
ap_field_noparam(r->pool, r->content_type);
|
||||||
const char *script;
|
const char *script;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@@ -467,7 +467,7 @@ static int check_speling(request_rec *r)
|
|||||||
|
|
||||||
*(const char **)ap_push_array(t) =
|
*(const char **)ap_push_array(t) =
|
||||||
"The document name you requested (<code>";
|
"The document name you requested (<code>";
|
||||||
*(const char **)ap_push_array(t) = r->uri;
|
*(const char **)ap_push_array(t) = ap_escape_html(sub_pool, r->uri);
|
||||||
*(const char **)ap_push_array(t) =
|
*(const char **)ap_push_array(t) =
|
||||||
"</code>) could not be found on this server.\n"
|
"</code>) could not be found on this server.\n"
|
||||||
"However, we found documents with names similar "
|
"However, we found documents with names similar "
|
||||||
@@ -486,15 +486,15 @@ static int check_speling(request_rec *r)
|
|||||||
? r->parsed_uri.query : "",
|
? r->parsed_uri.query : "",
|
||||||
NULL);
|
NULL);
|
||||||
*(const char **)ap_push_array(v) = "\"";
|
*(const char **)ap_push_array(v) = "\"";
|
||||||
*(const char **)ap_push_array(v) = vuri;
|
*(const char **)ap_push_array(v) = ap_escape_uri(sub_pool, vuri);
|
||||||
*(const char **)ap_push_array(v) = "\";\"";
|
*(const char **)ap_push_array(v) = "\";\"";
|
||||||
*(const char **)ap_push_array(v) = reason;
|
*(const char **)ap_push_array(v) = reason;
|
||||||
*(const char **)ap_push_array(v) = "\"";
|
*(const char **)ap_push_array(v) = "\"";
|
||||||
|
|
||||||
*(const char **)ap_push_array(t) = "<li><a href=\"";
|
*(const char **)ap_push_array(t) = "<li><a href=\"";
|
||||||
*(const char **)ap_push_array(t) = vuri;
|
*(const char **)ap_push_array(t) = ap_escape_uri(sub_pool, vuri);
|
||||||
*(const char **)ap_push_array(t) = "\">";
|
*(const char **)ap_push_array(t) = "\">";
|
||||||
*(const char **)ap_push_array(t) = vuri;
|
*(const char **)ap_push_array(t) = ap_escape_html(sub_pool, vuri);
|
||||||
*(const char **)ap_push_array(t) = "</a> (";
|
*(const char **)ap_push_array(t) = "</a> (";
|
||||||
*(const char **)ap_push_array(t) = reason;
|
*(const char **)ap_push_array(t) = reason;
|
||||||
*(const char **)ap_push_array(t) = ")\n";
|
*(const char **)ap_push_array(t) = ")\n";
|
||||||
@@ -521,7 +521,7 @@ static int check_speling(request_rec *r)
|
|||||||
*(const char **)ap_push_array(t) =
|
*(const char **)ap_push_array(t) =
|
||||||
"Please consider informing the owner of the "
|
"Please consider informing the owner of the "
|
||||||
"<a href=\"";
|
"<a href=\"";
|
||||||
*(const char **)ap_push_array(t) = ref;
|
*(const char **)ap_push_array(t) = ap_escape_uri(sub_pool, ref);
|
||||||
*(const char **)ap_push_array(t) = "\">referring page</a> "
|
*(const char **)ap_push_array(t) = "\">referring page</a> "
|
||||||
"about the broken link.\n";
|
"about the broken link.\n";
|
||||||
}
|
}
|
||||||
|
@@ -441,7 +441,8 @@ static int add_expires(request_rec *r)
|
|||||||
if (r->content_type == NULL)
|
if (r->content_type == NULL)
|
||||||
code = NULL;
|
code = NULL;
|
||||||
else
|
else
|
||||||
code = (char *) ap_table_get(conf->expiresbytype, r->content_type);
|
code = (char *) ap_table_get(conf->expiresbytype,
|
||||||
|
ap_field_noparam(r->pool, r->content_type));
|
||||||
|
|
||||||
if (code == NULL) {
|
if (code == NULL) {
|
||||||
/* no expires defined for that type, is there a default? */
|
/* no expires defined for that type, is there a default? */
|
||||||
|
@@ -822,11 +822,15 @@ int ap_proxyerror(request_rec *r, int statuscode, const char *message)
|
|||||||
ap_table_setn(r->notes, "error-notes",
|
ap_table_setn(r->notes, "error-notes",
|
||||||
ap_pstrcat(r->pool,
|
ap_pstrcat(r->pool,
|
||||||
"The proxy server could not handle the request "
|
"The proxy server could not handle the request "
|
||||||
"<EM><A HREF=\"", r->uri, "\">",
|
"<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
|
||||||
r->method, " ", r->uri, "</A></EM>.<P>\n"
|
"\">", ap_escape_html(r->pool, r->method),
|
||||||
"Reason: <STRONG>", message, "</STRONG>", NULL));
|
" ",
|
||||||
|
ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
|
||||||
|
"Reason: <STRONG>",
|
||||||
|
ap_escape_html(r->pool, message),
|
||||||
|
"</STRONG>", NULL));
|
||||||
|
|
||||||
/* Allow the "error-notes" string to be printed by ap_send_error_response() */
|
/* Allow "error-notes" string to be printed by ap_send_error_response() */
|
||||||
ap_table_setn(r->notes, "verbose-error-to", ap_pstrdup(r->pool, "*"));
|
ap_table_setn(r->notes, "verbose-error-to", ap_pstrdup(r->pool, "*"));
|
||||||
|
|
||||||
r->status_line = ap_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
|
r->status_line = ap_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
|
||||||
|
@@ -469,7 +469,8 @@ API_EXPORT(void) ap_log_rerror(const char *file, int line, int level,
|
|||||||
if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
|
if (((level & APLOG_LEVELMASK) <= APLOG_WARNING)
|
||||||
&& (ap_table_get(r->notes, "error-notes") == NULL)) {
|
&& (ap_table_get(r->notes, "error-notes") == NULL)) {
|
||||||
ap_table_setn(r->notes, "error-notes",
|
ap_table_setn(r->notes, "error-notes",
|
||||||
ap_pvsprintf(r->pool, fmt, args));
|
ap_escape_html(r->pool, ap_pvsprintf(r->pool, fmt,
|
||||||
|
args)));
|
||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
@@ -104,6 +104,8 @@ API_EXPORT(char *) ap_field_noparam(ap_context_t *p, const char *intype)
|
|||||||
{
|
{
|
||||||
const char *semi;
|
const char *semi;
|
||||||
|
|
||||||
|
if (intype == NULL) return NULL;
|
||||||
|
|
||||||
semi = strchr(intype, ';');
|
semi = strchr(intype, ';');
|
||||||
if (semi == NULL) {
|
if (semi == NULL) {
|
||||||
return ap_pstrdup(p, intype);
|
return ap_pstrdup(p, intype);
|
||||||
@@ -275,6 +277,38 @@ API_EXPORT(void) ap_pregfree(ap_context_t *p, regex_t * reg)
|
|||||||
ap_unblock_alarms();
|
ap_unblock_alarms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to standard strstr() but we ignore case in this version.
|
||||||
|
* Based on the strstr() implementation further below.
|
||||||
|
*/
|
||||||
|
API_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
char *p1, *p2;
|
||||||
|
if (*s2 == '\0') {
|
||||||
|
/* an empty s2 */
|
||||||
|
return((char *)s1);
|
||||||
|
}
|
||||||
|
while(1) {
|
||||||
|
for ( ; (*s1 != '\0') && (ap_tolower(*s1) != ap_tolower(*s2)); s1++);
|
||||||
|
if (*s1 == '\0') return(NULL);
|
||||||
|
/* found first character of s2, see if the rest matches */
|
||||||
|
p1 = (char *)s1;
|
||||||
|
p2 = (char *)s2;
|
||||||
|
while (ap_tolower(*++p1) == ap_tolower(*++p2)) {
|
||||||
|
if (*p1 == '\0') {
|
||||||
|
/* both strings ended together */
|
||||||
|
return((char *)s1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*p2 == '\0') {
|
||||||
|
/* second string ended, a match */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* didn't find a match here, try starting at next character in s1 */
|
||||||
|
s1++;
|
||||||
|
}
|
||||||
|
return((char *)s1);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Apache stub function for the regex libraries regexec() to make sure the
|
* Apache stub function for the regex libraries regexec() to make sure the
|
||||||
* whole regex(3) API is available through the Apache (exported) namespace.
|
* whole regex(3) API is available through the Apache (exported) namespace.
|
||||||
|
Reference in New Issue
Block a user