diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2021-03-14 11:09:35 -0400 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2021-03-22 07:10:32 -0400 |
commit | fe4310cc61a44d51f451bfdad16b1db7f6769fd4 (patch) | |
tree | 0b4a5a0c441eafb6a1c4f2944d62bda06d1f1ac7 /src/mod_dirlisting.c | |
parent | 7b9c5adda1f8254119627973618c4157746abba9 (diff) | |
download | lighttpd-git-fe4310cc61a44d51f451bfdad16b1db7f6769fd4.tar.gz |
[mod_dirlisting, mod_trigger_b4_dl] use keyvalue
use keyvalue.[ch] for basic matching
consolidate PCRE logic and leverage PCRE study in keyvalue.[ch]
remove direct link to -lpcre from modules using keyvalue.[ch]
Diffstat (limited to 'src/mod_dirlisting.c')
-rw-r--r-- | src/mod_dirlisting.c | 99 |
1 files changed, 29 insertions, 70 deletions
diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c index 4a029d8c..df84c3ad 100644 --- a/src/mod_dirlisting.c +++ b/src/mod_dirlisting.c @@ -18,6 +18,7 @@ #include "buffer.h" #include "fdevent.h" #include "http_header.h" +#include "keyvalue.h" #include "plugin.h" @@ -44,10 +45,6 @@ #endif #endif -#ifdef HAVE_PCRE_H -#include <pcre.h> -#endif - /** * this is a dirlisting for a lighttpd plugin */ @@ -61,11 +58,7 @@ typedef struct { char encode_header; char auto_layout; - #ifdef HAVE_PCRE_H - pcre **excludes; - #else - void *excludes; - #endif + pcre_keyvalue_buffer *excludes; const buffer *show_readme; const buffer *show_header; @@ -83,53 +76,38 @@ typedef struct { buffer tmp_buf; } plugin_data; -#ifdef HAVE_PCRE_H - -static pcre ** mod_dirlisting_parse_excludes(server *srv, const array *a) { - pcre **regexes = calloc(a->used + 1, sizeof(pcre *)); - force_assert(regexes); +static pcre_keyvalue_buffer * mod_dirlisting_parse_excludes(server *srv, const array *a) { + const int pcre_jit = + !srv->srvconf.feature_flags + || config_plugin_value_tobool( + array_get_element_klen(srv->srvconf.feature_flags, + CONST_STR_LEN("server.pcre_jit")), 1); + pcre_keyvalue_buffer * const kvb = pcre_keyvalue_buffer_init(); + buffer empty = { NULL, 0, 0 }; for (uint32_t j = 0; j < a->used; ++j) { - const data_string *ds = (const data_string *)a->data[j]; - const char *errptr; - int erroff; - regexes[j] = pcre_compile(ds->value.ptr, 0, &errptr, &erroff, NULL); - if (NULL == regexes[j]) { + const data_string *ds = (data_string *)a->data[j]; + if (!pcre_keyvalue_buffer_append(srv->errh, kvb, &ds->value, &empty, + pcre_jit)) { log_error(srv->errh, __FILE__, __LINE__, - "pcre_compile failed for: %s", ds->value.ptr); - for (pcre **regex = regexes; *regex; ++regex) pcre_free(*regex); - free(regexes); + "pcre_compile failed for %s", ds->key.ptr); + pcre_keyvalue_buffer_free(kvb); return NULL; } } - return regexes; + return kvb; } -static int mod_dirlisting_exclude(log_error_st *errh, pcre **regex, const char *name, size_t len) { - for(; *regex; ++regex) { - #define N 10 - int ovec[N * 3]; - int n; - if ((n = pcre_exec(*regex, NULL, name, len, 0, 0, ovec, 3 * N)) < 0) { - if (n == PCRE_ERROR_NOMATCH) continue; - - log_error(errh, __FILE__, __LINE__, - "execution error while matching: %d", n); - /* aborting would require a lot of manual cleanup here. - * skip instead (to not leak names that break pcre matching) - */ - } - return 1; - #undef N - } - return 0; /* no match */ +static int mod_dirlisting_exclude(pcre_keyvalue_buffer * const kvb, const char * const name, const uint32_t len) { + /*(re-use keyvalue.[ch] for match-only; + * must have been configured with empty kvb 'value' during init)*/ + buffer input = { NULL, len+1, 0 }; + *(const char **)&input.ptr = name; + pcre_keyvalue_ctx ctx = { NULL, NULL, 0, -1 }; + /*(fail closed (simulate match to exclude) if there is an error)*/ + return HANDLER_ERROR == pcre_keyvalue_buffer_process(kvb,&ctx,&input,NULL) + || -1 != ctx.m; } -#else - -#define mod_dirlisting_exclude(a, b, c, d) 0 - -#endif - INIT_FUNC(mod_dirlisting_init) { return calloc(1, sizeof(plugin_data)); @@ -144,14 +122,10 @@ FREE_FUNC(mod_dirlisting_free) { config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0]; for (; -1 != cpv->k_id; ++cpv) { switch (cpv->k_id) { - #ifdef HAVE_PCRE_H case 2: /* dir-listing.exclude */ if (cpv->vtype != T_CONFIG_LOCAL) continue; - for (pcre **regex = cpv->v.v; *regex; ++regex) - pcre_free(*regex); - free(cpv->v.v); + pcre_keyvalue_buffer_free(cpv->v.v); break; - #endif default: break; } @@ -290,23 +264,9 @@ SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) { case 1: /* server.dir-listing *//*(historical)*/ break; case 2: /* dir-listing.exclude */ - #ifndef HAVE_PCRE_H - if (cpv->v.a->used > 0) { - log_error(srv->errh, __FILE__, __LINE__, - "pcre support is missing for: %s, " - "please install libpcre and the headers", - cpk[cpv->k_id].k); - return HANDLER_ERROR; - } - #else cpv->v.v = mod_dirlisting_parse_excludes(srv, cpv->v.a); - if (NULL == cpv->v.v) { - log_error(srv->errh, __FILE__, __LINE__, - "unexpected value for %s", cpk[cpv->k_id].k); - return HANDLER_ERROR; - } + if (NULL == cpv->v.v) return HANDLER_ERROR; cpv->vtype = T_CONFIG_LOCAL; - #endif break; case 3: /* dir-listing.hide-dotfiles */ case 4: /* dir-listing.external-css */ @@ -854,7 +814,6 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff #if defined(HAVE_XATTR) || defined(HAVE_EXTATTR) || !defined(_ATFILE_SOURCE) char *path_file = path + dlen; #endif - log_error_st * const errh = r->conf.errh; struct dirent *dent; #ifndef _ATFILE_SOURCE /*(not using fdopendir unless _ATFILE_SOURCE)*/ @@ -865,7 +824,7 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff DIR * const dp = (dfd >= 0) ? fdopendir(dfd) : NULL; #endif if (NULL == dp) { - log_perror(errh, __FILE__, __LINE__, "opendir %s", path); + log_perror(r->conf.errh, __FILE__, __LINE__, "opendir %s", path); if (dfd >= 0) close(dfd); free(path); return -1; @@ -908,7 +867,7 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff * elements, skipping any that match. */ if (p->conf.excludes - && mod_dirlisting_exclude(errh, p->conf.excludes, d_name, dsz)) + && mod_dirlisting_exclude(p->conf.excludes, d_name, dsz)) continue; /* NOTE: the manual says, d_name is never more than NAME_MAX |