Annotation of embedaddon/lighttpd/src/mod_alias.c, revision 1.1.1.3
1.1.1.3 ! misho 1: #include "first.h"
! 2:
1.1 misho 3: #include "base.h"
4: #include "log.h"
5: #include "buffer.h"
6:
7: #include "plugin.h"
8:
9: #include <ctype.h>
10: #include <stdlib.h>
11: #include <string.h>
12: #include <stdio.h>
13:
14: /* plugin config for all request/connections */
15: typedef struct {
16: array *alias;
17: } plugin_config;
18:
19: typedef struct {
20: PLUGIN_DATA;
21:
22: plugin_config **config_storage;
23:
24: plugin_config conf;
25: } plugin_data;
26:
27: /* init the plugin data */
28: INIT_FUNC(mod_alias_init) {
29: plugin_data *p;
30:
31: p = calloc(1, sizeof(*p));
32:
33:
34:
35: return p;
36: }
37:
38: /* detroy the plugin data */
39: FREE_FUNC(mod_alias_free) {
40: plugin_data *p = p_d;
41:
42: if (!p) return HANDLER_GO_ON;
43:
44: if (p->config_storage) {
45: size_t i;
46:
47: for (i = 0; i < srv->config_context->used; i++) {
48: plugin_config *s = p->config_storage[i];
49:
1.1.1.3 ! misho 50: if (NULL == s) continue;
1.1 misho 51:
52: array_free(s->alias);
53:
54: free(s);
55: }
56: free(p->config_storage);
57: }
58:
59: free(p);
60:
61: return HANDLER_GO_ON;
62: }
63:
64: /* handle plugin config and check values */
65:
66: SETDEFAULTS_FUNC(mod_alias_set_defaults) {
67: plugin_data *p = p_d;
68: size_t i = 0;
69:
70: config_values_t cv[] = {
71: { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
72: { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
73: };
74:
75: if (!p) return HANDLER_ERROR;
76:
1.1.1.2 misho 77: p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1 misho 78:
79: for (i = 0; i < srv->config_context->used; i++) {
1.1.1.3 ! misho 80: data_config const* config = (data_config const*)srv->config_context->data[i];
1.1 misho 81: plugin_config *s;
82:
83: s = calloc(1, sizeof(plugin_config));
84: s->alias = array_init();
85: cv[0].destination = s->alias;
86:
87: p->config_storage[i] = s;
88:
1.1.1.3 ! misho 89: if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
1.1 misho 90: return HANDLER_ERROR;
91: }
92: if (s->alias->used >= 2) {
93: const array *a = s->alias;
94: size_t j, k;
95:
96: for (j = 0; j < a->used; j ++) {
97: const buffer *prefix = a->data[a->sorted[j]]->key;
98: for (k = j + 1; k < a->used; k ++) {
99: const buffer *key = a->data[a->sorted[k]]->key;
100:
1.1.1.3 ! misho 101: if (buffer_string_length(key) < buffer_string_length(prefix)) {
1.1 misho 102: break;
103: }
1.1.1.3 ! misho 104: if (memcmp(key->ptr, prefix->ptr, buffer_string_length(prefix)) != 0) {
1.1 misho 105: break;
106: }
107: /* ok, they have same prefix. check position */
108: if (a->sorted[j] < a->sorted[k]) {
109: log_error_write(srv, __FILE__, __LINE__, "SBSBS",
110: "url.alias: `", key, "' will never match as `", prefix, "' matched first");
111: return HANDLER_ERROR;
112: }
113: }
114: }
115: }
116: }
117:
118: return HANDLER_GO_ON;
119: }
120:
121: #define PATCH(x) \
122: p->conf.x = s->x;
123: static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
124: size_t i, j;
125: plugin_config *s = p->config_storage[0];
126:
127: PATCH(alias);
128:
129: /* skip the first, the global context */
130: for (i = 1; i < srv->config_context->used; i++) {
131: data_config *dc = (data_config *)srv->config_context->data[i];
132: s = p->config_storage[i];
133:
134: /* condition didn't match */
135: if (!config_check_cond(srv, con, dc)) continue;
136:
137: /* merge config */
138: for (j = 0; j < dc->value->used; j++) {
139: data_unset *du = dc->value->data[j];
140:
141: if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
142: PATCH(alias);
143: }
144: }
145: }
146:
147: return 0;
148: }
149: #undef PATCH
150:
151: PHYSICALPATH_FUNC(mod_alias_physical_handler) {
152: plugin_data *p = p_d;
153: int uri_len, basedir_len;
154: char *uri_ptr;
155: size_t k;
156:
1.1.1.3 ! misho 157: if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
1.1 misho 158:
159: mod_alias_patch_connection(srv, con, p);
160:
161: /* not to include the tailing slash */
1.1.1.3 ! misho 162: basedir_len = buffer_string_length(con->physical.basedir);
1.1 misho 163: if ('/' == con->physical.basedir->ptr[basedir_len-1]) --basedir_len;
1.1.1.3 ! misho 164: uri_len = buffer_string_length(con->physical.path) - basedir_len;
1.1 misho 165: uri_ptr = con->physical.path->ptr + basedir_len;
166:
167: for (k = 0; k < p->conf.alias->used; k++) {
168: data_string *ds = (data_string *)p->conf.alias->data[k];
1.1.1.3 ! misho 169: int alias_len = buffer_string_length(ds->key);
1.1 misho 170:
171: if (alias_len > uri_len) continue;
1.1.1.3 ! misho 172: if (buffer_is_empty(ds->key)) continue;
1.1 misho 173:
174: if (0 == (con->conf.force_lowercase_filenames ?
175: strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
176: strncmp(uri_ptr, ds->key->ptr, alias_len))) {
177: /* matched */
178:
1.1.1.3 ! misho 179: buffer_copy_buffer(con->physical.basedir, ds->value);
! 180: buffer_copy_buffer(srv->tmp_buf, ds->value);
1.1 misho 181: buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
1.1.1.3 ! misho 182: buffer_copy_buffer(con->physical.path, srv->tmp_buf);
1.1 misho 183:
184: return HANDLER_GO_ON;
185: }
186: }
187:
188: /* not found */
189: return HANDLER_GO_ON;
190: }
191:
192: /* this function is called at dlopen() time and inits the callbacks */
193:
194: int mod_alias_plugin_init(plugin *p);
195: int mod_alias_plugin_init(plugin *p) {
196: p->version = LIGHTTPD_VERSION_ID;
197: p->name = buffer_init_string("alias");
198:
199: p->init = mod_alias_init;
200: p->handle_physical= mod_alias_physical_handler;
201: p->set_defaults = mod_alias_set_defaults;
202: p->cleanup = mod_alias_free;
203:
204: p->data = NULL;
205:
206: return 0;
207: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>