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