]> code.citadel.org Git - citadel.git/blob - citadel/server/netconfig.c
Define the citserver BUILD_ID as a five digit number consisting of the two digit...
[citadel.git] / citadel / server / netconfig.c
1 // This module handles loading, saving, and parsing of room network configurations.
2 //
3 // Copyright (c) 2000-2022 by the citadel.org team
4 //
5 // This program is open source software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License, version 3.
7
8 #include "sysdep.h"
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <dirent.h>
12
13 #ifdef HAVE_SYSCALL_H
14 # include <syscall.h>
15 #else 
16 # if HAVE_SYS_SYSCALL_H
17 #  include <sys/syscall.h>
18 # endif
19 #endif
20 #include <dirent.h>
21 #include <assert.h>
22 #include <libcitadel.h>
23 #include "ctdl_module.h"
24 #include "serv_extensions.h"
25 #include "config.h"
26
27
28 // Create a config key for a room's netconfig entry
29 void netcfg_keyname(char *keybuf, long roomnum) {
30         if (!keybuf) return;
31         sprintf(keybuf, "c_netconfig_%010ld", roomnum);
32 }
33
34
35 // Given a room number and a textual netconfig, convert to base64 and write to the configdb
36 void SaveRoomNetConfigFile(long roomnum, const char *raw_netconfig) {
37         char keyname[25];
38         char *enc;
39         int enc_len;
40         int len;
41
42         len = strlen(raw_netconfig);
43         netcfg_keyname(keyname, roomnum);
44         enc = malloc(len * 2);
45
46         if (enc) {
47                 enc_len = CtdlEncodeBase64(enc, raw_netconfig, len, BASE64_NO_LINEBREAKS);
48                 if ((enc_len > 1) && (enc[enc_len-2] == 13)) enc[enc_len-2] = 0;
49                 if ((enc_len > 0) && (enc[enc_len-1] == 10)) enc[enc_len-1] = 0;
50                 enc[enc_len] = 0;
51                 syslog(LOG_DEBUG, "netconfig: writing key '%s' (length=%d)", keyname, enc_len);
52                 CtdlSetConfigStr(keyname, enc);
53                 free(enc);
54         }
55 }
56
57
58 // Given a room number, attempt to load the netconfig configdb entry for that room.
59 // If it returns NULL, there is no netconfig.
60 // Otherwise the caller owns the returned memory and is responsible for freeing it.
61 char *LoadRoomNetConfigFile(long roomnum) {
62         char keyname[25];
63         char *encoded_netconfig = NULL;
64         char *decoded_netconfig = NULL;
65
66         netcfg_keyname(keyname, roomnum);
67         encoded_netconfig = CtdlGetConfigStr(keyname);
68         if (!encoded_netconfig) return NULL;
69
70         decoded_netconfig = malloc(strlen(encoded_netconfig));  // yeah, way bigger than it needs to be, but safe
71         CtdlDecodeBase64(decoded_netconfig, encoded_netconfig, strlen(encoded_netconfig));
72         return decoded_netconfig;
73 }
74
75
76 //-----------------------------------------------------------------------------
77 //              Per room network configs : exchange with client                
78 //-----------------------------------------------------------------------------
79 void cmd_gnet(char *argbuf) {
80         if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) {
81                 // users can edit the netconfigs for their own mailbox rooms
82         }
83         else if (CtdlAccessCheck(ac_room_aide)) return;
84         
85         cprintf("%d Network settings for room #%ld <%s>\n", LISTING_FOLLOWS, CC->room.QRnumber, CC->room.QRname);
86
87         char *c = LoadRoomNetConfigFile(CC->room.QRnumber);
88         if (c) {
89                 int len = strlen(c);
90                 client_write(c, len);                   // Can't use cprintf() here, it has a limit of 1024 bytes
91                 if (c[len] != '\n') {
92                         client_write(HKEY("\n"));
93                 }
94                 free(c);
95         }
96         cprintf("000\n");
97 }
98
99
100 void cmd_snet(char *argbuf) {
101         StrBuf *Line = NULL;
102         StrBuf *TheConfig = NULL;
103         int rc;
104
105         unbuffer_output();
106         Line = NewStrBuf();
107         TheConfig = NewStrBuf();
108         cprintf("%d send new netconfig now\n", SEND_LISTING);
109
110         while (rc = CtdlClientGetLine(Line), (rc >= 0)) {
111                 if ((rc == 3) && (strcmp(ChrPtr(Line), "000") == 0))
112                         break;
113
114                 StrBufAppendBuf(TheConfig, Line, 0);
115                 StrBufAppendBufPlain(TheConfig, HKEY("\n"), 0);
116         }
117         FreeStrBuf(&Line);
118
119         begin_critical_section(S_NETCONFIGS);
120         SaveRoomNetConfigFile(CC->room.QRnumber, ChrPtr(TheConfig));
121         end_critical_section(S_NETCONFIGS);
122         FreeStrBuf(&TheConfig);
123 }
124
125
126 // Convert any legacy configuration files in the "netconfigs" directory
127 void convert_legacy_netcfg_files(void) {
128         DIR *dh = NULL;
129         struct dirent *dit = NULL;
130         char filename[PATH_MAX];
131         long roomnum;
132         FILE *fp;
133         long len;
134         char *v;
135
136         dh = opendir(ctdl_netcfg_dir);
137         if (!dh) return;
138
139         syslog(LOG_INFO, "netconfig: legacy netconfig files exist - converting them!");
140
141         while (dit = readdir(dh), dit != NULL) {        // yes, we use the non-reentrant version; we're not in threaded mode yet
142                 roomnum = atol(dit->d_name);
143                 if (roomnum > 0) {
144                         snprintf(filename, sizeof filename, "%s/%ld", ctdl_netcfg_dir, roomnum);
145                         fp = fopen(filename, "r");
146                         if (fp) {
147                                 fseek(fp, 0L, SEEK_END);
148                                 len = ftell(fp);
149                                 if (len > 0) {
150                                         v = malloc(len);
151                                         if (v) {
152                                                 rewind(fp);
153                                                 if (fread(v, len, 1, fp)) {
154                                                         SaveRoomNetConfigFile(roomnum, v);
155                                                         unlink(filename);
156                                                 }
157                                                 free(v);
158                                         }
159                                 }
160                                 else {
161                                         unlink(filename);       // zero length netconfig, just delete it
162                                 }
163                                 fclose(fp);
164                         }
165                 }
166         }
167
168         closedir(dh);
169         rmdir(ctdl_netcfg_dir);
170 }
171
172
173 /*
174  * Module entry point
175  */
176 char *ctdl_module_init_netconfig(void) {
177         if (!threading) {
178                 convert_legacy_netcfg_files();
179                 CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
180                 CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");
181         }
182         return "netconfig";
183 }