Loading modules/http/mod_mime.c +352 −3 Changes for modules/http/mod_mime.c: 352 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -73,6 +73,20 @@ #include <string.h> #endif /* XXXX - fix me / EBCDIC * there was a cludge here which would use its * own version ap_isascii(). Indicating that * on some platforms that might be needed. * * #define OS_ASC(c) (c) -- for mere mortals * or * #define OS_ASC(c) (ebcdic2ascii[c]) -- for dino's * * #define ap_isascii(c) ((OS_ASC(c) & 0x80) == 0) */ /* XXXXX - fix me - See note with NOT_PROXY */ typedef struct handlers_info { char *name; } handlers_info; Loading @@ -82,13 +96,34 @@ typedef struct { ap_table_t *encoding_types; /* Added with AddEncoding... */ ap_table_t *language_types; /* Added with AddLanguage... */ ap_table_t *handlers; /* Added with AddHandler... */ ap_table_t *charset_types; /* Added with AddCharset... */ ap_array_header_t *handlers_remove; /* List of handlers to remove */ char *type; /* Type forced with ForceType */ char *handler; /* Handler forced with SetHandler */ char *default_language; /* Language if no AddLanguage ext found */ /* Due to the FUD about JS and charsets * default_charset is actually in src/main */ } mime_dir_config; typedef struct param_s { char *attr; char *val; struct param_s *next; } param; typedef struct { char *type; char *subtype; param *param; } content_type; static char tspecial[] = { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '\0' }; module MODULE_VAR_EXPORT mime_module; static void *create_mime_dir_config(ap_context_t *p, char *dummy) Loading @@ -98,6 +133,7 @@ static void *create_mime_dir_config(ap_context_t *p, char *dummy) new->forced_types = ap_make_table(p, 4); new->encoding_types = ap_make_table(p, 4); new->charset_types = ap_make_table(p, 4); new->language_types = ap_make_table(p, 4); new->handlers = ap_make_table(p, 4); new->handlers_remove = ap_make_array(p, 4, sizeof(handlers_info)); Loading Loading @@ -127,6 +163,8 @@ static void *merge_mime_dir_configs(ap_context_t *p, void *basev, void *addv) base->forced_types); new->encoding_types = ap_overlay_tables(p, add->encoding_types, base->encoding_types); new->charset_types = ap_overlay_tables(p, add->charset_types, base->charset_types); new->language_types = ap_overlay_tables(p, add->language_types, base->language_types); new->handlers = ap_overlay_tables(p, add->handlers, Loading @@ -145,6 +183,7 @@ static const char *add_type(cmd_parms *cmd, mime_dir_config * m, char *ct, { if (*ext == '.') ++ext; ap_str_tolower(ct); ap_table_setn(m->forced_types, ext, ct); return NULL; Loading @@ -160,11 +199,23 @@ static const char *add_encoding(cmd_parms *cmd, mime_dir_config * m, char *enc, return NULL; } static const char *add_charset(cmd_parms *cmd, mime_dir_config *m, char *charset, char *ext) { if (*ext == '.') { ++ext; } ap_str_tolower(charset); ap_table_setn(m->charset_types, ext, charset); return NULL; } static const char *add_language(cmd_parms *cmd, mime_dir_config *m, char *lang, char *ext) { if (*ext == '.') if (*ext == '.') { ++ext; } ap_str_tolower(lang); ap_table_setn(m->language_types, ext, lang); return NULL; Loading Loading @@ -214,6 +265,8 @@ static const command_rec mime_cmds[] = "a mime type followed by one or more file extensions"}, {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2, "an encoding (e.g., gzip), followed by one or more file extensions"}, {"AddCharset", add_charset, NULL, OR_FILEINFO, ITERATE2, "a charset (e.g., iso-2022-jp), followed by one or more file extensions"}, {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2, "a language (e.g., fr), followed by one or more file extensions"}, {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2, Loading Loading @@ -281,6 +334,251 @@ static void mime_post_config(ap_context_t *p, ap_context_t *plog, ap_context_t * ap_cfg_closefile(f); } static char *zap_sp(char *s) { char *tp; if (s == NULL) { return (NULL); } if (*s == '\0') { return (s); } /* delete prefixed white space */ for (; *s == ' ' || *s == '\t' || *s == '\n'; s++); /* delete postfixed white space */ for (tp = s; *tp != '\0'; tp++); for (tp--; tp != s && (*tp == ' ' || *tp == '\t' || *tp == '\n'); tp--) { *tp = '\0'; } return (s); } static int is_token(char c) { int res; res = (ap_isascii(c) && ap_isgraph(c) && (strchr(tspecial, c) == NULL)) ? 1 : -1; return res; } static int is_qtext(char c) { int res; res = (ap_isascii(c) && (c != '"') && (c != '\\') && (c != '\n')) ? 1 : -1; return res; } static int is_quoted_pair(char *s) { int res = -1; int c; if (((s + 1) != NULL) && (*s == '\\')) { c = (int) *(s + 1); if (ap_isascii(c)) { res = 1; } } return (res); } static content_type *analyze_ct(request_rec *r, char *s) { char *tp, *mp, *cp; char *attribute, *value; int quoted = 0; server_rec * ss = r->server; ap_context_t * p = r->pool; content_type *ctp; param *pp, *npp; /* initialize ctp */ ctp = (content_type *) ap_palloc(p, sizeof(content_type)); ctp->type = NULL; ctp->subtype = NULL; ctp->param = NULL; tp = ap_pstrdup(p, s); mp = tp; cp = mp; /* getting a type */ if (!(cp = strchr(mp, '/'))) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "mod_mime: analyze_ct: cannot get media type from '%s'", (const char *) mp); return (NULL); } ctp->type = ap_pstrndup(p, mp, cp - mp); ctp->type = zap_sp(ctp->type); if (ctp->type == NULL || *(ctp->type) == '\0' || strchr(ctp->type, ';') || strchr(ctp->type, ' ') || strchr(ctp->type, '\t')) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media subtype."); return (NULL); } /* getting a subtype */ cp++; mp = cp; for (; *cp != ';' && *cp != '\0'; cp++); ctp->subtype = ap_pstrndup(p, mp, cp - mp); ctp->subtype = zap_sp(ctp->subtype); if ((ctp->subtype == NULL) || (*(ctp->subtype) == '\0') || strchr(ctp->subtype, ' ') || strchr(ctp->subtype, '\t')) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media subtype."); return (NULL); } cp = zap_sp(cp); if (cp == NULL || *cp == '\0') { return (ctp); } /* getting parameters */ cp++; cp = zap_sp(cp); if (cp == NULL || *cp == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } mp = cp; attribute = NULL; value = NULL; while (cp != NULL && *cp != '\0') { if (attribute == NULL) { if (is_token((int) *cp) > 0) { cp++; continue; } else if (*cp == ' ' || *cp == '\t' || *cp == '\n') { cp++; continue; } else if (*cp == '=') { attribute = ap_pstrndup(p, mp, cp - mp); attribute = zap_sp(attribute); if (attribute == NULL || *attribute == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } cp++; cp = zap_sp(cp); if (cp == NULL || *cp == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } mp = cp; continue; } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } } else { if (mp == cp) { if (*cp == '"') { quoted = 1; cp++; } else { quoted = 0; } } if (quoted > 0) { while (quoted && *cp != '\0') { if (is_qtext((int) *cp) > 0) { cp++; } else if (is_quoted_pair(cp) > 0) { cp += 2; } else if (*cp == '"') { cp++; while (*cp == ' ' || *cp == '\t' || *cp == '\n') { cp++; } if (*cp != ';' && *cp != '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return(NULL); } quoted = 0; } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } } } else { while (1) { if (is_token((int) *cp) > 0) { cp++; } else if (*cp == '\0' || *cp == ';') { break; } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } } } value = ap_pstrndup(p, mp, cp - mp); value = zap_sp(value); if (value == NULL || *value == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } pp = ap_palloc(p, sizeof(param)); pp->attr = attribute; pp->val = value; pp->next = NULL; if (ctp->param == NULL) { ctp->param = pp; } else { npp = ctp->param; while (npp->next) { npp = npp->next; } npp->next = pp; } quoted = 0; attribute = NULL; value = NULL; if (*cp == '\0') { break; } cp++; mp = cp; } } return (ctp); } static int find_ct(request_rec *r) { const char *fn = strrchr(r->filename, '/'); Loading @@ -289,6 +587,7 @@ static int find_ct(request_rec *r) char *ext; const char *orighandler = r->handler; const char *type; const char *charset = NULL; if (r->finfo.filetype == APR_DIR) { r->content_type = DIR_MAGIC_TYPE; Loading @@ -300,8 +599,9 @@ static int find_ct(request_rec *r) * pointer to getword, causing a SEGV .. */ if (fn == NULL) if (fn == NULL) { fn = r->filename; } /* Parse filename extensions, which can be in any order */ while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) { Loading @@ -314,6 +614,12 @@ static int find_ct(request_rec *r) found = 1; } /* Add charset to Content-Type */ if ((type = ap_table_get(conf->charset_types, ext))) { charset = type; found = 1; } /* Check for Content-Language */ if ((type = ap_table_get(conf->language_types, ext))) { const char **new; Loading @@ -337,7 +643,12 @@ static int find_ct(request_rec *r) } /* Check for a special handler, but not for proxy request */ if ((type = ap_table_get(conf->handlers, ext)) && !r->proxyreq) { if ((type = ap_table_get(conf->handlers, ext)) #if 0 /* XXX fix me when the proxy code is updated */ && r->proxyreq == NOT_PROXY) #endif ) { r->handler = type; found = 1; } Loading @@ -353,8 +664,46 @@ static int find_ct(request_rec *r) r->content_languages = NULL; r->content_encoding = NULL; r->handler = orighandler; charset = NULL; } } if (r->content_type) { content_type *ctp; char *ct; int override = 0; ct = (char *) ap_palloc(r->pool, sizeof(char) * (strlen(r->content_type) + 1)); strcpy(ct, r->content_type); if ((ctp = analyze_ct(r, ct))) { param *pp = ctp->param; r->content_type = ap_pstrcat(r->pool, ctp->type, "/", ctp->subtype, NULL); while (pp != NULL) { if (charset && !strcmp(pp->attr, "charset")) { if (!override) { r->content_type = ap_pstrcat(r->pool, r->content_type, "; charset=", charset, NULL); override = 1; } } else { r->content_type = ap_pstrcat(r->pool, r->content_type, "; ", pp->attr, "=", pp->val, NULL); } pp = pp->next; } if (charset && !override) { r->content_type = ap_pstrcat(r->pool, r->content_type, "; charset=", charset, NULL); } } } /* Set default language, if none was specified by the extensions Loading Loading
modules/http/mod_mime.c +352 −3 Changes for modules/http/mod_mime.c: 352 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -73,6 +73,20 @@ #include <string.h> #endif /* XXXX - fix me / EBCDIC * there was a cludge here which would use its * own version ap_isascii(). Indicating that * on some platforms that might be needed. * * #define OS_ASC(c) (c) -- for mere mortals * or * #define OS_ASC(c) (ebcdic2ascii[c]) -- for dino's * * #define ap_isascii(c) ((OS_ASC(c) & 0x80) == 0) */ /* XXXXX - fix me - See note with NOT_PROXY */ typedef struct handlers_info { char *name; } handlers_info; Loading @@ -82,13 +96,34 @@ typedef struct { ap_table_t *encoding_types; /* Added with AddEncoding... */ ap_table_t *language_types; /* Added with AddLanguage... */ ap_table_t *handlers; /* Added with AddHandler... */ ap_table_t *charset_types; /* Added with AddCharset... */ ap_array_header_t *handlers_remove; /* List of handlers to remove */ char *type; /* Type forced with ForceType */ char *handler; /* Handler forced with SetHandler */ char *default_language; /* Language if no AddLanguage ext found */ /* Due to the FUD about JS and charsets * default_charset is actually in src/main */ } mime_dir_config; typedef struct param_s { char *attr; char *val; struct param_s *next; } param; typedef struct { char *type; char *subtype; param *param; } content_type; static char tspecial[] = { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '\0' }; module MODULE_VAR_EXPORT mime_module; static void *create_mime_dir_config(ap_context_t *p, char *dummy) Loading @@ -98,6 +133,7 @@ static void *create_mime_dir_config(ap_context_t *p, char *dummy) new->forced_types = ap_make_table(p, 4); new->encoding_types = ap_make_table(p, 4); new->charset_types = ap_make_table(p, 4); new->language_types = ap_make_table(p, 4); new->handlers = ap_make_table(p, 4); new->handlers_remove = ap_make_array(p, 4, sizeof(handlers_info)); Loading Loading @@ -127,6 +163,8 @@ static void *merge_mime_dir_configs(ap_context_t *p, void *basev, void *addv) base->forced_types); new->encoding_types = ap_overlay_tables(p, add->encoding_types, base->encoding_types); new->charset_types = ap_overlay_tables(p, add->charset_types, base->charset_types); new->language_types = ap_overlay_tables(p, add->language_types, base->language_types); new->handlers = ap_overlay_tables(p, add->handlers, Loading @@ -145,6 +183,7 @@ static const char *add_type(cmd_parms *cmd, mime_dir_config * m, char *ct, { if (*ext == '.') ++ext; ap_str_tolower(ct); ap_table_setn(m->forced_types, ext, ct); return NULL; Loading @@ -160,11 +199,23 @@ static const char *add_encoding(cmd_parms *cmd, mime_dir_config * m, char *enc, return NULL; } static const char *add_charset(cmd_parms *cmd, mime_dir_config *m, char *charset, char *ext) { if (*ext == '.') { ++ext; } ap_str_tolower(charset); ap_table_setn(m->charset_types, ext, charset); return NULL; } static const char *add_language(cmd_parms *cmd, mime_dir_config *m, char *lang, char *ext) { if (*ext == '.') if (*ext == '.') { ++ext; } ap_str_tolower(lang); ap_table_setn(m->language_types, ext, lang); return NULL; Loading Loading @@ -214,6 +265,8 @@ static const command_rec mime_cmds[] = "a mime type followed by one or more file extensions"}, {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2, "an encoding (e.g., gzip), followed by one or more file extensions"}, {"AddCharset", add_charset, NULL, OR_FILEINFO, ITERATE2, "a charset (e.g., iso-2022-jp), followed by one or more file extensions"}, {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2, "a language (e.g., fr), followed by one or more file extensions"}, {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2, Loading Loading @@ -281,6 +334,251 @@ static void mime_post_config(ap_context_t *p, ap_context_t *plog, ap_context_t * ap_cfg_closefile(f); } static char *zap_sp(char *s) { char *tp; if (s == NULL) { return (NULL); } if (*s == '\0') { return (s); } /* delete prefixed white space */ for (; *s == ' ' || *s == '\t' || *s == '\n'; s++); /* delete postfixed white space */ for (tp = s; *tp != '\0'; tp++); for (tp--; tp != s && (*tp == ' ' || *tp == '\t' || *tp == '\n'); tp--) { *tp = '\0'; } return (s); } static int is_token(char c) { int res; res = (ap_isascii(c) && ap_isgraph(c) && (strchr(tspecial, c) == NULL)) ? 1 : -1; return res; } static int is_qtext(char c) { int res; res = (ap_isascii(c) && (c != '"') && (c != '\\') && (c != '\n')) ? 1 : -1; return res; } static int is_quoted_pair(char *s) { int res = -1; int c; if (((s + 1) != NULL) && (*s == '\\')) { c = (int) *(s + 1); if (ap_isascii(c)) { res = 1; } } return (res); } static content_type *analyze_ct(request_rec *r, char *s) { char *tp, *mp, *cp; char *attribute, *value; int quoted = 0; server_rec * ss = r->server; ap_context_t * p = r->pool; content_type *ctp; param *pp, *npp; /* initialize ctp */ ctp = (content_type *) ap_palloc(p, sizeof(content_type)); ctp->type = NULL; ctp->subtype = NULL; ctp->param = NULL; tp = ap_pstrdup(p, s); mp = tp; cp = mp; /* getting a type */ if (!(cp = strchr(mp, '/'))) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "mod_mime: analyze_ct: cannot get media type from '%s'", (const char *) mp); return (NULL); } ctp->type = ap_pstrndup(p, mp, cp - mp); ctp->type = zap_sp(ctp->type); if (ctp->type == NULL || *(ctp->type) == '\0' || strchr(ctp->type, ';') || strchr(ctp->type, ' ') || strchr(ctp->type, '\t')) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media subtype."); return (NULL); } /* getting a subtype */ cp++; mp = cp; for (; *cp != ';' && *cp != '\0'; cp++); ctp->subtype = ap_pstrndup(p, mp, cp - mp); ctp->subtype = zap_sp(ctp->subtype); if ((ctp->subtype == NULL) || (*(ctp->subtype) == '\0') || strchr(ctp->subtype, ' ') || strchr(ctp->subtype, '\t')) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media subtype."); return (NULL); } cp = zap_sp(cp); if (cp == NULL || *cp == '\0') { return (ctp); } /* getting parameters */ cp++; cp = zap_sp(cp); if (cp == NULL || *cp == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } mp = cp; attribute = NULL; value = NULL; while (cp != NULL && *cp != '\0') { if (attribute == NULL) { if (is_token((int) *cp) > 0) { cp++; continue; } else if (*cp == ' ' || *cp == '\t' || *cp == '\n') { cp++; continue; } else if (*cp == '=') { attribute = ap_pstrndup(p, mp, cp - mp); attribute = zap_sp(attribute); if (attribute == NULL || *attribute == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } cp++; cp = zap_sp(cp); if (cp == NULL || *cp == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } mp = cp; continue; } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } } else { if (mp == cp) { if (*cp == '"') { quoted = 1; cp++; } else { quoted = 0; } } if (quoted > 0) { while (quoted && *cp != '\0') { if (is_qtext((int) *cp) > 0) { cp++; } else if (is_quoted_pair(cp) > 0) { cp += 2; } else if (*cp == '"') { cp++; while (*cp == ' ' || *cp == '\t' || *cp == '\n') { cp++; } if (*cp != ';' && *cp != '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return(NULL); } quoted = 0; } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } } } else { while (1) { if (is_token((int) *cp) > 0) { cp++; } else if (*cp == '\0' || *cp == ';') { break; } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } } } value = ap_pstrndup(p, mp, cp - mp); value = zap_sp(value); if (value == NULL || *value == '\0') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss, "Cannot get media parameter."); return (NULL); } pp = ap_palloc(p, sizeof(param)); pp->attr = attribute; pp->val = value; pp->next = NULL; if (ctp->param == NULL) { ctp->param = pp; } else { npp = ctp->param; while (npp->next) { npp = npp->next; } npp->next = pp; } quoted = 0; attribute = NULL; value = NULL; if (*cp == '\0') { break; } cp++; mp = cp; } } return (ctp); } static int find_ct(request_rec *r) { const char *fn = strrchr(r->filename, '/'); Loading @@ -289,6 +587,7 @@ static int find_ct(request_rec *r) char *ext; const char *orighandler = r->handler; const char *type; const char *charset = NULL; if (r->finfo.filetype == APR_DIR) { r->content_type = DIR_MAGIC_TYPE; Loading @@ -300,8 +599,9 @@ static int find_ct(request_rec *r) * pointer to getword, causing a SEGV .. */ if (fn == NULL) if (fn == NULL) { fn = r->filename; } /* Parse filename extensions, which can be in any order */ while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) { Loading @@ -314,6 +614,12 @@ static int find_ct(request_rec *r) found = 1; } /* Add charset to Content-Type */ if ((type = ap_table_get(conf->charset_types, ext))) { charset = type; found = 1; } /* Check for Content-Language */ if ((type = ap_table_get(conf->language_types, ext))) { const char **new; Loading @@ -337,7 +643,12 @@ static int find_ct(request_rec *r) } /* Check for a special handler, but not for proxy request */ if ((type = ap_table_get(conf->handlers, ext)) && !r->proxyreq) { if ((type = ap_table_get(conf->handlers, ext)) #if 0 /* XXX fix me when the proxy code is updated */ && r->proxyreq == NOT_PROXY) #endif ) { r->handler = type; found = 1; } Loading @@ -353,8 +664,46 @@ static int find_ct(request_rec *r) r->content_languages = NULL; r->content_encoding = NULL; r->handler = orighandler; charset = NULL; } } if (r->content_type) { content_type *ctp; char *ct; int override = 0; ct = (char *) ap_palloc(r->pool, sizeof(char) * (strlen(r->content_type) + 1)); strcpy(ct, r->content_type); if ((ctp = analyze_ct(r, ct))) { param *pp = ctp->param; r->content_type = ap_pstrcat(r->pool, ctp->type, "/", ctp->subtype, NULL); while (pp != NULL) { if (charset && !strcmp(pp->attr, "charset")) { if (!override) { r->content_type = ap_pstrcat(r->pool, r->content_type, "; charset=", charset, NULL); override = 1; } } else { r->content_type = ap_pstrcat(r->pool, r->content_type, "; ", pp->attr, "=", pp->val, NULL); } pp = pp->next; } if (charset && !override) { r->content_type = ap_pstrcat(r->pool, r->content_type, "; charset=", charset, NULL); } } } /* Set default language, if none was specified by the extensions Loading