summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-04-14 04:03:59 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2017-04-15 03:42:28 -0400
commit0cc7556aec6ae6da4270e82a72d0bfce52ff1d8c (patch)
tree9f10434103121230441d24121925b3dcd987878b
parent8e97c84c0f491247ea200d93367aa1d81e6105c1 (diff)
downloadlighttpd1.4-0cc7556aec6ae6da4270e82a72d0bfce52ff1d8c.tar.gz
lighttpd1.4-0cc7556aec6ae6da4270e82a72d0bfce52ff1d8c.zip
[core] perf: stat_cache_mimetype_by_ext()
shared code to get mimetype string via longest extension match (attempts to match file basename, then longest ext, then "") Note: this is a behavior change from simple suffix match if there are 16 or more entries in mimetypes.assign
-rw-r--r--src/mod_dirlisting.c20
-rw-r--r--src/mod_webdav.c20
-rw-r--r--src/stat_cache.c56
-rw-r--r--src/stat_cache.h1
4 files changed, 48 insertions, 49 deletions
diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c
index dd93aaed..3dacf16d 100644
--- a/src/mod_dirlisting.c
+++ b/src/mod_dirlisting.c
@@ -875,7 +875,6 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf
dirls_entry_t *tmp;
char sizebuf[sizeof("999.9K")];
char datebuf[sizeof("2005-Jan-01 22:23:24")];
- size_t k;
const char *content_type;
long name_max;
#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR)
@@ -1067,23 +1066,8 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf
#endif
if (content_type == NULL) {
- content_type = "application/octet-stream";
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
- size_t ct_len;
-
- if (buffer_is_empty(ds->key))
- continue;
-
- ct_len = buffer_string_length(ds->key);
- if (tmp->namelen < ct_len)
- continue;
-
- if (0 == strncasecmp(DIRLIST_ENT_NAME(tmp) + tmp->namelen - ct_len, ds->key->ptr, ct_len)) {
- content_type = ds->value->ptr;
- break;
- }
- }
+ const buffer *type = stat_cache_mimetype_by_ext(con, DIRLIST_ENT_NAME(tmp), tmp->namelen);
+ content_type = NULL != type ? type->ptr : "application/octet-stream";
}
#ifdef HAVE_LOCALTIME_R
diff --git a/src/mod_webdav.c b/src/mod_webdav.c
index e298d826..d575ade8 100644
--- a/src/mod_webdav.c
+++ b/src/mod_webdav.c
@@ -932,7 +932,6 @@ static int webdav_get_live_property(server *srv, connection *con, handler_ctx *h
if (HANDLER_ERROR != (stat_cache_get_entry(srv, con, dst->path, &sce))) {
char ctime_buf[] = "2005-08-18T07:27:16Z";
char mtime_buf[] = "Thu, 18 Aug 2005 07:27:16 GMT";
- size_t k;
if (0 == strcmp(prop_name, "resourcetype")) {
if (S_ISDIR(sce->st.st_mode)) {
@@ -946,19 +945,12 @@ static int webdav_get_live_property(server *srv, connection *con, handler_ctx *h
buffer_append_string_len(b, CONST_STR_LEN("<D:getcontenttype>httpd/unix-directory</D:getcontenttype>"));
found = 1;
} else if(S_ISREG(sce->st.st_mode)) {
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
-
- if (buffer_is_empty(ds->key)) continue;
-
- if (buffer_is_equal_right_len(dst->path, ds->key, buffer_string_length(ds->key))) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:getcontenttype>"));
- buffer_append_string_buffer(b, ds->value);
- buffer_append_string_len(b, CONST_STR_LEN("</D:getcontenttype>"));
- found = 1;
-
- break;
- }
+ const buffer *type = stat_cache_mimetype_by_ext(con, CONST_BUF_LEN(dst->path));
+ if (NULL != type) {
+ buffer_append_string_len(b, CONST_STR_LEN("<D:getcontenttype>"));
+ buffer_append_string_buffer(b, type);
+ buffer_append_string_len(b, CONST_STR_LEN("</D:getcontenttype>"));
+ found = 1;
}
}
} else if (0 == strcmp(prop_name, "creationdate")) {
diff --git a/src/stat_cache.c b/src/stat_cache.c
index c08d2dd7..7215fdf9 100644
--- a/src/stat_cache.c
+++ b/src/stat_cache.c
@@ -268,6 +268,42 @@ static int stat_cache_attr_get(buffer *buf, char *name, char *xattrname) {
}
#endif
+const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *name, size_t nlen)
+{
+ const char *end = name + nlen; /*(end of string)*/
+ const size_t used = con->conf.mimetypes->used;
+ if (used < 16) {
+ for (size_t i = 0; i < used; ++i) {
+ /* suffix match */
+ const data_string *ds = (data_string *)con->conf.mimetypes->data[i];
+ const size_t klen = buffer_string_length(ds->key);
+ if (klen <= nlen && 0 == strncasecmp(end-klen, ds->key->ptr, klen))
+ return ds->value;
+ }
+ }
+ else {
+ const char *s;
+ const data_string *ds;
+ if (nlen) {
+ for (s = end-1; s != name && *s != '/'; --s) ; /*(like memrchr())*/
+ if (*s == '/') ++s;
+ }
+ else {
+ s = name;
+ }
+ /* search for basename, then longest .ext2.ext1, then .ext1, then "" */
+ ds = (data_string *)array_get_element(con->conf.mimetypes, s);
+ if (NULL != ds) return ds->value;
+ while (++s < end) {
+ while (*s != '.' && ++s != end) ;
+ ds = (data_string *)array_get_element(con->conf.mimetypes, s);
+ if (NULL != ds) return ds->value;
+ }
+ }
+
+ return NULL;
+}
+
/* the famous DJB hash function for strings */
static uint32_t hashme(buffer *str) {
uint32_t hash = 5381;
@@ -400,7 +436,6 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
stat_cache_entry *sce = NULL;
stat_cache *sc;
struct stat st;
- size_t k;
int fd;
struct stat lst;
#ifdef DEBUG_STAT_CACHE
@@ -635,22 +670,9 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
#endif
/* xattr did not set a content-type. ask the config */
if (buffer_string_is_empty(sce->content_type)) {
- size_t namelen = buffer_string_length(name);
-
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
- buffer *type = ds->key;
- size_t typelen = buffer_string_length(type);
-
- if (buffer_is_empty(type)) continue;
-
- /* check if the right side is the same */
- if (typelen > namelen) continue;
-
- if (0 == strncasecmp(name->ptr + namelen - typelen, type->ptr, typelen)) {
- buffer_copy_buffer(sce->content_type, ds->value);
- break;
- }
+ const buffer *type = stat_cache_mimetype_by_ext(con, CONST_BUF_LEN(name));
+ if (NULL != type) {
+ buffer_copy_buffer(sce->content_type, type);
}
}
etag_create(sce->etag, &(sce->st), con->etag_flags);
diff --git a/src/stat_cache.h b/src/stat_cache.h
index 8610fa9b..72298630 100644
--- a/src/stat_cache.h
+++ b/src/stat_cache.h
@@ -9,6 +9,7 @@ struct stat_cache; /* declaration */
struct stat_cache *stat_cache_init(server *srv);
void stat_cache_free(struct stat_cache *fc);
+const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *name, size_t nlen);
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **fce);
int stat_cache_open_rdonly_fstat (server *srv, connection *con, buffer *name, struct stat *st);