-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathugopherserver.h
More file actions
455 lines (380 loc) · 11 KB
/
Copy pathugopherserver.h
File metadata and controls
455 lines (380 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
/*
* Gophernicus - Copyright (c) 2009-2014 Kim Holviala <kim@holviala.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GOPHERNICUS_H
#define _GOPHERNICUS_H
/*
* Features
*/
#undef ENABLE_STRICT_RFC1436 /* Follow RFC1436 to the letter */
#undef ENABLE_AUTOHIDING /* Hide manually listed resources from generated menus */
/*
* Platform configuration
*/
/* Defaults should fit standard POSIX systems */
#define HAVE_IPv4 /* IPv4 should work anywhere */
#define HAVE_IPv6 /* Requires modern POSIX */
#define HAVE_PASSWD /* For systems with passwd-like userdb */
#define PASSWD_MIN_UID 100 /* Minimum allowed UID for ~userdirs */
#define HAVE_LOCALES /* setlocale() and friends */
#define HAVE_SHMEM /* Shared memory support */
#define HAVE_UNAME /* uname() */
#define HAVE_POPEN /* popen() */
#undef HAVE_STRLCPY /* strlcpy() from OpenBSD */
#undef HAVE_SENDFILE /* sendfile() in Linux & others */
/* Linux */
#ifdef __linux
#undef PASSWD_MIN_UID
#define PASSWD_MIN_UID 500
#define HAVE_SENDFILE
#endif
/* Embedded Linux with uClibc */
#ifdef __UCLIBC__
#undef HAVE_SHMEM
#undef HAVE_PASSWD
#endif
/* Haiku */
#ifdef __HAIKU__
#undef HAVE_SHMEM
#undef HAVE_PASSWD
#endif
/* OpenBSD */
#ifdef __OpenBSD__
#define HAVE_STRLCPY
#endif
/* MacOS */
#if defined(__APPLE__)
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10
#define HAVE_STRLCPY
#endif
#endif
/* Add other OS-specific defines here */
/*
* Include headers
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <libgen.h>
#include <time.h>
#include <syslog.h>
#include <errno.h>
#include <pwd.h>
#include <limits.h>
#ifdef HAVE_SENDFILE
#include <sys/sendfile.h>
#include <fcntl.h>
#endif
#ifdef HAVE_LOCALES
#include <locale.h>
#endif
#ifdef HAVE_SHMEM
#include <sys/ipc.h>
#include <sys/shm.h>
#else
#define shm_state void
#endif
#if defined(HAVE_IPv4) || defined(HAVE_IPv6)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif
#if !defined(HAVE_STRLCPY)
size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz);
#endif
/*
* Compile-time configuration
*/
/* Common stuff */
#define CRLF "\r\n"
#define EMPTY ""
#define PARENT ".."
#define ROOT "/"
#define FALSE 0
#define TRUE 1
#define QUIT 1
#define OK 0
#define ERROR -1
#define MATCH 0
/* Gopher filetypes */
#define TYPE_TEXT '0'
#define TYPE_MENU '1'
#define TYPE_ERROR '3'
#define TYPE_GZIP '5'
#define TYPE_QUERY '7'
#define TYPE_BINARY '9'
#define TYPE_GIF 'g'
#define TYPE_HTML 'h'
#define TYPE_INFO 'i'
#define TYPE_IMAGE 'I'
#define TYPE_MIME 'M'
#define TYPE_DOC 'd'
#define TYPE_TITLE '!'
/* Protocols */
#define PROTO_GOPHER 'g'
#define PROTO_HTTP 'h'
/* Charsets */
#define AUTO 0
#define US_ASCII 1
#define ISO_8859_1 2
#define UTF_8 3
/* HTTP protocol stuff for logging */
#define HTTP_OK 200
#define HTTP_404 404
#define HTTP_DATE "%d/%b/%Y:%T %z"
#define HTTP_USERAGENT "Unknown gopher client"
/* Defaults for settings */
#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT 70
#define DEFAULT_TYPE TYPE_TEXT
#define DEFAULT_MAP "gophermap"
#define DEFAULT_TAG "gophertag"
#define DEFAULT_HDR_EXT "Ghdr"
#define DEFAULT_TAG_EXT "Gtag"
#define DEFAULT_FTR_EXT "Gftr"
#define DEFAULT_GPH_EXT "gph"
#define DEFAULT_GMP_EXT "gmp"
#define DEFAULT_SSL_CKF "/m"
#define DEFAULT_CIPHERS "HIGH:DEFAULT:!aNULL:!PSK:!SRP:!MD5:!RC4:!EXP"
#define DEFAULT_CGI "/cgi-bin/"
#define DEFAULT_USERDIR "public_gopher"
#define DEFAULT_ADDR "unknown"
#define DEFAULT_WIDTH 70
#define DEFAULT_CHARSET US_ASCII
#define MIN_WIDTH 33
#define MAX_WIDTH 600
/* Session defaults */
#define DEFAULT_SESSION_TIMEOUT 1800
#define DEFAULT_SESSION_MAX_KBYTES 4194304
#define DEFAULT_SESSION_MAX_HITS 4096
/* Dummy values for gopher protocol */
#define DUMMY_SELECTOR "null"
#define DUMMY_HOST "null.host\t1"
/* Safe $PATH for exec() */
#ifdef __HAIKU__
#define SAFE_PATH "/boot/common/bin:/bin"
#else
#define SAFE_PATH "/opt/local/bin:/usr/local/bin:/usr/bin:/bin"
#endif
/* Special requests */
#define SERVER_STATUS "/server-status"
#define CAPS_TXT "/caps.txt"
/* Error messages */
#define ERR_ACCESS "Access denied!"
#define ERR_NOTFOUND "File or directory not found!"
#define ERROR_HOST "error.host\t1"
#define ERROR_PREFIX "Error: "
/* Strings */
#define SERVER_SOFTWARE "uGopherServer"
#define SERVER_SOFTWARE_FULL SERVER_SOFTWARE "-" VERSION
#define HEADER_FORMAT "[%s]"
#define FOOTER_FORMAT "Ecstatically rendered by UniversalGopherServer " VERSION " on %s"
#define UNITS "KB", "MB", "GB", "TB", "PB", NULL
#define DATE_FORMAT "%Y-%b-%d %H:%M" /* See man 3 strftime */
#define DATE_WIDTH 17
#define DATE_LOCALE "POSIX"
#define USERDIR_FORMAT "~%s", pwd->pw_name /* See man 3 getpwent */
#define VHOST_FORMAT "gopher://%s/"
/* ISO-8859-1 to US-ASCII look-alike conversion table */
#define ASCII \
"E?,f..++^%S<??Z?" \
"?''\"\"*--~?s>??zY" \
" !c_*Y|$\"C?<?-R-" \
"??23'u?*,1?>????" \
"AAAAAAACEEEEIIII" \
"DNOOOOO*OUUUUYTB" \
"aaaaaaaceeeeiiii" \
"dnooooo/ouuuuyty"
#define UNKNOWN '?'
/* Sizes & maximums */
#define BUFSIZE (4*1024) /* Default size for string buffers */
#define MAX_HIDDEN 32 /* Maximum number of hidden files */
#define MAX_FILETYPES 128 /* Maximum number of suffix to filetype mappings */
#define MAX_FILTERS 64 /* Maximum number of file filters */
#define MAX_SDIRENT 1024 /* Maximum number of files per directory to handle */
#define MAX_REWRITE 32 /* Maximum number of selector rewrite options */
// using one buffer now
extern char sockbuf[BUFSIZE*4];
/* Struct for file suffix -> gopher filetype mapping */
typedef struct {
char suffix[15];
char type;
} ftype;
/* Struct for selector rewriting */
typedef struct {
char match[BUFSIZE];
char replace[BUFSIZE];
} srewrite;
/* Struct for keeping the current options & state */
typedef struct {
void *sslh;
void *sslctx;
int rfd;
int wfd;
} sockstate;
typedef struct {
/* Request */
char req_selector[BUFSIZE];
char req_realpath[BUFSIZE*6];
char req_query_string[BUFSIZE];
char req_referrer[BUFSIZE];
char protection_certkeyfile[BUFSIZE];
char protection_cipherlist[BUFSIZE];
char req_local_addr[64];
char req_remote_addr[64];
char req_filetype;
char req_protocol;
off_t req_filesize;
uid_t drop_uid;
gid_t drop_gid;
/* Output */
int out_width;
int out_charset;
int out_protection;
/* Settings */
char server_description[64];
char server_location[64];
char server_platform[64];
char server_admin[64];
char server_root[256];
char server_host_default[64];
char server_host[64];
int server_port;
char default_filetype;
char map_file[64];
char tag_file[64];
char hdr_ext[64];
char tag_ext[64];
char ftr_ext[64];
char cgi_file[64];
char user_dir[64];
char log_file[256];
char hidden[MAX_HIDDEN][256];
int hidden_count;
ftype filetype[MAX_FILETYPES];
int filetype_count;
char filter_dir[64];
srewrite rewrite[MAX_REWRITE];
int rewrite_count;
/* Session */
int session_timeout;
int session_max_kbytes;
int session_max_hits;
int (*read)(void *, char *, size_t);
int (*write)(void *, const char *, size_t);
char *(*fgets)(char *, size_t, void *);
/* Feature options */
char opt_parent;
char opt_header;
char opt_footer;
char opt_date;
char opt_syslog;
char opt_magic;
char opt_iconv;
char opt_vhost;
char opt_query;
char opt_caps;
char opt_shm;
char opt_root;
char debug;
/* Preparing for future evented version of Gophernicus+Aster,
* socket state. Also used for SSL support, where available */
sockstate ss;
} state;
/* Shared memory for session & accounting data */
#ifdef HAVE_SHMEM
#define SHM_KEY 0xbeeb0006 /* Unique identifier + struct version */
#define SHM_MODE 0600 /* Access mode for the shared memory */
#define SHM_SESSIONS 256 /* Max amount of user sessions to track */
typedef struct {
long hits;
long kbytes;
time_t req_atime;
char req_selector[128];
char req_remote_addr[64];
char req_filetype;
char server_host[64];
int server_port;
} shm_session;
typedef struct {
time_t start_time;
long hits;
long kbytes;
char server_platform[64];
char server_description[64];
shm_session session[SHM_SESSIONS];
} shm_state;
#endif
/* Struct for directory sorting */
typedef struct {
char name[128]; /* Should be 256 but we're saving stack space */
mode_t mode;
uid_t uid;
gid_t gid;
off_t size;
time_t mtime;
} sdirent;
/* File suffix to gopher filetype mappings */
#define FILETYPES \
"txt","0","pl","0","py","0","sh","0","tcl","0","c","0","cpp","0", "h","0","log","0", \
"conf","0","php","0","php3","0", \
"map","1","menu","1", \
"hqx","4", \
"Z","5","gz","5","tgz","5","tar","5","zip","5","bz2","5","rar","5","sea","5", \
"q","7","qry","7", \
"iso","9","so","9","o","9","rtf","9","ttf","9","bin","9", \
"ics","c","ical","c", \
"gif","g", \
"html","h","htm","h","xhtml","h","css","h","swf","h","rdf","h","rss","h","xml","h", \
"jpg","I","jpeg","I","png","I","bmp","I","svg","I","tif","I","tiff","I", \
"ico","I","xbm","I","xpm","I","pcx","I", \
"mbox","M", \
"pdf","d","ps","d","doc","d","ppt","d","xls","d","xlsx","d","docx","d","pptx","d", \
"mp3","s","wav","s","mid","s","wma","s","flac","s","ogg","s","aiff","s","aac","s", \
"avi",";","mp4",";","mpg",";","mov",";","qt",";","asf",";","mpv",";","m4v",";", \
NULL, NULL
/*
* Useful macros
*/
#define strclear(str) str[0] = '\0';
#define sstrlcpy(dest, src) strlcpy(dest, src, sizeof(dest))
#define sstrlcat(dest, src) strlcat(dest, src, sizeof(dest))
#define sstrncmp(s1, s2) strncmp(s1, s2, sizeof(s2) - 1)
#define sstrncasecmp(s1, s2) strncasecmp(s1, s2, sizeof(s2) - 1)
#define sstrniconv(charset, out, in) strniconv(charset, out, in, sizeof(out))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
/*
* Include generated headers
*/
#include "functions.h"
#include "files.h"
#endif