source: Main/trunk/Server/config.c@ 212

Last change on this file since 212 was 212, checked in by Nishi, on Oct 3, 2024 at 2:44:55 AM

compiles on vc6

  • Property svn:keywords set to Id
File size: 13.3 KB
Line 
1/* $Id: config.c 212 2024-10-02 17:44:55Z nishi $ */
2
3#define SOURCE
4
5#include "tw_config.h"
6#include "tw_module.h"
7
8#include <stdio.h>
9#include <stdint.h>
10#include <stdlib.h>
11#include <string.h>
12
13#ifndef _MSC_VER
14#include <unistd.h>
15#endif
16
17#if defined(__MINGW32__) || defined(_MSC_VER)
18#include <winsock2.h>
19#endif
20
21#include <cm_string.h>
22#include <cm_log.h>
23
24struct tw_config config;
25
26struct tw_config_entry* tw_vhost_match(const char* name, int port) {
27 int i;
28 for(i = 0; i < config.vhost_count; i++) {
29 if(strcmp(config.vhosts[i].name, name) == 0 && (config.vhosts[i].port == -1 ? 1 : config.vhosts[i].port == port)) {
30 return &config.vhosts[i];
31 }
32 }
33 return &config.root;
34}
35
36bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost) {
37 int i;
38 bool found = false;
39 bool pathstart = false;
40 bool perm = false;
41again:
42 for(i = 0; i < vhost->dir_count; i++) {
43 char* noslash;
44 struct tw_dir_entry* e = &vhost->dirs[i];
45 pathstart = false;
46 if(strlen(path) >= strlen(e->dir)) {
47 int j;
48 pathstart = true;
49 for(j = 0; path[j] != 0 && e->dir[j] != 0; j++) {
50 if(path[j] != e->dir[j]) {
51 pathstart = false;
52 break;
53 }
54 }
55 }
56 noslash = cm_strdup(e->dir);
57 noslash[strlen(noslash) - 1] = 0;
58 if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart) {
59 found = true;
60 if(strcmp(e->name, "all") == 0) {
61 perm = e->type == TW_DIR_ALLOW;
62 }
63 }
64 free(noslash);
65 }
66 if(!found && vhost != &config.root) {
67 vhost = &config.root;
68 goto again;
69 }
70 return perm;
71}
72
73void tw_config_init(void) {
74 int i;
75 for(i = 0; i < MAX_PORTS + 1; i++) {
76 config.ports[i] = -1;
77 }
78 for(i = 0; i < MAX_VHOSTS; i++) {
79#ifndef NO_SSL
80 config.vhosts[i].sslkey = NULL;
81 config.vhosts[i].sslcert = NULL;
82#endif
83 config.vhosts[i].root = NULL;
84#ifdef HAS_CHROOT
85 config.vhosts[i].chroot_path = NULL;
86#endif
87 }
88#ifndef NO_SSL
89 config.root.sslkey = NULL;
90 config.root.sslcert = NULL;
91#endif
92 config.root.root = NULL;
93 config.root.mime_count = 0;
94 config.root.dir_count = 0;
95 config.root.icon_count = 0;
96 config.root.index_count = 0;
97 config.root.readme_count = 0;
98 config.root.hideport = 0;
99#ifdef HAS_CHROOT
100 config.root.chroot_path = NULL;
101#endif
102 config.vhost_count = 0;
103 config.module_count = 0;
104 config.extension = NULL;
105 config.server_root = cm_strdup(PREFIX);
106 config.server_admin = cm_strdup(SERVER_ADMIN);
107 config.defined[0] = NULL;
108#if defined(_PSP)
109 strcpy(config.hostname, "psp");
110#elif defined(__PPU__)
111 strcpy(config.hostname, "ps3");
112#elif defined(__ps2sdk__)
113 strcpy(config.hostname, "ps2");
114#else
115 gethostname(config.hostname, 1024);
116#endif
117#ifdef HAS_CHROOT
118 tw_add_define("HAS_CHROOT");
119#endif
120#ifndef NO_SSL
121 tw_add_define("HAS_SSL");
122#endif
123}
124
125int tw_config_read(const char* path) {
126 char cbuf[2];
127 int ln = 0;
128 int ifbr = 0;
129 int ignore = -1;
130 FILE* f;
131 cm_log("Config", "Reading %s", path);
132 f = fopen(path, "r");
133 cbuf[1] = 0;
134 if(f != NULL) {
135 char* line = malloc(1);
136 int stop = 0;
137 struct tw_config_entry* current = &config.root;
138 char* vhost = NULL;
139 char* dir = NULL;
140 line[0] = 0;
141 while(stop == 0) {
142 int c = fread(cbuf, 1, 1, f);
143 if(cbuf[0] == '\n' || c <= 0) {
144 char* l = cm_trim(line);
145 ln++;
146 if(strlen(l) > 0 && l[0] != '#') {
147 char** r = cm_split(l, " \t");
148 int i;
149 if(ignore != -1 && ifbr >= ignore) {
150 if(cm_strcaseequ(r[0], "EndIf")) ifbr--;
151 if(ifbr == 0) {
152 ignore = -1;
153 }
154 } else if(cm_strcaseequ(r[0], "Include") || cm_strcaseequ(r[0], "IncludeOptional")) {
155 for(i = 1; r[i] != NULL; i++) {
156 if(tw_config_read(r[i]) != 0 && cm_strcaseequ(r[0], "Include")) {
157 stop = 1;
158 break;
159 }
160 }
161 } else if(cm_strcaseequ(r[0], "Define")) {
162 if(r[1] == NULL) {
163 cm_log("Config", "Missing name at line %d", ln);
164 stop = 1;
165 } else {
166 tw_add_define(r[1]);
167 }
168 } else if(cm_strcaseequ(r[0], "Undefine")) {
169 if(r[1] == NULL) {
170 cm_log("Config", "Missing name at line %d", ln);
171 stop = 1;
172 } else {
173 tw_delete_define(r[1]);
174 }
175 } else if(cm_strcaseequ(r[0], "BeginDirectory")) {
176 if(dir != NULL) {
177 cm_log("Config", "Already in directory section at line %d", ln);
178 stop = 1;
179 } else {
180 if(r[1] == NULL) {
181 cm_log("Config", "Missing directory at line %d", ln);
182 stop = 1;
183 } else {
184 dir = cm_strcat(r[1], r[1][strlen(r[1]) - 1] == '/' ? "" : "/");
185 }
186 }
187 } else if(cm_strcaseequ(r[0], "EndDirectory")) {
188 if(dir == NULL) {
189 cm_log("Config", "Not in directory section at line %d", ln);
190 stop = 1;
191 } else {
192 free(dir);
193 dir = NULL;
194 }
195 } else if(cm_strcaseequ(r[0], "Allow")) {
196 if(dir == NULL) {
197 cm_log("Config", "Not in directory section at line %d", ln);
198 stop = 1;
199 } else {
200 if(r[1] == NULL) {
201 cm_log("Config", "Missing argument at line %d", ln);
202 stop = 1;
203 } else {
204 struct tw_dir_entry* e = &current->dirs[current->dir_count++];
205 e->name = cm_strdup(r[1]);
206 e->dir = cm_strdup(dir);
207 e->type = TW_DIR_ALLOW;
208 }
209 }
210 } else if(cm_strcaseequ(r[0], "Deny")) {
211 if(dir == NULL) {
212 cm_log("Config", "Not in directory section at line %d", ln);
213 stop = 1;
214 } else {
215 if(r[1] == NULL) {
216 cm_log("Config", "Missing argument at line %d", ln);
217 stop = 1;
218 } else {
219 struct tw_dir_entry* e = &current->dirs[current->dir_count++];
220 e->name = cm_strdup(r[1]);
221 e->dir = cm_strdup(dir);
222 e->type = TW_DIR_DENY;
223 }
224 }
225 } else if(cm_strcaseequ(r[0], "BeginVirtualHost")) {
226 if(vhost != NULL) {
227 cm_log("Config", "Already in virtual host section at line %d", ln);
228 stop = 1;
229 } else {
230 if(r[1] == NULL) {
231 cm_log("Config", "Missing virtual host at line %d", ln);
232 stop = 1;
233 } else {
234 int i;
235 vhost = cm_strdup(r[1]);
236 current = &config.vhosts[config.vhost_count++];
237 current->dir_count = 0;
238 current->mime_count = 0;
239 current->icon_count = 0;
240 current->index_count = 0;
241 current->readme_count = 0;
242 current->hideport = -1;
243 current->name = cm_strdup(vhost);
244 current->port = -1;
245 for(i = 0; vhost[i] != 0; i++) {
246 if(vhost[i] == ':') {
247 current->name[i] = 0;
248 current->port = atoi(current->name + i + 1);
249 break;
250 }
251 }
252 }
253 }
254 } else if(cm_strcaseequ(r[0], "EndVirtualHost")) {
255 if(vhost == NULL) {
256 cm_log("Config", "Not in virtual host section at line %d", ln);
257 stop = 1;
258 } else {
259 free(vhost);
260 vhost = NULL;
261 current = &config.root;
262 }
263 } else if(cm_strcaseequ(r[0], "Listen")
264#ifndef NO_SSL
265 || cm_strcaseequ(r[0], "ListenSSL")
266#endif
267 ) {
268 for(i = 1; r[i] != NULL; i++) {
269#ifdef _MSC_VER
270 uint32_t port = atoi(r[i]);
271#else
272 uint64_t port = atoi(r[i]);
273#endif
274 int j;
275 cm_log("Config", "Going to listen at port %d%s", (int)port, cm_strcaseequ(r[0], "ListenSSL") ? " with SSL" : "");
276#ifdef _MSC_VER
277 if(cm_strcaseequ(r[0], "ListenSSL")) port |= (1UL << 31);
278#else
279 if(cm_strcaseequ(r[0], "ListenSSL")) port |= (1ULL << 31);
280#endif
281 for(j = 0; config.ports[j] != -1; j++)
282 ;
283 config.ports[j] = port;
284 }
285 } else if(cm_strcaseequ(r[0], "HidePort")) {
286 current->hideport = 1;
287 } else if(cm_strcaseequ(r[0], "ShowPort")) {
288 current->hideport = 0;
289#ifndef NO_SSL
290 } else if(cm_strcaseequ(r[0], "SSLKey")) {
291 if(r[1] == NULL) {
292 cm_log("Config", "Missing path at line %d", ln);
293 stop = 1;
294 } else {
295 if(current->sslkey != NULL) free(current->sslkey);
296 current->sslkey = cm_strdup(r[1]);
297 }
298 } else if(cm_strcaseequ(r[0], "SSLCertificate")) {
299 if(r[1] == NULL) {
300 cm_log("Config", "Missing path at line %d", ln);
301 stop = 1;
302 } else {
303 if(current->sslcert != NULL) free(current->sslcert);
304 current->sslcert = cm_strdup(r[1]);
305 }
306#endif
307#ifdef HAS_CHROOT
308 } else if(cm_strcaseequ(r[0], "ChrootDirectory")) {
309 if(r[1] == NULL) {
310 cm_log("Config", "Missing path at line %d", ln);
311 stop = 1;
312 } else {
313 if(current->chroot_path != NULL) free(current->chroot_path);
314 current->chroot_path = cm_strdup(r[1]);
315 }
316#endif
317 } else if(cm_strcaseequ(r[0], "ForceLog")) {
318 if(r[1] == NULL) {
319 cm_log("Config", "Missing log at line %d", ln);
320 stop = 1;
321 } else {
322 cm_force_log(r[1]);
323 }
324 } else if(cm_strcaseequ(r[0], "EndIf")) {
325 if(ifbr == 0) {
326 cm_log("Config", "Missing BeginIf at line %d", ln);
327 stop = 1;
328 }
329 ifbr--;
330 } else if(cm_strcaseequ(r[0], "BeginIf") || cm_strcaseequ(r[0], "BeginIfNot")) {
331 if(r[1] == NULL) {
332 cm_log("Config", "Missing condition type at line %d", ln);
333 } else {
334 bool ign = false;
335 ifbr++;
336 if(cm_strcaseequ(r[1], "False")) {
337 ign = true;
338 } else if(cm_strcaseequ(r[1], "True")) {
339 } else if(cm_strcaseequ(r[1], "Defined")) {
340 if(r[2] == NULL) {
341 cm_log("Config", "Missing name at line %d", ln);
342 stop = 1;
343 } else {
344 int i;
345 bool fndit = false;
346 for(i = 0; config.defined[i] != NULL; i++) {
347 if(strcmp(config.defined[i], r[2]) == 0) {
348 fndit = true;
349 break;
350 }
351 }
352 if(!fndit) {
353 ign = true;
354 }
355 }
356 } else {
357 cm_log("Config", "Unknown condition type at line %d", ln);
358 stop = 1;
359 }
360 if(cm_strcaseequ(r[0], "BeginIfNot")) ign = !ign;
361 if(ign) {
362 ignore = ifbr - 1;
363 }
364 }
365 } else if(cm_strcaseequ(r[0], "ServerRoot")) {
366 if(r[1] == NULL) {
367 cm_log("Config", "Missing path at line %d", ln);
368 stop = 1;
369 } else {
370 chdir(r[1]);
371 free(config.server_root);
372 config.server_root = cm_strdup(r[1]);
373 }
374 } else if(cm_strcaseequ(r[0], "ServerAdmin")) {
375 if(r[1] == NULL) {
376 cm_log("Config", "Missing email at line %d", ln);
377 stop = 1;
378 } else {
379 free(config.server_admin);
380 config.server_admin = cm_strdup(r[1]);
381 }
382 } else if(cm_strcaseequ(r[0], "DocumentRoot")) {
383 if(r[1] == NULL) {
384 cm_log("Config", "Missing path at line %d", ln);
385 stop = 1;
386 } else {
387 if(current->root != NULL) free(current->root);
388 current->root = cm_strdup(strcmp(r[1], "/") == 0 ? "" : r[1]);
389 }
390 } else if(cm_strcaseequ(r[0], "MIMEType")) {
391 if(r[1] == NULL) {
392 cm_log("Config", "Missing extension at line %d", ln);
393 stop = 1;
394 } else if(r[2] == NULL) {
395 cm_log("Config", "Missing MIME at line %d", ln);
396 stop = 1;
397 } else {
398 struct tw_mime_entry* e = &current->mimes[current->mime_count++];
399 e->ext = cm_strdup(r[1]);
400 e->mime = cm_strdup(r[2]);
401 }
402 } else if(cm_strcaseequ(r[0], "Icon")) {
403 if(r[1] == NULL) {
404 cm_log("Config", "Missing MIME at line %d", ln);
405 stop = 1;
406 } else if(r[2] == NULL) {
407 cm_log("Config", "Missing path at line %d", ln);
408 stop = 1;
409 } else {
410 struct tw_icon_entry* e = &current->icons[current->icon_count++];
411 e->mime = cm_strdup(r[1]);
412 e->icon = cm_strdup(r[2]);
413 }
414 } else if(cm_strcaseequ(r[0], "LoadModule")) {
415 for(i = 1; r[i] != NULL; i++) {
416 void* mod = tw_module_load(r[i]);
417 if(mod != NULL) {
418 config.modules[config.module_count++] = mod;
419 if(tw_module_init(mod) != 0) {
420 stop = 1;
421 break;
422 }
423 } else {
424 cm_log("Config", "Could not load the module at line %d", ln);
425 stop = 1;
426 break;
427 }
428 }
429 } else if(cm_strcaseequ(r[0], "DirectoryIndex")) {
430 for(i = 1; r[i] != NULL; i++) {
431 current->indexes[current->index_count++] = cm_strdup(r[i]);
432 }
433 } else if(cm_strcaseequ(r[0], "ReadmeFile") || cm_strcaseequ(r[0], "Readme")) {
434 if(cm_strcaseequ(r[0], "Readme")) {
435 cm_force_log("NOTE: Readme directive is deprecated.");
436 }
437 for(i = 1; r[i] != NULL; i++) {
438 current->readmes[current->readme_count++] = cm_strdup(r[i]);
439 }
440 } else {
441 stop = 1;
442 if(r[0] != NULL) {
443 int argc;
444 int i;
445 bool called = false;
446 struct tw_tool tools;
447 for(argc = 0; r[argc] != NULL; argc++)
448 ;
449 stop = 0;
450 tw_init_tools(&tools);
451 for(i = 0; i < config.module_count; i++) {
452 tw_mod_config_t mod_config = (tw_mod_config_t)tw_module_symbol(config.modules[i], "mod_config");
453 int resp;
454 if(mod_config != NULL && (resp = mod_config(&tools, r, argc)) == TW_CONFIG_PARSED) {
455 called = true;
456 break;
457 }
458 if(resp == TW_CONFIG_ERROR) {
459 stop = 1;
460 called = true;
461 break;
462 }
463 }
464 if(!called) {
465 cm_log("Config", "Unknown directive `%s' at line %d", r[0], ln);
466 stop = 1;
467 }
468 }
469 }
470 for(i = 0; r[i] != NULL; i++) free(r[i]);
471 free(r);
472 }
473 free(l);
474 free(line);
475 line = malloc(1);
476 line[0] = 0;
477 if(c <= 0) break;
478 } else if(cbuf[0] != '\r') {
479 char* tmp = line;
480 line = cm_strcat(tmp, cbuf);
481 free(tmp);
482 }
483 }
484 free(line);
485 fclose(f);
486 return stop;
487 } else {
488 cm_log("Config", "Could not open the file");
489 return 1;
490 }
491}
Note: See TracBrowser for help on using the repository browser.