2 * Configuration screens that are part of the text mode client.
4 * Copyright (c) 1987-2014 by the citadel.org team
6 * This program is open source software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
17 #include <sys/types.h>
25 #if TIME_WITH_SYS_TIME
26 # include <sys/time.h>
30 # include <sys/time.h>
40 #include <libcitadel.h>
42 ///#include "citadel.h"
43 #include "citadel_ipc.h"
44 #include "citadel_decls.h"
45 #include "tuiconfig.h"
49 ///#ifndef HAVE_SNPRINTF
50 ///#include "snprintf.h"
54 /* work around solaris include files */
60 extern char tempdir[];
61 extern char *axdefs[8];
62 extern long highest_msg_read;
63 extern long maxmsgnum;
64 extern unsigned room_flags;
65 extern int screenwidth;
66 char editor_path[PATH_MAX];
70 * General system configuration command
72 void do_system_configuration(CtdlIPC *ipc)
75 /* NUM_CONFIGS is now defined in citadel.h */
78 char sc[NUM_CONFIGS][256];
80 struct ExpirePolicy *site_expirepolicy = NULL;
81 struct ExpirePolicy *mbx_expirepolicy = NULL;
84 int r; /* IPC response code */
85 int server_configs = 0;
87 /* Clear out the config buffers */
88 memset(&sc[0][0], 0, sizeof(sc));
90 /* Fetch the current config */
91 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
93 server_configs = num_tokens(resp, '\n');
94 for (a=0; a<server_configs; ++a) {
95 if (a < NUM_CONFIGS) {
96 extract_token(&sc[a][0], resp, a, '\n', sizeof sc[a]);
100 if (resp) free(resp);
102 /* Fetch the expire policy (this will silently fail on old servers,
103 * resulting in "default" policy)
105 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
106 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
108 /* Identification parameters */
110 strprompt("Node name", &sc[0][0], 15);
111 strprompt("Fully qualified domain name", &sc[1][0], 63);
112 strprompt("Human readable node name", &sc[2][0], 20);
113 strprompt("Telephone number", &sc[3][0], 15);
114 strprompt("Geographic location of this system", &sc[12][0], 31);
115 strprompt("Name of system administrator", &sc[13][0], 25);
116 strprompt("Paginator prompt", &sc[10][0], 79);
118 /* Security parameters */
120 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt("Require registration for new users", atoi(&sc[7][0]))));
121 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt("Disable self-service user account creation", atoi(&sc[29][0]))));
122 strprompt("Initial access level for new users", &sc[6][0], 1);
123 strprompt("Access level required to create rooms", &sc[19][0], 1);
124 snprintf(sc[67], sizeof sc[67], "%d", (boolprompt("Allow anonymous guest logins", atoi(&sc[67][0]))));
125 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
126 "Automatically give room admin privs to a user who creates a private room",
129 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
130 "Automatically move problem user messages to twit room",
133 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
134 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
135 "Restrict Internet mail to only those with that privilege",
137 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
138 "Allow admins to Zap (forget) rooms",
141 if (!IsEmptyStr(&sc[18][0])) {
147 logpages = boolprompt("Log all instant messages", logpages);
149 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
155 /* Commented out because this setting isn't really appropriate to
156 * change while the server is running.
158 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
159 * "Use system authentication",
160 * atoi(&sc[52][0]))));
165 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
166 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
167 strprompt("Maximum message length", &sc[20][0], 20);
168 strprompt("Minimum number of worker threads", &sc[21][0], 3);
169 strprompt("Maximum number of worker threads", &sc[22][0], 3);
170 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
171 "Automatically delete committed database logs",
174 strprompt("Server IP address (* for 'any')", &sc[37][0], 15);
175 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
176 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
177 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
178 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
179 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
180 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
181 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
182 strprompt("NNTP server port (-1 to disable)", &sc[70][0], 5);
183 strprompt("NNTPS server port (-1 to disable)", &sc[71][0], 5);
184 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
185 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
187 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc[62][0], 5);
188 /* No prompt because we don't implement this service yet, it's just a placeholder */
189 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
191 /* This logic flips the question around, because it's one of those
192 * situations where 0=yes and 1=no
196 a = boolprompt("Correct forged From: lines during authenticated SMTP", a);
198 snprintf(sc[25], sizeof sc[25], "%d", a);
200 snprintf(sc[66], sizeof sc[66], "%d", (boolprompt(
201 "Flag messages as spam instead of rejecting",
204 /* This logic flips the question around, because it's one of those
205 * situations where 0=yes and 1=no
209 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
211 snprintf(sc[61], sizeof sc[61], "%d", a);
213 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
214 "Allow unauthenticated SMTP clients to spoof my domains",
216 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
217 "Perform RBL checks at greeting instead of after RCPT",
221 if (ipc->ServInfo.supports_ldap) {
222 a = strlen(&sc[32][0]);
223 a = (a ? 1 : 0); /* Set only to 1 or 0 */
224 a = boolprompt("Do you want to configure LDAP authentication?", a);
226 strprompt("Host name of LDAP server", &sc[32][0], 127);
227 strprompt("Port number of LDAP service", &sc[33][0], 5);
228 strprompt("Base DN", &sc[34][0], 255);
229 strprompt("Bind DN (or blank for anonymous bind)", &sc[35][0], 255);
230 strprompt("Password for bind DN (or blank for anonymous bind)", &sc[36][0], 255);
233 strcpy(&sc[32][0], "");
237 /* Expiry settings */
238 strprompt("Default user purge time (days)", &sc[16][0], 5);
239 strprompt("Default room purge time (days)", &sc[17][0], 5);
241 /* Angels and demons dancing in my head... */
243 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_mode);
244 strprompt("System default message expire policy (? for list)",
248 "1. Never automatically expire messages\n"
249 "2. Expire by message count\n"
250 "3. Expire by message age\n");
252 } while ((buf[0] < '1') || (buf[0] > '3'));
253 site_expirepolicy->expire_mode = buf[0] - '0';
255 /* ...lunatics and monsters underneath my bed */
256 if (site_expirepolicy->expire_mode == 2) {
257 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
258 strprompt("Keep how many messages online?", buf, 10);
259 site_expirepolicy->expire_value = atol(buf);
261 if (site_expirepolicy->expire_mode == 3) {
262 snprintf(buf, sizeof buf, "%d", site_expirepolicy->expire_value);
263 strprompt("Keep messages for how many days?", buf, 10);
264 site_expirepolicy->expire_value = atol(buf);
267 /* Media messiahs preying on my fears... */
269 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_mode);
270 strprompt("Mailbox default message expire policy (? for list)",
274 "0. Go with the system default\n"
275 "1. Never automatically expire messages\n"
276 "2. Expire by message count\n"
277 "3. Expire by message age\n");
279 } while ((buf[0] < '0') || (buf[0] > '3'));
280 mbx_expirepolicy->expire_mode = buf[0] - '0';
282 /* ...Pop culture prophets playing in my ears */
283 if (mbx_expirepolicy->expire_mode == 2) {
284 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
285 strprompt("Keep how many messages online?", buf, 10);
286 mbx_expirepolicy->expire_value = atol(buf);
288 if (mbx_expirepolicy->expire_mode == 3) {
289 snprintf(buf, sizeof buf, "%d", mbx_expirepolicy->expire_value);
290 strprompt("Keep messages for how many days?", buf, 10);
291 mbx_expirepolicy->expire_value = atol(buf);
294 strprompt("How often to run network jobs (in seconds)", &sc[28][0], 5);
295 strprompt("Default frequency to run POP3 collection (in seconds)", &sc[64][0], 5);
296 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc[65][0], 5);
297 strprompt("Hour to run purges (0-23)", &sc[31][0], 2);
298 snprintf(sc[42], sizeof sc[42], "%d", (boolprompt(
299 "Enable full text search index (warning: resource intensive)",
302 snprintf(sc[46], sizeof sc[46], "%d", (boolprompt(
303 "Perform journaling of email messages",
305 snprintf(sc[47], sizeof sc[47], "%d", (boolprompt(
306 "Perform journaling of non-email messages",
308 if ( (atoi(&sc[46][0])) || (atoi(&sc[47][0])) ) {
309 strprompt("Email destination of journalized messages",
313 /* Funambol push stuff */
314 int yes_funambol = 0;
315 if (strlen(sc[53]) > 0) yes_funambol = 1;
316 yes_funambol = boolprompt("Connect to an external Funambol sync server", yes_funambol);
318 strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
319 strprompt("Funambol server port", &sc[54][0], 5);
320 strprompt("Funambol sync source", &sc[55][0], 63);
321 strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
330 /* External pager stuff */
332 if (strlen(sc[60]) > 0) yes_pager = 1;
333 yes_pager = boolprompt("Configure an external pager tool", yes_pager);
335 strprompt("External pager tool", &sc[60][0], 255);
341 /* Master user account */
343 if (strlen(sc[58]) > 0) yes_muacct = 1;
344 yes_muacct = boolprompt("Enable a 'master user' account", yes_muacct);
346 strprompt("Master user name", &sc[58][0], 31);
347 strprompt("Master user password", &sc[59][0], -31);
350 strcpy(&sc[58][0], "");
351 strcpy(&sc[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
355 scr_printf("Save this configuration? ");
358 for (a = 0; a < NUM_CONFIGS; a++) {
359 r += 1 + strlen(sc[a]);
361 resp = (char *)calloc(1, r);
363 scr_printf("Can't save config - out of memory!\n");
366 for (a = 0; a < NUM_CONFIGS; a++) {
370 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
372 scr_printf("%s\n", buf);
376 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
378 scr_printf("%s\n", buf);
381 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
383 scr_printf("%s\n", buf);
387 if (site_expirepolicy) free(site_expirepolicy);
388 if (mbx_expirepolicy) free(mbx_expirepolicy);
393 * support function for do_internet_configuration()
395 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
398 keyopt(" <1> localhost (Alias for this computer)\n");
399 keyopt(" <2> smart host (Forward all outbound mail to this host)\n");
400 keyopt(" <3> fallback host (Send mail to this host only if direct delivery fails)\n");
401 keyopt(" <4> directory (Consult the Global Address Book)\n");
402 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
403 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
404 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
405 keyopt(" <8> ClamAV (Address of ClamAV clamd server)\n");
406 sel = intprompt("Which one", 1, 1, 8);
408 case 1: strcpy(buf, "localhost");
410 case 2: strcpy(buf, "smarthost");
412 case 3: strcpy(buf, "fallbackhost");
414 case 4: strcpy(buf, "directory");
416 case 5: strcpy(buf, "spamassassin");
418 case 6: strcpy(buf, "rbl");
420 case 7: strcpy(buf, "masqdomain");
422 case 8: strcpy(buf, "clamav");
429 * Internet mail configuration
431 void do_internet_configuration(CtdlIPC *ipc)
443 r = CtdlIPCGetSystemConfigByType(ipc, INTERNETCFG, &resp, buf);
445 while (!IsEmptyStr(resp)) {
446 extract_token(buf, resp, 0, '\n', sizeof buf);
447 remove_token(resp, 0, '\n');
449 if (num_recs == 1) recs = malloc(sizeof(char *));
450 else recs = realloc(recs, (sizeof(char *)) * num_recs);
451 recs[num_recs-1] = malloc(strlen(buf) + 1);
452 strcpy(recs[num_recs-1], buf);
455 if (resp) free(resp);
460 scr_printf("### Host or domain Record type \n");
462 scr_printf("--- -------------------------------------------------- --------------------\n");
463 for (i=0; i<num_recs; ++i) {
465 scr_printf("%3d ", i+1);
466 extract_token(buf, recs[i], 0, '|', sizeof buf);
468 scr_printf("%-50s ", buf);
469 extract_token(buf, recs[i], 1, '|', sizeof buf);
470 color(BRIGHT_MAGENTA);
471 scr_printf("%-20s\n", buf);
475 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
478 newprompt("Enter host name: ",
481 if (!IsEmptyStr(buf)) {
484 recs = malloc(sizeof(char *));
485 else recs = realloc(recs,
486 (sizeof(char *)) * num_recs);
488 get_inet_rec_type(ipc,
490 recs[num_recs-1] = strdup(buf);
495 i = intprompt("Delete which one",
499 for (j=i; j<num_recs; ++j)
505 for (i = 0; i < num_recs; i++)
506 r += 1 + strlen(recs[i]);
507 resp = (char *)calloc(1, r);
509 scr_printf("Can't save config - out of memory!\n");
512 if (num_recs) for (i = 0; i < num_recs; i++) {
513 strcat(resp, recs[i]);
516 r = CtdlIPCSetSystemConfigByType(ipc, INTERNETCFG, resp, buf);
518 scr_printf("%s\n", buf);
520 scr_printf("Wrote %d records.\n", num_recs);
526 quitting = !modified || boolprompt(
527 "Quit without saving", 0);
535 for (i=0; i<num_recs; ++i) free(recs[i]);
543 * Edit network configuration for room sharing, mailing lists, etc.
545 void network_config_management(CtdlIPC *ipc, char *entrytype, char *comment)
547 char filename[PATH_MAX];
548 char changefile[PATH_MAX];
558 char *listing = NULL;
561 if (IsEmptyStr(editor_path)) {
562 scr_printf("You must have an external editor configured in"
563 " order to use this function.\n");
567 CtdlMakeTempFileName(filename, sizeof filename);
568 CtdlMakeTempFileName(changefile, sizeof changefile);
570 tempfp = fopen(filename, "w");
571 if (tempfp == NULL) {
572 scr_printf("Cannot open %s: %s\n", filename, strerror(errno));
576 fprintf(tempfp, "# Configuration for room: %s\n", room_name);
577 fprintf(tempfp, "# %s\n", comment);
578 fprintf(tempfp, "# Specify one per line.\n"
581 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
583 while(listing && !IsEmptyStr(listing)) {
584 extract_token(buf, listing, 0, '\n', sizeof buf);
585 remove_token(listing, 0, '\n');
586 extract_token(instr, buf, 0, '|', sizeof instr);
587 if (!strcasecmp(instr, entrytype)) {
588 tokens = num_tokens(buf, '|');
589 for (i=1; i<tokens; ++i) {
590 extract_token(addr, buf, i, '|', sizeof addr);
591 fprintf(tempfp, "%s", addr);
592 if (i < (tokens-1)) {
593 fprintf(tempfp, "|");
596 fprintf(tempfp, "\n");
606 e_ex_code = 1; /* start with a failed exit code */
607 stty_ctdl(SB_RESTORE);
609 cksum = file_checksum(filename);
610 if (editor_pid == 0) {
611 chmod(filename, 0600);
612 putenv("WINDOW_TITLE=Network configuration");
613 execlp(editor_path, editor_path, filename, NULL);
616 if (editor_pid > 0) {
619 b = ka_wait(&e_ex_code);
620 } while ((b != editor_pid) && (b >= 0));
625 if (file_checksum(filename) == cksum) {
626 scr_printf("*** No changes to save.\n");
630 if (e_ex_code == 0) { /* Save changes */
631 changefp = fopen(changefile, "w");
633 /* Load all netconfig entries that are *not* of the type we are editing */
634 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
636 while(listing && !IsEmptyStr(listing)) {
637 extract_token(buf, listing, 0, '\n', sizeof buf);
638 remove_token(listing, 0, '\n');
639 extract_token(instr, buf, 0, '|', sizeof instr);
640 if (strcasecmp(instr, entrytype)) {
641 fprintf(changefp, "%s\n", buf);
650 /* ...and merge that with the data we just edited */
651 tempfp = fopen(filename, "r");
652 while (fgets(buf, sizeof buf, tempfp) != NULL) {
653 for (i=0; i<strlen(buf); ++i) {
654 if (buf[i] == '#') buf[i] = 0;
657 if (!IsEmptyStr(buf)) {
658 fprintf(changefp, "%s|%s\n", entrytype, buf);
664 /* now write it to the server... */
665 changefp = fopen(changefile, "r");
666 if (changefp != NULL) {
667 listing = load_message_from_file(changefp);
669 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
677 unlink(filename); /* Delete the temporary files */
683 * IGnet node configuration
685 void do_ignet_configuration(CtdlIPC *ipc) {
693 char *listing = NULL;
696 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
697 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
698 extract_token(buf, listing, 0, '\n', sizeof buf);
699 remove_token(listing, 0, '\n');
702 if (num_recs == 1) recs = malloc(sizeof(char *));
703 else recs = realloc(recs, (sizeof(char *)) * num_recs);
704 recs[num_recs-1] = malloc(SIZ);
705 strcpy(recs[num_recs-1], buf);
707 if (listing) free(listing);
720 "------------------ "
721 "-------------------------------- "
723 for (i=0; i<num_recs; ++i) {
725 scr_printf("%3d ", i+1);
726 extract_token(buf, recs[i], 0, '|', sizeof buf);
728 scr_printf("%-16s ", buf);
729 extract_token(buf, recs[i], 1, '|', sizeof buf);
730 color(BRIGHT_MAGENTA);
731 scr_printf("%-18s ", buf);
732 extract_token(buf, recs[i], 2, '|', sizeof buf);
734 scr_printf("%-32s ", buf);
735 extract_token(buf, recs[i], 3, '|', sizeof buf);
736 color(BRIGHT_MAGENTA);
737 scr_printf("%-3s\n", buf);
742 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
747 recs = malloc(sizeof(char *));
748 else recs = realloc(recs,
749 (sizeof(char *)) * num_recs);
750 newprompt("Enter node name : ", buf, 16);
752 newprompt("Enter shared secret: ",
753 &buf[strlen(buf)], 18);
755 newprompt("Enter host or IP : ",
756 &buf[strlen(buf)], 32);
758 strprompt("Enter port number : ",
759 &buf[strlen(buf)-3], 5);
760 recs[num_recs-1] = strdup(buf);
764 i = intprompt("Delete which one",
768 for (j=i; j<num_recs; ++j)
774 for (i = 0; i < num_recs; ++i)
775 r += 1 + strlen(recs[i]);
776 listing = (char*) calloc(1, r);
778 scr_printf("Can't save config - out of memory!\n");
781 if (num_recs) for (i = 0; i < num_recs; ++i) {
782 strcat(listing, recs[i]);
783 strcat(listing, "\n");
785 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
787 scr_printf("%s\n", buf);
789 scr_printf("Wrote %d records.\n", num_recs);
795 quitting = !modified || boolprompt(
796 "Quit without saving", 0);
804 for (i=0; i<num_recs; ++i) free(recs[i]);
811 * Filter list configuration
813 void do_filterlist_configuration(CtdlIPC *ipc)
822 char *listing = NULL;
825 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
826 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
827 extract_token(buf, listing, 0, '\n', sizeof buf);
828 remove_token(listing, 0, '\n');
831 if (num_recs == 1) recs = malloc(sizeof(char *));
832 else recs = realloc(recs, (sizeof(char *)) * num_recs);
833 recs[num_recs-1] = malloc(SIZ);
834 strcpy(recs[num_recs-1], buf);
836 if (listing) free(listing);
848 "---------------------------- "
849 "---------------------------- "
852 for (i=0; i<num_recs; ++i) {
854 scr_printf("%3d ", i+1);
855 extract_token(buf, recs[i], 0, '|', sizeof buf);
857 scr_printf("%-28s ", buf);
858 extract_token(buf, recs[i], 1, '|', sizeof buf);
859 color(BRIGHT_MAGENTA);
860 scr_printf("%-28s ", buf);
861 extract_token(buf, recs[i], 2, '|', sizeof buf);
863 scr_printf("%-16s\n", buf);
864 extract_token(buf, recs[i], 3, '|', sizeof buf);
868 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
873 recs = malloc(sizeof(char *));
874 else recs = realloc(recs,
875 (sizeof(char *)) * num_recs);
876 newprompt("Enter user name: ", buf, 28);
878 newprompt("Enter room name: ",
879 &buf[strlen(buf)], 28);
881 newprompt("Enter node name: ",
882 &buf[strlen(buf)], 16);
884 recs[num_recs-1] = strdup(buf);
888 i = intprompt("Delete which one",
892 for (j=i; j<num_recs; ++j)
898 for (i = 0; i < num_recs; ++i)
899 r += 1 + strlen(recs[i]);
900 listing = (char*) calloc(1, r);
902 scr_printf("Can't save config - out of memory!\n");
905 if (num_recs) for (i = 0; i < num_recs; ++i) {
906 strcat(listing, recs[i]);
907 strcat(listing, "\n");
909 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
911 scr_printf("%s\n", buf);
913 scr_printf("Wrote %d records.\n", num_recs);
919 quitting = !modified || boolprompt(
920 "Quit without saving", 0);
928 for (i=0; i<num_recs; ++i) free(recs[i]);
937 * POP3 aggregation client configuration
939 void do_pop3client_configuration(CtdlIPC *ipc)
948 char *listing = NULL;
949 char *other_listing = NULL;
953 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
955 while(listing && !IsEmptyStr(listing)) {
956 extract_token(buf, listing, 0, '\n', sizeof buf);
957 remove_token(listing, 0, '\n');
958 extract_token(instr, buf, 0, '|', sizeof instr);
959 if (!strcasecmp(instr, "pop3client")) {
962 if (num_recs == 1) recs = malloc(sizeof(char *));
963 else recs = realloc(recs, (sizeof(char *)) * num_recs);
964 recs[num_recs-1] = malloc(SIZ);
965 strcpy(recs[num_recs-1], buf);
986 "---------------------------- "
987 "---------------------------- "
991 for (i=0; i<num_recs; ++i) {
993 scr_printf("%3d ", i+1);
995 extract_token(buf, recs[i], 1, '|', sizeof buf);
997 scr_printf("%-28s ", buf);
999 extract_token(buf, recs[i], 2, '|', sizeof buf);
1000 color(BRIGHT_MAGENTA);
1001 scr_printf("%-28s ", buf);
1004 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1005 color(BRIGHT_MAGENTA);
1006 scr_printf("%ld\n", extract_long(recs[i], 5) );
1010 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1014 if (num_recs == 1) {
1015 recs = malloc(sizeof(char *));
1018 recs = realloc(recs, (sizeof(char *)) * num_recs);
1020 strcpy(buf, "pop3client|");
1021 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1023 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1025 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1027 scr_printf("Keep messages on server instead of deleting them? ");
1028 sprintf(&buf[strlen(buf)], "%d", yesno());
1030 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1032 recs[num_recs-1] = strdup(buf);
1036 i = intprompt("Delete which one",
1037 1, 1, num_recs) - 1;
1040 for (j=i; j<num_recs; ++j)
1041 recs[j] = recs[j+1];
1046 for (i = 0; i < num_recs; ++i) {
1047 r += 1 + strlen(recs[i]);
1049 listing = (char*) calloc(1, r);
1051 scr_printf("Can't save config - out of memory!\n");
1054 if (num_recs) for (i = 0; i < num_recs; ++i) {
1055 strcat(listing, recs[i]);
1056 strcat(listing, "\n");
1059 /* Retrieve all the *other* records for merging */
1060 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1062 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1063 extract_token(buf, other_listing, i, '\n', sizeof buf);
1064 if (strncasecmp(buf, "pop3client|", 11)) {
1065 listing = realloc(listing, strlen(listing) +
1067 strcat(listing, buf);
1068 strcat(listing, "\n");
1072 free(other_listing);
1073 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1078 scr_printf("%s\n", buf);
1080 scr_printf("Wrote %d records.\n", num_recs);
1086 quitting = !modified || boolprompt(
1087 "Quit without saving", 0);
1092 } while (!quitting);
1095 for (i=0; i<num_recs; ++i) free(recs[i]);
1106 * RSS feed retrieval client configuration
1108 void do_rssclient_configuration(CtdlIPC *ipc)
1117 char *listing = NULL;
1118 char *other_listing = NULL;
1122 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1124 while(listing && !IsEmptyStr(listing)) {
1125 extract_token(buf, listing, 0, '\n', sizeof buf);
1126 remove_token(listing, 0, '\n');
1127 extract_token(instr, buf, 0, '|', sizeof instr);
1128 if (!strcasecmp(instr, "rssclient")) {
1131 if (num_recs == 1) recs = malloc(sizeof(char *));
1132 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1133 recs[num_recs-1] = malloc(SIZ);
1134 strcpy(recs[num_recs-1], buf);
1146 color(BRIGHT_WHITE);
1147 scr_printf("### Feed URL\n");
1150 "---------------------------------------------------------------------------"
1153 for (i=0; i<num_recs; ++i) {
1155 scr_printf("%3d ", i+1);
1157 extract_token(buf, recs[i], 1, '|', sizeof buf);
1159 scr_printf("%-75s\n", buf);
1164 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1168 if (num_recs == 1) {
1169 recs = malloc(sizeof(char *));
1172 recs = realloc(recs, (sizeof(char *)) * num_recs);
1174 strcpy(buf, "rssclient|");
1175 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1177 recs[num_recs-1] = strdup(buf);
1181 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1184 for (j=i; j<num_recs; ++j)
1185 recs[j] = recs[j+1];
1190 for (i = 0; i < num_recs; ++i) {
1191 r += 1 + strlen(recs[i]);
1193 listing = (char*) calloc(1, r);
1195 scr_printf("Can't save config - out of memory!\n");
1198 if (num_recs) for (i = 0; i < num_recs; ++i) {
1199 strcat(listing, recs[i]);
1200 strcat(listing, "\n");
1203 /* Retrieve all the *other* records for merging */
1204 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1206 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1207 extract_token(buf, other_listing, i, '\n', sizeof buf);
1208 if (strncasecmp(buf, "rssclient|", 10)) {
1209 listing = realloc(listing, strlen(listing) +
1211 strcat(listing, buf);
1212 strcat(listing, "\n");
1216 free(other_listing);
1217 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1222 scr_printf("%s\n", buf);
1224 scr_printf("Wrote %d records.\n", num_recs);
1230 quitting = !modified || boolprompt(
1231 "Quit without saving", 0);
1236 } while (!quitting);
1239 for (i=0; i<num_recs; ++i) free(recs[i]);