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

Last change on this file since 400 was 400, checked in by Nishi, on Nov 3, 2024 at 2:19:42 PM

a

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