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

Last change on this file since 205 was 189, checked in by Nishi, on Sep 29, 2024 at 9:37:00 AM

will try to fix ps2 later

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