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

Last change on this file since 213 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
RevLine 
[4]1/* $Id: config.c 212 2024-10-02 17:44:55Z 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>
[212]12
13#ifndef _MSC_VER
[12]14#include <unistd.h>
[212]15#endif
[4]16
[212]17#if defined(__MINGW32__) || defined(_MSC_VER)
[20]18#include <winsock2.h>
19#endif
20
[4]21#include <cm_string.h>
22#include <cm_log.h>
23
[6]24struct tw_config config;
25
[12]26struct tw_config_entry* tw_vhost_match(const char* name, int port) {
27 int i;
28 for(i = 0; i < config.vhost_count; i++) {
[13]29 if(strcmp(config.vhosts[i].name, name) == 0 && (config.vhosts[i].port == -1 ? 1 : config.vhosts[i].port == port)) {
[12]30 return &config.vhosts[i];
31 }
32 }
33 return &config.root;
34}
35
[22]36bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost) {
[21]37 int i;
38 bool found = false;
39 bool pathstart = false;
40 bool perm = false;
41again:
[22]42 for(i = 0; i < vhost->dir_count; i++) {
[212]43 char* noslash;
[21]44 struct tw_dir_entry* e = &vhost->dirs[i];
45 pathstart = false;
[22]46 if(strlen(path) >= strlen(e->dir)) {
[212]47 int j;
[21]48 pathstart = true;
[22]49 for(j = 0; path[j] != 0 && e->dir[j] != 0; j++) {
50 if(path[j] != e->dir[j]) {
[21]51 pathstart = false;
52 break;
53 }
54 }
55 }
[212]56 noslash = cm_strdup(e->dir);
[21]57 noslash[strlen(noslash) - 1] = 0;
[22]58 if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart) {
[21]59 found = true;
[22]60 if(strcmp(e->name, "all") == 0) {
[21]61 perm = e->type == TW_DIR_ALLOW;
62 }
63 }
64 free(noslash);
65 }
[22]66 if(!found && vhost != &config.root) {
[21]67 vhost = &config.root;
68 goto again;
69 }
70 return perm;
71}
72
[7]73void tw_config_init(void) {
74 int i;
75 for(i = 0; i < MAX_PORTS + 1; i++) {
76 config.ports[i] = -1;
77 }
[12]78 for(i = 0; i < MAX_VHOSTS; i++) {
[156]79#ifndef NO_SSL
[12]80 config.vhosts[i].sslkey = NULL;
81 config.vhosts[i].sslcert = NULL;
[156]82#endif
[19]83 config.vhosts[i].root = NULL;
[156]84#ifdef HAS_CHROOT
85 config.vhosts[i].chroot_path = NULL;
86#endif
[12]87 }
[156]88#ifndef NO_SSL
[12]89 config.root.sslkey = NULL;
90 config.root.sslcert = NULL;
[156]91#endif
[19]92 config.root.root = NULL;
[21]93 config.root.mime_count = 0;
94 config.root.dir_count = 0;
[22]95 config.root.icon_count = 0;
[24]96 config.root.index_count = 0;
[33]97 config.root.readme_count = 0;
[123]98 config.root.hideport = 0;
[156]99#ifdef HAS_CHROOT
100 config.root.chroot_path = NULL;
101#endif
[12]102 config.vhost_count = 0;
[18]103 config.module_count = 0;
104 config.extension = NULL;
[17]105 config.server_root = cm_strdup(PREFIX);
[128]106 config.server_admin = cm_strdup(SERVER_ADMIN);
[156]107 config.defined[0] = NULL;
[187]108#if defined(_PSP)
[182]109 strcpy(config.hostname, "psp");
[187]110#elif defined(__PPU__)
111 strcpy(config.hostname, "ps3");
[189]112#elif defined(__ps2sdk__)
113 strcpy(config.hostname, "ps2");
[182]114#else
[12]115 gethostname(config.hostname, 1024);
[182]116#endif
[161]117#ifdef HAS_CHROOT
118 tw_add_define("HAS_CHROOT");
119#endif
[174]120#ifndef NO_SSL
121 tw_add_define("HAS_SSL");
122#endif
[7]123}
[6]124
125int tw_config_read(const char* path) {
[4]126 char cbuf[2];
[6]127 int ln = 0;
[156]128 int ifbr = 0;
129 int ignore = -1;
[212]130 FILE* f;
131 cm_log("Config", "Reading %s", path);
132 f = fopen(path, "r");
133 cbuf[1] = 0;
[6]134 if(f != NULL) {
[4]135 char* line = malloc(1);
[6]136 int stop = 0;
[12]137 struct tw_config_entry* current = &config.root;
[6]138 char* vhost = NULL;
[21]139 char* dir = NULL;
[212]140 line[0] = 0;
[6]141 while(stop == 0) {
[4]142 int c = fread(cbuf, 1, 1, f);
[6]143 if(cbuf[0] == '\n' || c <= 0) {
[212]144 char* l = cm_trim(line);
[6]145 ln++;
146 if(strlen(l) > 0 && l[0] != '#') {
[5]147 char** r = cm_split(l, " \t");
148 int i;
[156]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")) {
[6]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;
[5]159 }
160 }
[156]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 }
[21]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 }
[6]225 } else if(cm_strcaseequ(r[0], "BeginVirtualHost")) {
226 if(vhost != NULL) {
[12]227 cm_log("Config", "Already in virtual host section at line %d", ln);
[6]228 stop = 1;
229 } else {
230 if(r[1] == NULL) {
[12]231 cm_log("Config", "Missing virtual host at line %d", ln);
[6]232 stop = 1;
233 } else {
[212]234 int i;
[6]235 vhost = cm_strdup(r[1]);
[12]236 current = &config.vhosts[config.vhost_count++];
[21]237 current->dir_count = 0;
238 current->mime_count = 0;
[22]239 current->icon_count = 0;
[24]240 current->index_count = 0;
[33]241 current->readme_count = 0;
[123]242 current->hideport = -1;
[12]243 current->name = cm_strdup(vhost);
[13]244 current->port = -1;
[12]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 }
[6]252 }
253 }
254 } else if(cm_strcaseequ(r[0], "EndVirtualHost")) {
255 if(vhost == NULL) {
[12]256 cm_log("Config", "Not in virtual host section at line %d", ln);
[6]257 stop = 1;
258 } else {
259 free(vhost);
260 vhost = NULL;
[12]261 current = &config.root;
[6]262 }
[174]263 } else if(cm_strcaseequ(r[0], "Listen")
264#ifndef NO_SSL
265 || cm_strcaseequ(r[0], "ListenSSL")
266#endif
267 ) {
[7]268 for(i = 1; r[i] != NULL; i++) {
[212]269#ifdef _MSC_VER
270 uint32_t port = atoi(r[i]);
271#else
[7]272 uint64_t port = atoi(r[i]);
[212]273#endif
274 int j;
[7]275 cm_log("Config", "Going to listen at port %d%s", (int)port, cm_strcaseequ(r[0], "ListenSSL") ? " with SSL" : "");
[212]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
[7]281 for(j = 0; config.ports[j] != -1; j++)
282 ;
283 config.ports[j] = port;
284 }
[123]285 } else if(cm_strcaseequ(r[0], "HidePort")) {
286 current->hideport = 1;
287 } else if(cm_strcaseequ(r[0], "ShowPort")) {
288 current->hideport = 0;
[156]289#ifndef NO_SSL
[12]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 }
[156]306#endif
[161]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
[156]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 {
[212]334 bool ign = false;
[156]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 }
[61]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]);
[127]371 free(config.server_root);
372 config.server_root = cm_strdup(r[1]);
[61]373 }
[128]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 }
[19]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);
[21]388 current->root = cm_strdup(strcmp(r[1], "/") == 0 ? "" : r[1]);
[19]389 }
[21]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;
[22]394 } else if(r[2] == NULL) {
[21]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 }
[22]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 }
[17]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) {
[18]418 config.modules[config.module_count++] = mod;
[17]419 if(tw_module_init(mod) != 0) {
420 stop = 1;
421 break;
422 }
423 } else {
[127]424 cm_log("Config", "Could not load the module at line %d", ln);
[17]425 stop = 1;
426 break;
427 }
428 }
[24]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 }
[178]433 } else if(cm_strcaseequ(r[0], "ReadmeFile") || cm_strcaseequ(r[0], "Readme")) {
[182]434 if(cm_strcaseequ(r[0], "Readme")) {
[178]435 cm_force_log("NOTE: Readme directive is deprecated.");
436 }
[33]437 for(i = 1; r[i] != NULL; i++) {
438 current->readmes[current->readme_count++] = cm_strdup(r[i]);
439 }
[6]440 } else {
[39]441 stop = 1;
[6]442 if(r[0] != NULL) {
[39]443 int argc;
[212]444 int i;
445 bool called = false;
446 struct tw_tool tools;
[39]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 }
[6]468 }
[5]469 }
470 for(i = 0; r[i] != NULL; i++) free(r[i]);
471 free(r);
[4]472 }
473 free(l);
474 free(line);
475 line = malloc(1);
476 line[0] = 0;
477 if(c <= 0) break;
[6]478 } else if(cbuf[0] != '\r') {
[4]479 char* tmp = line;
480 line = cm_strcat(tmp, cbuf);
481 free(tmp);
482 }
483 }
484 free(line);
485 fclose(f);
[6]486 return stop;
487 } else {
[5]488 cm_log("Config", "Could not open the file");
[4]489 return 1;
490 }
491}
Note: See TracBrowser for help on using the repository browser.