[core] Add liPattern type and associated functions
parent
7174ca4d15
commit
3668ef97ab
|
@ -56,6 +56,8 @@
|
|||
#include <lighttpd/log.h>
|
||||
#include <lighttpd/stat_cache.h>
|
||||
#include <lighttpd/throttle.h>
|
||||
#include <lighttpd/pattern.h>
|
||||
#include <lighttpd/encoding.h>
|
||||
|
||||
#include <lighttpd/connection.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _LIGHTTPD_PATTERN_H_
|
||||
#define _LIGHTTPD_PATTERN_H_
|
||||
|
||||
/* liPattern are a parsed representation of a string that can contain various placeholders like $n, %n, %{var} or {enc:var} */
|
||||
|
||||
typedef struct {
|
||||
enum {
|
||||
PATTERN_STRING, /* literal */
|
||||
PATTERN_NTH, /* $n */
|
||||
PATTERN_NTH_PREV, /* %n */
|
||||
PATTERN_VAR, /* %{req.foo} */
|
||||
PATTERN_VAR_ENCODED /* %{enc:req.foo} */
|
||||
} type;
|
||||
|
||||
union {
|
||||
GString *str; /* PATTERN_STRING */
|
||||
guint8 ndx; /* PATTERN_NTH and PATTERN_NTH_PREV */
|
||||
liCondLValue var; /* PATTERN_VAR and PATTERN_VAR_ENCODED */
|
||||
} data;
|
||||
} liPatternPart;
|
||||
|
||||
/* liPattern is a GArray in disguise */
|
||||
typedef GArray liPattern;
|
||||
|
||||
/* a pattern callback receives an integer index and a data pointer (usually an array) and must return a GString* which gets inserted into the pattern result */
|
||||
typedef void (*liPatternCB) (GString *pattern_result, guint8 nth_ndx, gpointer data);
|
||||
|
||||
/* constructs a new liPattern* by parsing the given string, returns NULL on error */
|
||||
LI_API liPattern *li_pattern_new(const gchar* str);
|
||||
LI_API void li_pattern_free(liPattern *pattern);
|
||||
|
||||
LI_API void li_pattern_eval(liVRequest *vr, GString *dest, liPattern *pattern, liPatternCB nth_callback, gpointer nth_data, liPatternCB nth_prev_callback, gpointer nth_prev_data);
|
||||
|
||||
/* default array callback, expects a GArray* containing GString* elements */
|
||||
LI_API void li_pattern_array_cb(GString *pattern_result, guint8 nth_ndx, gpointer data);
|
||||
/* default regex callback, expects a GMatchInfo* */
|
||||
LI_API void li_pattern_regex_cb(GString *pattern_result, guint8 nth_ndx, gpointer data);
|
||||
|
||||
#endif
|
|
@ -206,6 +206,7 @@ SET(LIGHTTPD_SHARED_SRC
|
|||
network_write.c network_writev.c
|
||||
network_sendfile.c
|
||||
options.c
|
||||
pattern.c
|
||||
plugin.c
|
||||
request.c
|
||||
response.c
|
||||
|
|
|
@ -28,6 +28,7 @@ lighttpd_shared_src= \
|
|||
network_write.c network_writev.c \
|
||||
network_sendfile.c \
|
||||
options.c \
|
||||
pattern.c \
|
||||
plugin.c \
|
||||
request.c \
|
||||
response.c \
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
#include <lighttpd/base.h>
|
||||
|
||||
liPattern *li_pattern_new(const gchar* str) {
|
||||
GArray *pattern;
|
||||
liPatternPart part;
|
||||
gchar *c;
|
||||
gboolean encoded;
|
||||
|
||||
pattern = g_array_new(FALSE, TRUE, sizeof(liPatternPart));
|
||||
|
||||
for (c = (gchar*)str; *c;) {
|
||||
if (*c == '$') {
|
||||
/* $n, PATTERN_NTH */
|
||||
c++;
|
||||
if (*c >= '0' && *c <= '9') {
|
||||
part.type = PATTERN_NTH;
|
||||
part.data.ndx = *c - '0';
|
||||
g_array_append_val(pattern, part);
|
||||
c++;
|
||||
} else {
|
||||
/* parse error */
|
||||
li_pattern_free((liPattern*)pattern);
|
||||
return NULL;
|
||||
}
|
||||
} else if (*c == '%') {
|
||||
c++;
|
||||
if (*c >= '0' && *c <= '9') {
|
||||
/* %n, PATTERN_NTH_PREV */
|
||||
part.type = PATTERN_NTH_PREV;
|
||||
part.data.ndx = *c - '0';
|
||||
g_array_append_val(pattern, part);
|
||||
c++;
|
||||
} else if (*c == '{') {
|
||||
/* %{var}, PATTERN_VAR */
|
||||
guint len;
|
||||
|
||||
c++;
|
||||
encoded = FALSE;
|
||||
|
||||
if (g_str_has_prefix(c, "enc:")) {
|
||||
/* %{enc:var}, PATTERN_VAR_ENCODED */
|
||||
c += sizeof("enc:")-1;
|
||||
encoded = TRUE;
|
||||
}
|
||||
|
||||
for (len = 0; *c != '\0' && *c != '}'; c++)
|
||||
len++;
|
||||
|
||||
if (*c == '\0') {
|
||||
/* parse error */
|
||||
li_pattern_free((liPattern*)pattern);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
part.data.var = li_cond_lvalue_from_string(c-len, len);
|
||||
|
||||
if (part.data.var == LI_COMP_UNKNOWN) {
|
||||
/* parse error */
|
||||
li_pattern_free((liPattern*)pattern);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len && *c == '}') {
|
||||
part.type = encoded ? PATTERN_VAR_ENCODED : PATTERN_VAR;
|
||||
g_array_append_val(pattern, part);
|
||||
c++;
|
||||
} else {
|
||||
/* parse error */
|
||||
li_pattern_free((liPattern*)pattern);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* parse error */
|
||||
li_pattern_free((liPattern*)pattern);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* string */
|
||||
gchar *first = c;
|
||||
c++;
|
||||
|
||||
for (;;) {
|
||||
if (*c == '\0' || *c == '?' || *c == '$' || *c == '%') {
|
||||
break;
|
||||
} else if (*c == '\\') {
|
||||
c++;
|
||||
if (*c == '\\' || *c == '?' || *c == '$' || *c == '%') {
|
||||
c++;
|
||||
} else {
|
||||
/* parse error */
|
||||
li_pattern_free((liPattern*)pattern);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
part.type = PATTERN_STRING;
|
||||
part.data.str= g_string_new_len(first, c - first);
|
||||
g_array_append_val(pattern, part);
|
||||
}
|
||||
}
|
||||
|
||||
return (liPattern*) pattern;
|
||||
}
|
||||
|
||||
|
||||
void li_pattern_free(liPattern *pattern) {
|
||||
guint i;
|
||||
GArray *arr = (GArray*) pattern;
|
||||
|
||||
for (i = 0; i < arr->len; i++) {
|
||||
if (g_array_index(arr, liPatternPart, i).type == PATTERN_STRING)
|
||||
g_string_free(g_array_index(arr, liPatternPart, i).data.str, TRUE);
|
||||
}
|
||||
|
||||
g_array_free(arr, TRUE);
|
||||
}
|
||||
|
||||
void li_pattern_eval(liVRequest *vr, GString *dest, liPattern *pattern, liPatternCB nth_callback, gpointer nth_data, liPatternCB nth_prev_callback, gpointer nth_prev_data) {
|
||||
guint i;
|
||||
gboolean encoded;
|
||||
GString *str;
|
||||
GString str_stack;
|
||||
GArray *arr = (GArray*) pattern;
|
||||
|
||||
for (i = 0; i < arr->len; i++) {
|
||||
liPatternPart *part = &g_array_index(arr, liPatternPart, i);
|
||||
encoded = FALSE;
|
||||
|
||||
switch (part->type) {
|
||||
case PATTERN_STRING:
|
||||
g_string_append_len(dest, GSTR_LEN(part->data.str));
|
||||
break;
|
||||
case PATTERN_NTH:
|
||||
nth_callback(dest, part->data.ndx, nth_data);
|
||||
break;
|
||||
case PATTERN_NTH_PREV:
|
||||
nth_prev_callback(dest, part->data.ndx, nth_prev_data);
|
||||
break;
|
||||
case PATTERN_VAR_ENCODED:
|
||||
encoded = TRUE;
|
||||
/* fall through */
|
||||
case PATTERN_VAR:
|
||||
switch (part->data.var) {
|
||||
case LI_COMP_REQUEST_LOCALIP: str = vr->con->local_addr_str; break;
|
||||
case LI_COMP_REQUEST_REMOTEIP: str = vr->con->remote_addr_str; break;
|
||||
case LI_COMP_REQUEST_SCHEME:
|
||||
if (vr->con->is_ssl)
|
||||
str_stack = li_const_gstring(CONST_STR_LEN("https"));
|
||||
else
|
||||
str_stack = li_const_gstring(CONST_STR_LEN("http"));
|
||||
str = &str_stack;
|
||||
break;
|
||||
case LI_COMP_REQUEST_PATH: str = vr->request.uri.path; break;
|
||||
case LI_COMP_REQUEST_HOST: str = vr->request.uri.host; break;
|
||||
case LI_COMP_REQUEST_QUERY_STRING: str = vr->request.uri.query; break;
|
||||
case LI_COMP_REQUEST_METHOD: str = vr->request.http_method_str; break;
|
||||
case LI_COMP_REQUEST_CONTENT_LENGTH:
|
||||
g_string_printf(vr->con->wrk->tmp_str, "%"L_GOFFSET_FORMAT, vr->request.content_length);
|
||||
str = vr->con->wrk->tmp_str;
|
||||
break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
if (encoded)
|
||||
li_string_encode_append(str->str, dest, LI_ENCODING_URI);
|
||||
else
|
||||
g_string_append_len(dest, GSTR_LEN(str));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void li_pattern_array_cb(GString *pattern_result, guint8 nth_ndx, gpointer data) {
|
||||
GString *str = g_array_index((GArray*)data, GString*, nth_ndx);
|
||||
|
||||
g_string_append_len(pattern_result, GSTR_LEN(str));
|
||||
}
|
||||
|
||||
void li_pattern_regex_cb(GString *pattern_result, guint8 nth_ndx, gpointer data) {
|
||||
gint start_pos, end_pos;
|
||||
GMatchInfo *match_info = data;
|
||||
|
||||
if (!match_info)
|
||||
return;
|
||||
|
||||
if (g_match_info_fetch_pos(match_info, (gint)nth_ndx, &start_pos, &end_pos))
|
||||
g_string_append_len(pattern_result, g_match_info_get_string(match_info) + start_pos, end_pos - start_pos);
|
||||
}
|
|
@ -43,6 +43,7 @@ def build(bld):
|
|||
network_write.c
|
||||
network_writev.c
|
||||
options.c
|
||||
pattern.c
|
||||
plugin.c
|
||||
plugin_core.c
|
||||
request.c
|
||||
|
|
Loading…
Reference in New Issue