15 |
15 |
|
16 |
16 |
typedef struct {
|
17 |
17 |
pcre_keyvalue_buffer *redirect;
|
|
18 |
#ifdef HAVE_GLIB_H
|
|
19 |
GHashTable *redirect_simple;
|
|
20 |
#endif
|
18 |
21 |
data_config *context; /* to which apply me */
|
19 |
22 |
|
20 |
23 |
unsigned short redirect_code;
|
... | ... | |
43 |
46 |
return p;
|
44 |
47 |
}
|
45 |
48 |
|
|
49 |
#ifdef HAVE_GLIB_H
|
|
50 |
static gboolean mod_redirect_simple_free_hrfunc(gpointer k, gpointer v, gpointer user_data) {
|
|
51 |
buffer_free((buffer *)k);
|
|
52 |
buffer_free((buffer *)v);
|
|
53 |
|
|
54 |
UNUSED(user_data);
|
|
55 |
|
|
56 |
return TRUE;
|
|
57 |
}
|
|
58 |
#endif
|
|
59 |
|
46 |
60 |
FREE_FUNC(mod_redirect_free) {
|
47 |
61 |
plugin_data *p = p_d;
|
48 |
62 |
|
... | ... | |
54 |
68 |
plugin_config *s = p->config_storage[i];
|
55 |
69 |
|
56 |
70 |
pcre_keyvalue_buffer_free(s->redirect);
|
|
71 |
#ifdef HAVE_GLIB_H
|
|
72 |
g_hash_table_foreach_remove(s->redirect_simple, mod_redirect_simple_free_hrfunc, NULL);
|
|
73 |
g_hash_table_destroy(s->redirect_simple);
|
|
74 |
#endif
|
57 |
75 |
|
58 |
76 |
free(s);
|
59 |
77 |
}
|
... | ... | |
76 |
94 |
|
77 |
95 |
config_values_t cv[] = {
|
78 |
96 |
{ "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
|
79 |
|
{ "url.redirect-code", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
|
|
97 |
{ "url.redirect-simple", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
|
|
98 |
{ "url.redirect-code", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
|
80 |
99 |
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
|
81 |
100 |
};
|
82 |
101 |
|
... | ... | |
93 |
112 |
|
94 |
113 |
s = calloc(1, sizeof(plugin_config));
|
95 |
114 |
s->redirect = pcre_keyvalue_buffer_init();
|
|
115 |
s->redirect_simple = g_hash_table_new(buffer_key_hash, buffer_key_equal);
|
96 |
116 |
|
97 |
117 |
cv[0].destination = s->redirect;
|
98 |
|
cv[1].destination = &(s->redirect_code);
|
|
118 |
cv[1].destination = s->redirect_simple;
|
|
119 |
cv[2].destination = &(s->redirect_code);
|
99 |
120 |
|
100 |
121 |
p->config_storage[i] = s;
|
101 |
122 |
ca = ((data_config *)srv->config_context->data[i])->value;
|
... | ... | |
104 |
125 |
return HANDLER_ERROR;
|
105 |
126 |
}
|
106 |
127 |
|
107 |
|
if (NULL == (du = array_get_element(ca, CONST_STR_LEN("url.redirect")))) {
|
108 |
|
/* no url.redirect defined */
|
109 |
|
continue;
|
110 |
|
}
|
|
128 |
if (NULL != (du = array_get_element(ca, CONST_STR_LEN("url.redirect")))) {
|
|
129 |
/* url.redirect defined */
|
|
130 |
if (du->type != TYPE_ARRAY) {
|
|
131 |
log_error_write(srv, __FILE__, __LINE__, "sss",
|
|
132 |
"unexpected type for key: ", "url.redirect", "array of strings");
|
|
133 |
|
|
134 |
return HANDLER_ERROR;
|
|
135 |
}
|
111 |
136 |
|
112 |
|
if (du->type != TYPE_ARRAY) {
|
113 |
|
log_error_write(srv, __FILE__, __LINE__, "sss",
|
114 |
|
"unexpected type for key: ", "url.redirect", "array of strings");
|
|
137 |
da = (data_array *)du;
|
115 |
138 |
|
116 |
|
return HANDLER_ERROR;
|
117 |
|
}
|
|
139 |
for (j = 0; j < da->value->used; j++) {
|
|
140 |
if (da->value->data[j]->type != TYPE_STRING) {
|
|
141 |
log_error_write(srv, __FILE__, __LINE__, "sssbs",
|
|
142 |
"unexpected type for key: ",
|
|
143 |
"url.redirect",
|
|
144 |
"[", da->value->data[j]->key, "](string)");
|
118 |
145 |
|
119 |
|
da = (data_array *)du;
|
|
146 |
return HANDLER_ERROR;
|
|
147 |
}
|
120 |
148 |
|
121 |
|
for (j = 0; j < da->value->used; j++) {
|
122 |
|
if (da->value->data[j]->type != TYPE_STRING) {
|
123 |
|
log_error_write(srv, __FILE__, __LINE__, "sssbs",
|
124 |
|
"unexpected type for key: ",
|
125 |
|
"url.redirect",
|
126 |
|
"[", da->value->data[j]->key, "](string)");
|
|
149 |
if (0 != pcre_keyvalue_buffer_append(s->redirect,
|
|
150 |
((data_string *)(da->value->data[j]))->key->ptr,
|
|
151 |
((data_string *)(da->value->data[j]))->value->ptr)) {
|
127 |
152 |
|
128 |
|
return HANDLER_ERROR;
|
|
153 |
log_error_write(srv, __FILE__, __LINE__, "sb",
|
|
154 |
"pcre-compile failed for", da->value->data[j]->key);
|
|
155 |
}
|
129 |
156 |
}
|
|
157 |
}
|
|
158 |
if (NULL != (du = array_get_element(ca, CONST_STR_LEN("url.redirect-simple")))) {
|
|
159 |
/* url.redirect-simple defined */
|
|
160 |
if (du->type != TYPE_ARRAY) {
|
|
161 |
log_error_write(srv, __FILE__, __LINE__, "sss",
|
|
162 |
"unexpected type for key: ", "url.redirect-simple", "array of strings");
|
130 |
163 |
|
131 |
|
if (0 != pcre_keyvalue_buffer_append(s->redirect,
|
132 |
|
((data_string *)(da->value->data[j]))->key->ptr,
|
133 |
|
((data_string *)(da->value->data[j]))->value->ptr)) {
|
|
164 |
return HANDLER_ERROR;
|
|
165 |
}
|
134 |
166 |
|
135 |
|
log_error_write(srv, __FILE__, __LINE__, "sb",
|
136 |
|
"pcre-compile failed for", da->value->data[j]->key);
|
|
167 |
da = (data_array *)du;
|
|
168 |
|
|
169 |
for (j = 0; j < da->value->used; j++) {
|
|
170 |
if (da->value->data[j]->type != TYPE_STRING) {
|
|
171 |
log_error_write(srv, __FILE__, __LINE__, "sssbs",
|
|
172 |
"unexpected type for key: ",
|
|
173 |
"url.redirect-simple",
|
|
174 |
"[", da->value->data[j]->key, "](string)");
|
|
175 |
|
|
176 |
return HANDLER_ERROR;
|
|
177 |
}
|
|
178 |
|
|
179 |
g_hash_table_insert(s->redirect_simple,
|
|
180 |
buffer_init_string(
|
|
181 |
((data_string *)(da->value->data[j]))->key->ptr
|
|
182 |
),
|
|
183 |
buffer_init_string(
|
|
184 |
((data_string *)(da->value->data[j]))->value->ptr
|
|
185 |
)
|
|
186 |
);
|
137 |
187 |
}
|
138 |
188 |
}
|
139 |
189 |
}
|
140 |
190 |
|
141 |
191 |
return HANDLER_GO_ON;
|
142 |
192 |
}
|
143 |
|
#ifdef HAVE_PCRE_H
|
|
193 |
#if defined (HAVE_PCRE_H) || defined (HAVE_GLIB_H)
|
144 |
194 |
static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
|
145 |
195 |
size_t i, j;
|
146 |
196 |
plugin_config *s = p->config_storage[0];
|
147 |
197 |
|
|
198 |
#ifdef HAVE_PCRE_H
|
148 |
199 |
PATCH_OPTION(redirect);
|
|
200 |
#endif
|
|
201 |
#ifdef HAVE_GLIB_H
|
|
202 |
PATCH_OPTION(redirect_simple);
|
|
203 |
#endif
|
149 |
204 |
PATCH_OPTION(redirect_code);
|
150 |
205 |
|
151 |
206 |
/* skip the first, the global context */
|
... | ... | |
160 |
215 |
for (j = 0; j < dc->value->used; j++) {
|
161 |
216 |
data_unset *du = dc->value->data[j];
|
162 |
217 |
|
163 |
|
if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect"))) {
|
|
218 |
if
|
|
219 |
#ifdef HAVE_PCRE_H
|
|
220 |
(buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect"))) {
|
164 |
221 |
PATCH_OPTION(redirect);
|
165 |
222 |
p->conf.context = dc;
|
166 |
|
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-code"))) {
|
|
223 |
} else if
|
|
224 |
#endif
|
|
225 |
#ifdef HAVE_GLIB_H
|
|
226 |
(buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-simple"))) {
|
|
227 |
PATCH_OPTION(redirect_simple);
|
|
228 |
p->conf.context = dc;
|
|
229 |
} else if
|
|
230 |
#endif
|
|
231 |
(buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-code"))) {
|
167 |
232 |
PATCH_OPTION(redirect_code);
|
168 |
233 |
}
|
169 |
234 |
}
|
... | ... | |
173 |
238 |
}
|
174 |
239 |
#endif
|
175 |
240 |
static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
|
176 |
|
#ifdef HAVE_PCRE_H
|
|
241 |
#if defined (HAVE_PCRE_H) || defined (HAVE_GLIB_H)
|
177 |
242 |
plugin_data *p = p_data;
|
178 |
243 |
int i;
|
|
244 |
buffer *dest;
|
179 |
245 |
|
180 |
246 |
/*
|
181 |
247 |
* REWRITE URL
|
... | ... | |
187 |
253 |
mod_redirect_patch_connection(srv, con, p);
|
188 |
254 |
|
189 |
255 |
buffer_copy_string_buffer(p->match_buf, con->request.uri);
|
190 |
|
i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
|
191 |
|
|
192 |
|
if (i >= 0) {
|
193 |
|
response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
|
|
256 |
#ifdef HAVE_GLIB_H
|
|
257 |
dest = g_hash_table_lookup(p->conf.redirect_simple, p->match_buf);
|
|
258 |
if (dest != NULL) {
|
|
259 |
response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(dest));
|
|
260 |
i = -1;
|
|
261 |
} else {
|
|
262 |
#endif
|
|
263 |
#ifdef HAVE_PCRE_H
|
|
264 |
i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
|
|
265 |
if (i >= 0) {
|
|
266 |
response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
|
|
267 |
}
|
|
268 |
else if (i != PCRE_ERROR_NOMATCH) {
|
|
269 |
log_error_write(srv, __FILE__, __LINE__, "s",
|
|
270 |
"execution error while matching", i);
|
|
271 |
}
|
|
272 |
#endif
|
|
273 |
#ifdef HAVE_GLIB_H
|
|
274 |
}
|
|
275 |
#else
|
|
276 |
dest = NULL;
|
|
277 |
#endif
|
|
278 |
if (dest != NULL || i >= 0) {
|
194 |
279 |
|
195 |
280 |
con->http_status = p->conf.redirect_code > 99 && p->conf.redirect_code < 1000 ? p->conf.redirect_code : 301;
|
196 |
281 |
con->send->is_closed = 1;
|
197 |
282 |
|
198 |
283 |
return HANDLER_FINISHED;
|
199 |
284 |
}
|
200 |
|
else if (i != PCRE_ERROR_NOMATCH) {
|
201 |
|
log_error_write(srv, __FILE__, __LINE__, "s",
|
202 |
|
"execution error while matching", i);
|
203 |
|
}
|
204 |
285 |
#undef N
|
205 |
286 |
|
206 |
287 |
#else
|