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

Last change on this file since 311 was 311, checked in by Nishi, on Oct 13, 2024 at 10:23:22 AM

attempting to add os/2

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