1 // This module handles loading, saving, and parsing of room network configurations.
3 // Copyright (c) 2000-2022 by the citadel.org team
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.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
15 #include <sys/types.h>
21 # if HAVE_SYS_SYSCALL_H
22 # include <sys/syscall.h>
27 #include <libcitadel.h>
28 #include "ctdl_module.h"
29 #include "serv_extensions.h"
33 // Create a config key for a room's netconfig entry
34 void netcfg_keyname(char *keybuf, long roomnum) {
36 sprintf(keybuf, "c_netconfig_%010ld", roomnum);
40 // Given a room number and a textual netconfig, convert to base64 and write to the configdb
41 void SaveRoomNetConfigFile(long roomnum, const char *raw_netconfig) {
47 len = strlen(raw_netconfig);
48 netcfg_keyname(keyname, roomnum);
49 enc = malloc(len * 2);
52 enc_len = CtdlEncodeBase64(enc, raw_netconfig, len, BASE64_NO_LINEBREAKS);
53 if ((enc_len > 1) && (enc[enc_len-2] == 13)) enc[enc_len-2] = 0;
54 if ((enc_len > 0) && (enc[enc_len-1] == 10)) enc[enc_len-1] = 0;
56 syslog(LOG_DEBUG, "netconfig: writing key '%s' (length=%d)", keyname, enc_len);
57 CtdlSetConfigStr(keyname, enc);
63 // Given a room number, attempt to load the netconfig configdb entry for that room.
64 // If it returns NULL, there is no netconfig.
65 // Otherwise the caller owns the returned memory and is responsible for freeing it.
66 char *LoadRoomNetConfigFile(long roomnum) {
68 char *encoded_netconfig = NULL;
69 char *decoded_netconfig = NULL;
71 netcfg_keyname(keyname, roomnum);
72 encoded_netconfig = CtdlGetConfigStr(keyname);
73 if (!encoded_netconfig) return NULL;
75 decoded_netconfig = malloc(strlen(encoded_netconfig)); // yeah, way bigger than it needs to be, but safe
76 CtdlDecodeBase64(decoded_netconfig, encoded_netconfig, strlen(encoded_netconfig));
77 return decoded_netconfig;
81 //-----------------------------------------------------------------------------
82 // Per room network configs : exchange with client
83 //-----------------------------------------------------------------------------
84 void cmd_gnet(char *argbuf) {
85 if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) {
86 // users can edit the netconfigs for their own mailbox rooms
88 else if (CtdlAccessCheck(ac_room_aide)) return;
90 cprintf("%d Network settings for room #%ld <%s>\n", LISTING_FOLLOWS, CC->room.QRnumber, CC->room.QRname);
92 char *c = LoadRoomNetConfigFile(CC->room.QRnumber);
95 client_write(c, len); // Can't use cprintf() here, it has a limit of 1024 bytes
97 client_write(HKEY("\n"));
105 void cmd_snet(char *argbuf) {
107 StrBuf *TheConfig = NULL;
112 TheConfig = NewStrBuf();
113 cprintf("%d send new netconfig now\n", SEND_LISTING);
115 while (rc = CtdlClientGetLine(Line), (rc >= 0)) {
116 if ((rc == 3) && (strcmp(ChrPtr(Line), "000") == 0))
119 StrBufAppendBuf(TheConfig, Line, 0);
120 StrBufAppendBufPlain(TheConfig, HKEY("\n"), 0);
124 begin_critical_section(S_NETCONFIGS);
125 SaveRoomNetConfigFile(CC->room.QRnumber, ChrPtr(TheConfig));
126 end_critical_section(S_NETCONFIGS);
127 FreeStrBuf(&TheConfig);
131 // Convert any legacy configuration files in the "netconfigs" directory
132 void convert_legacy_netcfg_files(void) {
134 struct dirent *dit = NULL;
135 char filename[PATH_MAX];
141 dh = opendir(ctdl_netcfg_dir);
144 syslog(LOG_INFO, "netconfig: legacy netconfig files exist - converting them!");
146 while (dit = readdir(dh), dit != NULL) { // yes, we use the non-reentrant version; we're not in threaded mode yet
147 roomnum = atol(dit->d_name);
149 snprintf(filename, sizeof filename, "%s/%ld", ctdl_netcfg_dir, roomnum);
150 fp = fopen(filename, "r");
152 fseek(fp, 0L, SEEK_END);
158 if (fread(v, len, 1, fp)) {
159 SaveRoomNetConfigFile(roomnum, v);
166 unlink(filename); // zero length netconfig, just delete it
174 rmdir(ctdl_netcfg_dir);
181 char *ctdl_module_init_netconfig(void) {
183 convert_legacy_netcfg_files();
184 CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
185 CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");