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

Last change on this file since 349 was 349, checked in by Nishi, on Oct 16, 2024 at 5:08:08 AM

fix some stuff

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