| 26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
| 27 */ |
27 */ |
| 28 |
28 |
| 29 #include "location.h" |
29 #include "location.h" |
| 30 #include "config.h" |
30 #include "config.h" |
| |
31 #include "request.h" |
| 31 #include "../util/util.h" |
32 #include "../util/util.h" |
| |
33 #include "../util/pblock.h" |
| |
34 #include "vserver.h" |
| 32 #include <cx/linked_list.h> |
35 #include <cx/linked_list.h> |
| 33 |
36 |
| 34 #define DIR_CHECK_ARGC(n) if(argc != n) { \ |
37 #define DIR_CHECK_ARGC(n) if(argc != n) { \ |
| 35 log_ereport(LOG_FAILURE, "%s directive argc != %d", name.ptr, n); \ |
38 log_ereport(LOG_FAILURE, "%s directive argc != %d", name.ptr, n); \ |
| 36 return 1; \ |
39 return 1; \ |
| 40 void **begin = (void**)&location->children_begin; |
43 void **begin = (void**)&location->children_begin; |
| 41 void **end = (void**)&location->children_end; |
44 void **end = (void**)&location->children_end; |
| 42 cx_linked_list_add(begin, end, offsetof(WSLocation, prev), offsetof(WSLocation, next), sub); |
45 cx_linked_list_add(begin, end, offsetof(WSLocation, prev), offsetof(WSLocation, next), sub); |
| 43 } |
46 } |
| 44 |
47 |
| 45 static int add_location_config(const CxAllocator *a, WSLocation *location, ConfigNode *dir) { |
48 static int add_location_config(ServerConfiguration *cfg, WSLocation *location, ConfigNode *dir) { |
| |
49 const CxAllocator *a = cfg->a; |
| |
50 |
| 46 cxmutstr name = dir->name; |
51 cxmutstr name = dir->name; |
| 47 int argc = serverconfig_directive_count_args(dir); |
52 int argc = serverconfig_directive_count_args(dir); |
| 48 if(!cx_strcasecmp(name, "DirectoryIndex")) { |
53 if(!cx_strcasecmp(name, "DirectoryIndex")) { |
| 49 DIR_CHECK_ARGC(1); |
54 DIR_CHECK_ARGC(1); |
| 50 location->config.set_dirindex = TRUE; |
55 location->config.set_dirindex = TRUE; |
| 51 location->config.dirindex = util_getboolean_s(cx_strcast(dir->args->value), FALSE); |
56 location->config.dirindex = util_getboolean_s(cx_strcast(dir->args->value), FALSE); |
| 52 } else if(!cx_strcasecmp(name, "DocumentRoot")) { |
57 } else if(!cx_strcasecmp(name, "DocumentRoot")) { |
| 53 DIR_CHECK_ARGC(1); |
58 DIR_CHECK_ARGC(1); |
| 54 location->config.docroot = cx_strdup_a(a, dir->args->value); |
59 location->config.docroot = cx_strdup_a(a, dir->args->value); |
| 55 } else if(!cx_strcasecmp(name, "Location")) { |
60 } else if(!cx_strcasecmp(name, "Location")) { |
| 56 WSLocation *sub_location = cfg_location_get(a, dir); |
61 WSLocation *sub_location = cfg_location_get(cfg, dir); |
| 57 if(!sub_location) { |
62 if(!sub_location) { |
| 58 return 1; |
63 return 1; |
| 59 } |
64 } |
| 60 location_list_add(location, sub_location); |
65 location_list_add(location, sub_location); |
| 61 } |
66 } |
| 62 |
67 |
| 63 return 0; |
68 return 0; |
| 64 } |
69 } |
| 65 |
70 |
| 66 |
71 |
| 67 WSLocation* cfg_location_get(const CxAllocator *a, ConfigNode *obj) { |
72 WSLocation* cfg_location_get(ServerConfiguration *cfg, ConfigNode *obj) { |
| |
73 const CxAllocator *a = cfg->a; |
| |
74 |
| 68 WSLocationMatch match = WS_LOCATION_MATCH_EXACT; |
75 WSLocationMatch match = WS_LOCATION_MATCH_EXACT; |
| 69 cxmutstr match_str; |
76 cxmutstr match_str; |
| 70 |
77 |
| 71 int regex_flags = REG_EXTENDED; |
78 int regex_flags = REG_EXTENDED | REG_NOSUB; |
| 72 int argc = serverconfig_directive_count_args(obj); |
79 int argc = serverconfig_directive_count_args(obj); |
| 73 if(argc == 2) { |
80 if(argc == 2) { |
| 74 // arg0: match type |
81 // arg0: match type |
| 75 cxmutstr type_str = obj->args->value; |
82 cxmutstr type_str = obj->args->value; |
| 76 if(!cx_strcmp(type_str, "=")) { |
83 if(!cx_strcmp(type_str, "=")) { |
| 120 |
127 |
| 121 |
128 |
| 122 |
129 |
| 123 return location; |
130 return location; |
| 124 } |
131 } |
| |
132 |
| |
133 int location_apply_config(WSLocationConfig *target, WSLocation *loc) { |
| |
134 WSLocationConfig *src = &loc->config; |
| |
135 if(src->set_dirindex) { |
| |
136 target->set_dirindex = TRUE; |
| |
137 target->dirindex = src->dirindex; |
| |
138 } |
| |
139 if(src->set_forcetls) { |
| |
140 target->set_forcetls = TRUE; |
| |
141 target->forcetls = src->forcetls; |
| |
142 } |
| |
143 if(src->docroot.ptr) { |
| |
144 target->docroot = src->docroot; |
| |
145 } |
| |
146 if(src->name.ptr) { |
| |
147 target->name = src->name; |
| |
148 } |
| |
149 if(src->dav) { |
| |
150 target->dav = src->dav; |
| |
151 } |
| |
152 // TODO: ... |
| |
153 |
| |
154 return 0; |
| |
155 } |
| |
156 |
| |
157 int location_match(WSLocation *loc, cxstring uri) { |
| |
158 if(loc->match == WS_LOCATION_MATCH_EXACT) { |
| |
159 return !cx_strcmp(loc->match_string, uri); |
| |
160 } else if(loc->match == WS_LOCATION_MATCH_PREFIX) { |
| |
161 return cx_strprefix(uri, loc->match_string); |
| |
162 } else { |
| |
163 return regexec(&loc->regex, uri.ptr, 0, NULL, 0) == 0; |
| |
164 } |
| |
165 return 0; |
| |
166 } |
| |
167 |
| |
168 WSLocationConfig* location_match_and_get_config(pool_handle_t *pool, cxstring uri, WSLocation *loc) { |
| |
169 WSLocationConfig *config = pool_malloc(pool, sizeof(WSLocationConfig)); |
| |
170 if(!config) { |
| |
171 return NULL; |
| |
172 } |
| |
173 ZERO(config, sizeof(WSLocationConfig)); |
| |
174 |
| |
175 while(loc) { |
| |
176 if(location_match(loc, uri)) { |
| |
177 if(location_apply_config(config, loc)) { |
| |
178 return NULL; |
| |
179 } |
| |
180 } |
| |
181 loc = loc->next; |
| |
182 } |
| |
183 |
| |
184 |
| |
185 return config; |
| |
186 } |
| |
187 |
| |
188 WSLocationConfig* cfg_location_match(Session *sn, Request *rq) { |
| |
189 NSAPIRequest *req = (NSAPIRequest*)rq; |
| |
190 WSLocation *loc = req->vs->locations_begin; |
| |
191 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); |
| |
192 return location_match_and_get_config(sn->pool, cx_str(uri), loc); |
| |
193 } |