summaryrefslogtreecommitdiff
path: root/src/mod_dirlisting.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-03-14 11:09:35 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-03-22 07:10:32 -0400
commitfe4310cc61a44d51f451bfdad16b1db7f6769fd4 (patch)
tree0b4a5a0c441eafb6a1c4f2944d62bda06d1f1ac7 /src/mod_dirlisting.c
parent7b9c5adda1f8254119627973618c4157746abba9 (diff)
downloadlighttpd-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.c99
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