source: Main/trunk/Server/config.c

Last change on this file was 402, checked in by Nishi, on Nov 3, 2024 at 7:39:59 PM

amiga

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