2 * Configuration screens that are part of the text mode client.
16 #if TIME_WITH_SYS_TIME
17 # include <sys/time.h>
21 # include <sys/time.h>
31 #include <libcitadel.h>
34 #include "citadel_ipc.h"
35 #include "citadel_decls.h"
36 #include "tuiconfig.h"
45 /* work around solaris include files */
51 extern char tempdir[];
52 extern char *axdefs[8];
53 extern long highest_msg_read;
54 extern long maxmsgnum;
55 extern unsigned room_flags;
56 extern int screenwidth;
60 * General system configuration command
62 void do_system_configuration(CtdlIPC *ipc)
65 #define NUM_CONFIGS 68
68 char sc[NUM_CONFIGS][256];
70 struct ExpirePolicy *site_expirepolicy = NULL;
71 struct ExpirePolicy *mbx_expirepolicy = NULL;
74 int r; /* IPC response code */
75 int server_configs = 0;
77 /* Clear out the config buffers */
78 memset(&sc[0][0], 0, sizeof(sc));
80 /* Fetch the current config */
81 r = CtdlIPCGetSystemConfig(ipc, &resp, buf);
83 server_configs = num_tokens(resp, '\n');
84 for (a=0; a<server_configs; ++a) {
85 if (a < NUM_CONFIGS) {
86 extract_token(&sc[a][0], resp, a, '\n', sizeof sc[a]);
92 /* Fetch the expire policy (this will silently fail on old servers,
93 * resulting in "default" policy)
95 r = CtdlIPCGetMessageExpirationPolicy(ipc, 2, &site_expirepolicy, buf);
96 r = CtdlIPCGetMessageExpirationPolicy(ipc, 3, &mbx_expirepolicy, buf);
98 /* Identification parameters */
100 strprompt("Node name", &sc[0][0], 15);
101 strprompt("Fully qualified domain name", &sc[1][0], 63);
102 strprompt("Human readable node name", &sc[2][0], 20);
103 strprompt("Telephone number", &sc[3][0], 15);
104 strprompt("Geographic location of this system", &sc[12][0], 31);
105 strprompt("Name of system administrator", &sc[13][0], 25);
106 strprompt("Paginator prompt", &sc[10][0], 79);
108 /* Security parameters */
110 snprintf(sc[7], sizeof sc[7], "%d", (boolprompt(
111 "Require registration for new users",
113 snprintf(sc[29], sizeof sc[29], "%d", (boolprompt(
114 "Disable self-service user account creation",
116 strprompt("Initial access level for new users", &sc[6][0], 1);
117 strprompt("Access level required to create rooms", &sc[19][0], 1);
118 snprintf(sc[67], sizeof sc[67], "%d", (boolprompt(
119 "Allow anonymous guest logins",
121 snprintf(sc[4], sizeof sc[4], "%d", (boolprompt(
122 "Automatically give room aide privs to a user who creates a private room",
125 snprintf(sc[8], sizeof sc[8], "%d", (boolprompt(
126 "Automatically move problem user messages to twit room",
129 strprompt("Name of twit room", &sc[9][0], ROOMNAMELEN);
130 snprintf(sc[11], sizeof sc[11], "%d", (boolprompt(
131 "Restrict Internet mail to only those with that privilege",
133 snprintf(sc[26], sizeof sc[26], "%d", (boolprompt(
134 "Allow Aides to Zap (forget) rooms",
137 if (!IsEmptyStr(&sc[18][0])) {
143 logpages = boolprompt("Log all instant messages", logpages);
145 strprompt("Name of logging room", &sc[18][0], ROOMNAMELEN);
151 /* Commented out because this setting isn't really appropriate to
152 * change while the server is running.
154 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
155 * "Use system authentication",
156 * atoi(&sc[52][0]))));
161 strprompt("Server connection idle timeout (in seconds)", &sc[5][0], 4);
162 strprompt("Maximum concurrent sessions", &sc[14][0], 4);
163 strprompt("Maximum message length", &sc[20][0], 20);
164 strprompt("Minimum number of worker threads", &sc[21][0], 3);
165 strprompt("Maximum number of worker threads", &sc[22][0], 3);
166 snprintf(sc[43], sizeof sc[43], "%d", (boolprompt(
167 "Automatically delete committed database logs",
170 strprompt("Server IP address (* for 'any')", &sc[37][0], 15);
171 strprompt("POP3 server port (-1 to disable)", &sc[23][0], 5);
172 strprompt("POP3S server port (-1 to disable)", &sc[40][0], 5);
173 strprompt("IMAP server port (-1 to disable)", &sc[27][0], 5);
174 strprompt("IMAPS server port (-1 to disable)", &sc[39][0], 5);
175 strprompt("SMTP MTA server port (-1 to disable)", &sc[24][0], 5);
176 strprompt("SMTP MSA server port (-1 to disable)", &sc[38][0], 5);
177 strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
178 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
179 strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
181 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc[62][0], 5);
182 /* No prompt because we don't implement this service yet, it's just a placeholder */
183 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
185 /* This logic flips the question around, because it's one of those
186 * situations where 0=yes and 1=no
190 a = boolprompt("Correct forged From: lines during authenticated SMTP",
193 snprintf(sc[25], sizeof sc[25], "%d", a);
195 snprintf(sc[66], sizeof sc[66], "%d", (boolprompt(
196 "Flag messages as spam instead of rejecting",
199 /* This logic flips the question around, because it's one of those
200 * situations where 0=yes and 1=no
204 a = boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a);
206 snprintf(sc[61], sizeof sc[61], "%d", a);
208 snprintf(sc[45], sizeof sc[45], "%d", (boolprompt(
209 "Allow unauthenticated SMTP clients to spoof my domains",
211 snprintf(sc[57], sizeof sc[57], "%d", (boolprompt(
212 "Perform RBL checks at greeting instead of after RCPT",
214 snprintf(sc[44], sizeof sc[44], "%d", (boolprompt(
215 "Instantly expunge deleted IMAP messages",
219 if (ipc->ServInfo.supports_ldap) {
220 a = strlen(&sc[32][0]);
221 a = (a ? 1 : 0); /* Set only to 1 or 0 */
222 a = boolprompt("Do you want to configure LDAP authentication?", a);
224 strprompt("Host name of LDAP server",
226 strprompt("Port number of LDAP service",
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]);
360 resp = (char *)calloc(1, r);
362 scr_printf("Can't save config - out of memory!\n");
365 for (a = 0; a < NUM_CONFIGS; a++) {
369 r = CtdlIPCSetSystemConfig(ipc, resp, buf);
371 scr_printf("%s\n", buf);
375 r = CtdlIPCSetMessageExpirationPolicy(ipc, 2, site_expirepolicy, buf);
377 scr_printf("%s\n", buf);
380 r = CtdlIPCSetMessageExpirationPolicy(ipc, 3, mbx_expirepolicy, buf);
382 scr_printf("%s\n", buf);
386 if (site_expirepolicy) free(site_expirepolicy);
387 if (mbx_expirepolicy) free(mbx_expirepolicy);
392 * support function for do_internet_configuration()
394 void get_inet_rec_type(CtdlIPC *ipc, char *buf) {
397 keyopt(" <1> localhost (Alias for this computer)\n");
398 keyopt(" <2> smart host (Forward all outbound mail to this host)\n");
399 keyopt(" <3> fallback host (Send mail to this host only if direct delivery fails)\n");
400 keyopt(" <4> directory (Consult the Global Address Book)\n");
401 keyopt(" <5> SpamAssassin (Address of SpamAssassin server)\n");
402 keyopt(" <6> RBL (domain suffix of spam hunting RBL)\n");
403 keyopt(" <7> masq domains (Domains as which users are allowed to masquerade)\n");
404 keyopt(" <8> ClamAV (Address of ClamAV clamd server)\n");
405 sel = intprompt("Which one", 1, 1, 8);
407 case 1: strcpy(buf, "localhost");
409 case 2: strcpy(buf, "smarthost");
411 case 3: strcpy(buf, "fallbackhost");
413 case 4: strcpy(buf, "directory");
415 case 5: strcpy(buf, "spamassassin");
417 case 6: strcpy(buf, "rbl");
419 case 7: strcpy(buf, "masqdomain");
421 case 8: strcpy(buf, "clamav");
428 * Internet mail configuration
430 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_paths[0])) {
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_paths[0], editor_paths[0], 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) {
694 char *listing = NULL;
697 r = CtdlIPCGetSystemConfigByType(ipc, IGNETCFG, &listing, buf);
698 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
699 extract_token(buf, listing, 0, '\n', sizeof buf);
700 remove_token(listing, 0, '\n');
703 if (num_recs == 1) recs = malloc(sizeof(char *));
704 else recs = realloc(recs, (sizeof(char *)) * num_recs);
705 recs[num_recs-1] = malloc(SIZ);
706 strcpy(recs[num_recs-1], buf);
708 if (listing) free(listing);
721 "------------------ "
722 "-------------------------------- "
724 for (i=0; i<num_recs; ++i) {
726 scr_printf("%3d ", i+1);
727 extract_token(buf, recs[i], 0, '|', sizeof buf);
729 scr_printf("%-16s ", buf);
730 extract_token(buf, recs[i], 1, '|', sizeof buf);
731 color(BRIGHT_MAGENTA);
732 scr_printf("%-18s ", buf);
733 extract_token(buf, recs[i], 2, '|', sizeof buf);
735 scr_printf("%-32s ", buf);
736 extract_token(buf, recs[i], 3, '|', sizeof buf);
737 color(BRIGHT_MAGENTA);
738 scr_printf("%-3s\n", buf);
743 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
748 recs = malloc(sizeof(char *));
749 else recs = realloc(recs,
750 (sizeof(char *)) * num_recs);
751 newprompt("Enter node name : ", buf, 16);
753 newprompt("Enter shared secret: ",
754 &buf[strlen(buf)], 18);
756 newprompt("Enter host or IP : ",
757 &buf[strlen(buf)], 32);
759 strprompt("Enter port number : ",
760 &buf[strlen(buf)-3], 5);
761 recs[num_recs-1] = strdup(buf);
765 i = intprompt("Delete which one",
769 for (j=i; j<num_recs; ++j)
775 for (i = 0; i < num_recs; ++i)
776 r += 1 + strlen(recs[i]);
777 listing = (char*) calloc(1, r);
779 scr_printf("Can't save config - out of memory!\n");
782 if (num_recs) for (i = 0; i < num_recs; ++i) {
783 strcat(listing, recs[i]);
784 strcat(listing, "\n");
786 r = CtdlIPCSetSystemConfigByType(ipc, IGNETCFG, listing, buf);
788 scr_printf("%s\n", buf);
790 scr_printf("Wrote %d records.\n", num_recs);
796 quitting = !modified || boolprompt(
797 "Quit without saving", 0);
805 for (i=0; i<num_recs; ++i) free(recs[i]);
812 * Filter list configuration
814 void do_filterlist_configuration(CtdlIPC *ipc)
824 char *listing = NULL;
827 r = CtdlIPCGetSystemConfigByType(ipc, FILTERLIST, &listing, buf);
828 if (r / 100 == 1) while (*listing && !IsEmptyStr(listing)) {
829 extract_token(buf, listing, 0, '\n', sizeof buf);
830 remove_token(listing, 0, '\n');
833 if (num_recs == 1) recs = malloc(sizeof(char *));
834 else recs = realloc(recs, (sizeof(char *)) * num_recs);
835 recs[num_recs-1] = malloc(SIZ);
836 strcpy(recs[num_recs-1], buf);
838 if (listing) free(listing);
850 "---------------------------- "
851 "---------------------------- "
854 for (i=0; i<num_recs; ++i) {
856 scr_printf("%3d ", i+1);
857 extract_token(buf, recs[i], 0, '|', sizeof buf);
859 scr_printf("%-28s ", buf);
860 extract_token(buf, recs[i], 1, '|', sizeof buf);
861 color(BRIGHT_MAGENTA);
862 scr_printf("%-28s ", buf);
863 extract_token(buf, recs[i], 2, '|', sizeof buf);
865 scr_printf("%-16s\n", buf);
866 extract_token(buf, recs[i], 3, '|', sizeof buf);
870 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
875 recs = malloc(sizeof(char *));
876 else recs = realloc(recs,
877 (sizeof(char *)) * num_recs);
878 newprompt("Enter user name: ", buf, 28);
880 newprompt("Enter room name: ",
881 &buf[strlen(buf)], 28);
883 newprompt("Enter node name: ",
884 &buf[strlen(buf)], 16);
886 recs[num_recs-1] = strdup(buf);
890 i = intprompt("Delete which one",
894 for (j=i; j<num_recs; ++j)
900 for (i = 0; i < num_recs; ++i)
901 r += 1 + strlen(recs[i]);
902 listing = (char*) calloc(1, r);
904 scr_printf("Can't save config - out of memory!\n");
907 if (num_recs) for (i = 0; i < num_recs; ++i) {
908 strcat(listing, recs[i]);
909 strcat(listing, "\n");
911 r = CtdlIPCSetSystemConfigByType(ipc, FILTERLIST, listing, buf);
913 scr_printf("%s\n", buf);
915 scr_printf("Wrote %d records.\n", num_recs);
921 quitting = !modified || boolprompt(
922 "Quit without saving", 0);
930 for (i=0; i<num_recs; ++i) free(recs[i]);
939 * POP3 aggregation client configuration
941 void do_pop3client_configuration(CtdlIPC *ipc)
951 char *listing = NULL;
952 char *other_listing = NULL;
956 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
958 while(listing && !IsEmptyStr(listing)) {
959 extract_token(buf, listing, 0, '\n', sizeof buf);
960 remove_token(listing, 0, '\n');
961 extract_token(instr, buf, 0, '|', sizeof instr);
962 if (!strcasecmp(instr, "pop3client")) {
965 if (num_recs == 1) recs = malloc(sizeof(char *));
966 else recs = realloc(recs, (sizeof(char *)) * num_recs);
967 recs[num_recs-1] = malloc(SIZ);
968 strcpy(recs[num_recs-1], buf);
989 "---------------------------- "
990 "---------------------------- "
994 for (i=0; i<num_recs; ++i) {
996 scr_printf("%3d ", i+1);
998 extract_token(buf, recs[i], 1, '|', sizeof buf);
1000 scr_printf("%-28s ", buf);
1002 extract_token(buf, recs[i], 2, '|', sizeof buf);
1003 color(BRIGHT_MAGENTA);
1004 scr_printf("%-28s ", buf);
1007 scr_printf("%-15s ", (extract_int(recs[i], 4) ? "Yes" : "No") );
1008 color(BRIGHT_MAGENTA);
1009 scr_printf("%ld\n", extract_long(recs[i], 5) );
1013 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1017 if (num_recs == 1) {
1018 recs = malloc(sizeof(char *));
1021 recs = realloc(recs, (sizeof(char *)) * num_recs);
1023 strcpy(buf, "pop3client|");
1024 newprompt("Enter host name: ", &buf[strlen(buf)], 28);
1026 newprompt("Enter user name: ", &buf[strlen(buf)], 28);
1028 newprompt("Enter password : ", &buf[strlen(buf)], 16);
1030 scr_printf("Keep messages on server instead of deleting them? ");
1031 sprintf(&buf[strlen(buf)], "%d", yesno());
1033 newprompt("Enter interval : ", &buf[strlen(buf)], 5);
1035 recs[num_recs-1] = strdup(buf);
1039 i = intprompt("Delete which one",
1040 1, 1, num_recs) - 1;
1043 for (j=i; j<num_recs; ++j)
1044 recs[j] = recs[j+1];
1049 for (i = 0; i < num_recs; ++i) {
1050 r += 1 + strlen(recs[i]);
1052 listing = (char*) calloc(1, r);
1054 scr_printf("Can't save config - out of memory!\n");
1057 if (num_recs) for (i = 0; i < num_recs; ++i) {
1058 strcat(listing, recs[i]);
1059 strcat(listing, "\n");
1062 /* Retrieve all the *other* records for merging */
1063 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1065 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1066 extract_token(buf, other_listing, i, '\n', sizeof buf);
1067 if (strncasecmp(buf, "pop3client|", 11)) {
1068 listing = realloc(listing, strlen(listing) +
1070 strcat(listing, buf);
1071 strcat(listing, "\n");
1075 free(other_listing);
1076 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1081 scr_printf("%s\n", buf);
1083 scr_printf("Wrote %d records.\n", num_recs);
1089 quitting = !modified || boolprompt(
1090 "Quit without saving", 0);
1095 } while (!quitting);
1098 for (i=0; i<num_recs; ++i) free(recs[i]);
1109 * RSS feed retrieval client configuration
1111 void do_rssclient_configuration(CtdlIPC *ipc)
1121 char *listing = NULL;
1122 char *other_listing = NULL;
1126 r = CtdlIPCGetRoomNetworkConfig(ipc, &listing, buf);
1128 while(listing && !IsEmptyStr(listing)) {
1129 extract_token(buf, listing, 0, '\n', sizeof buf);
1130 remove_token(listing, 0, '\n');
1131 extract_token(instr, buf, 0, '|', sizeof instr);
1132 if (!strcasecmp(instr, "rssclient")) {
1135 if (num_recs == 1) recs = malloc(sizeof(char *));
1136 else recs = realloc(recs, (sizeof(char *)) * num_recs);
1137 recs[num_recs-1] = malloc(SIZ);
1138 strcpy(recs[num_recs-1], buf);
1150 color(BRIGHT_WHITE);
1151 scr_printf("### Feed URL\n");
1154 "---------------------------------------------------------------------------"
1157 for (i=0; i<num_recs; ++i) {
1159 scr_printf("%3d ", i+1);
1161 extract_token(buf, recs[i], 1, '|', sizeof buf);
1163 scr_printf("%-75s\n", buf);
1168 ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1172 if (num_recs == 1) {
1173 recs = malloc(sizeof(char *));
1176 recs = realloc(recs, (sizeof(char *)) * num_recs);
1178 strcpy(buf, "rssclient|");
1179 newprompt("Enter feed URL: ", &buf[strlen(buf)], 75);
1181 recs[num_recs-1] = strdup(buf);
1185 i = intprompt("Delete which one", 1, 1, num_recs) - 1;
1188 for (j=i; j<num_recs; ++j)
1189 recs[j] = recs[j+1];
1194 for (i = 0; i < num_recs; ++i) {
1195 r += 1 + strlen(recs[i]);
1197 listing = (char*) calloc(1, r);
1199 scr_printf("Can't save config - out of memory!\n");
1202 if (num_recs) for (i = 0; i < num_recs; ++i) {
1203 strcat(listing, recs[i]);
1204 strcat(listing, "\n");
1207 /* Retrieve all the *other* records for merging */
1208 r = CtdlIPCGetRoomNetworkConfig(ipc, &other_listing, buf);
1210 for (i=0; i<num_tokens(other_listing, '\n'); ++i) {
1211 extract_token(buf, other_listing, i, '\n', sizeof buf);
1212 if (strncasecmp(buf, "rssclient|", 10)) {
1213 listing = realloc(listing, strlen(listing) +
1215 strcat(listing, buf);
1216 strcat(listing, "\n");
1220 free(other_listing);
1221 r = CtdlIPCSetRoomNetworkConfig(ipc, listing, buf);
1226 scr_printf("%s\n", buf);
1228 scr_printf("Wrote %d records.\n", num_recs);
1234 quitting = !modified || boolprompt(
1235 "Quit without saving", 0);
1240 } while (!quitting);
1243 for (i=0; i<num_recs; ++i) free(recs[i]);