3 * Configuration screens that are part of the text mode client.
17 #if TIME_WITH_SYS_TIME
18 # include <sys/time.h>
22 # include <sys/time.h>
32 #include <libcitadel.h>
35 #include "citadel_ipc.h"
36 #include "citadel_decls.h"
37 #include "tuiconfig.h"
46 /* work around solaris include files */
52 extern char tempdir
[];
53 extern char *axdefs
[8];
54 extern long highest_msg_read
;
55 extern long maxmsgnum
;
56 extern unsigned room_flags
;
57 extern int screenwidth
;
61 * General system configuration command
63 void do_system_configuration(CtdlIPC
*ipc
)
66 #define NUM_CONFIGS 67
69 char sc
[NUM_CONFIGS
][256];
71 struct ExpirePolicy
*site_expirepolicy
= NULL
;
72 struct ExpirePolicy
*mbx_expirepolicy
= NULL
;
75 int r
; /* IPC response code */
76 int server_configs
= 0;
78 /* Clear out the config buffers */
79 memset(&sc
[0][0], 0, sizeof(sc
));
81 /* Fetch the current config */
82 r
= CtdlIPCGetSystemConfig(ipc
, &resp
, buf
);
84 server_configs
= num_tokens(resp
, '\n');
85 for (a
=0; a
<server_configs
; ++a
) {
86 if (a
< NUM_CONFIGS
) {
87 extract_token(&sc
[a
][0], resp
, a
, '\n', sizeof sc
[a
]);
93 /* Fetch the expire policy (this will silently fail on old servers,
94 * resulting in "default" policy)
96 r
= CtdlIPCGetMessageExpirationPolicy(ipc
, 2, &site_expirepolicy
, buf
);
97 r
= CtdlIPCGetMessageExpirationPolicy(ipc
, 3, &mbx_expirepolicy
, buf
);
99 /* Identification parameters */
101 strprompt("Node name", &sc
[0][0], 15);
102 strprompt("Fully qualified domain name", &sc
[1][0], 63);
103 strprompt("Human readable node name", &sc
[2][0], 20);
104 strprompt("Telephone number", &sc
[3][0], 15);
105 strprompt("Geographic location of this system", &sc
[12][0], 31);
106 strprompt("Name of system administrator", &sc
[13][0], 25);
107 strprompt("Paginator prompt", &sc
[10][0], 79);
109 /* Security parameters */
111 snprintf(sc
[7], sizeof sc
[7], "%d", (boolprompt(
112 "Require registration for new users",
114 snprintf(sc
[29], sizeof sc
[29], "%d", (boolprompt(
115 "Disable self-service user account creation",
117 strprompt("Initial access level for new users", &sc
[6][0], 1);
118 strprompt("Access level required to create rooms", &sc
[19][0], 1);
119 snprintf(sc
[4], sizeof sc
[4], "%d", (boolprompt(
120 "Automatically give room aide privs to a user who creates a private room",
123 snprintf(sc
[8], sizeof sc
[8], "%d", (boolprompt(
124 "Automatically move problem user messages to twit room",
127 strprompt("Name of twit room", &sc
[9][0], ROOMNAMELEN
);
128 snprintf(sc
[11], sizeof sc
[11], "%d", (boolprompt(
129 "Restrict Internet mail to only those with that privilege",
131 snprintf(sc
[26], sizeof sc
[26], "%d", (boolprompt(
132 "Allow Aides to Zap (forget) rooms",
135 if (!IsEmptyStr(&sc
[18][0])) logpages
= 1;
137 logpages
= boolprompt("Log all pages", logpages
);
139 strprompt("Name of logging room", &sc
[18][0], ROOMNAMELEN
);
145 /* Commented out because this setting isn't really appropriate to
146 * change while the server is running.
148 * snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
149 * "Use system authentication",
150 * atoi(&sc[52][0]))));
155 strprompt("Server connection idle timeout (in seconds)", &sc
[5][0], 4);
156 strprompt("Maximum concurrent sessions", &sc
[14][0], 4);
157 strprompt("Maximum message length", &sc
[20][0], 20);
158 strprompt("Minimum number of worker threads", &sc
[21][0], 3);
159 strprompt("Maximum number of worker threads", &sc
[22][0], 3);
160 snprintf(sc
[43], sizeof sc
[43], "%d", (boolprompt(
161 "Automatically delete committed database logs",
164 strprompt("Server IP address (0.0.0.0 for 'any')", &sc
[37][0], 15);
165 strprompt("POP3 server port (-1 to disable)", &sc
[23][0], 5);
166 strprompt("POP3S server port (-1 to disable)", &sc
[40][0], 5);
167 strprompt("IMAP server port (-1 to disable)", &sc
[27][0], 5);
168 strprompt("IMAPS server port (-1 to disable)", &sc
[39][0], 5);
169 strprompt("SMTP MTA server port (-1 to disable)", &sc
[24][0], 5);
170 strprompt("SMTP MSA server port (-1 to disable)", &sc
[38][0], 5);
171 strprompt("SMTPS server port (-1 to disable)", &sc
[41][0], 5);
172 strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc
[50][0], 5);
173 strprompt("ManageSieve server port (-1 to disable)", &sc
[51][0], 5);
175 strprompt("XMPP (Jabber) client to server port (-1 to disable)", &sc
[62][0], 5);
176 /* No prompt because we don't implement this service yet, it's just a placeholder */
177 /* strprompt("XMPP (Jabber) server to server port (-1 to disable)", &sc[63][0], 5); */
179 /* This logic flips the question around, because it's one of those
180 * situations where 0=yes and 1=no
184 a
= boolprompt("Correct forged From: lines during authenticated SMTP",
187 snprintf(sc
[25], sizeof sc
[25], "%d", a
);
189 snprintf(sc
[66], sizeof sc
[66], "%d", (boolprompt(
190 "Flag messages as spam instead of rejecting",
193 /* This logic flips the question around, because it's one of those
194 * situations where 0=yes and 1=no
198 a
= boolprompt("Force IMAP posts in public rooms to be from the user who submitted them", a
);
200 snprintf(sc
[61], sizeof sc
[61], "%d", a
);
202 snprintf(sc
[45], sizeof sc
[45], "%d", (boolprompt(
203 "Allow unauthenticated SMTP clients to spoof my domains",
205 snprintf(sc
[57], sizeof sc
[57], "%d", (boolprompt(
206 "Perform RBL checks at greeting instead of after RCPT",
208 snprintf(sc
[44], sizeof sc
[44], "%d", (boolprompt(
209 "Instantly expunge deleted IMAP messages",
213 if (ipc
->ServInfo
.supports_ldap
) {
214 a
= strlen(&sc
[32][0]);
215 a
= (a
? 1 : 0); /* Set only to 1 or 0 */
216 a
= boolprompt("Connect this Citadel to an external LDAP directory", a
);
218 strprompt("Host name of LDAP server",
220 strprompt("Port number of LDAP service",
222 strprompt("Base DN", &sc
[34][0], 255);
223 strprompt("Bind DN", &sc
[35][0], 255);
224 strprompt("Password for bind DN", &sc
[36][0], 255);
227 strcpy(&sc
[32][0], "");
231 /* Expiry settings */
232 strprompt("Default user purge time (days)", &sc
[16][0], 5);
233 strprompt("Default room purge time (days)", &sc
[17][0], 5);
235 /* Angels and demons dancing in my head... */
237 snprintf(buf
, sizeof buf
, "%d", site_expirepolicy
->expire_mode
);
238 strprompt("System default message expire policy (? for list)",
242 "1. Never automatically expire messages\n"
243 "2. Expire by message count\n"
244 "3. Expire by message age\n");
246 } while ((buf
[0] < '1') || (buf
[0] > '3'));
247 site_expirepolicy
->expire_mode
= buf
[0] - '0';
249 /* ...lunatics and monsters underneath my bed */
250 if (site_expirepolicy
->expire_mode
== 2) {
251 snprintf(buf
, sizeof buf
, "%d", site_expirepolicy
->expire_value
);
252 strprompt("Keep how many messages online?", buf
, 10);
253 site_expirepolicy
->expire_value
= atol(buf
);
255 if (site_expirepolicy
->expire_mode
== 3) {
256 snprintf(buf
, sizeof buf
, "%d", site_expirepolicy
->expire_value
);
257 strprompt("Keep messages for how many days?", buf
, 10);
258 site_expirepolicy
->expire_value
= atol(buf
);
261 /* Media messiahs preying on my fears... */
263 snprintf(buf
, sizeof buf
, "%d", mbx_expirepolicy
->expire_mode
);
264 strprompt("Mailbox default message expire policy (? for list)",
268 "0. Go with the system default\n"
269 "1. Never automatically expire messages\n"
270 "2. Expire by message count\n"
271 "3. Expire by message age\n");
273 } while ((buf
[0] < '0') || (buf
[0] > '3'));
274 mbx_expirepolicy
->expire_mode
= buf
[0] - '0';
276 /* ...Pop culture prophets playing in my ears */
277 if (mbx_expirepolicy
->expire_mode
== 2) {
278 snprintf(buf
, sizeof buf
, "%d", mbx_expirepolicy
->expire_value
);
279 strprompt("Keep how many messages online?", buf
, 10);
280 mbx_expirepolicy
->expire_value
= atol(buf
);
282 if (mbx_expirepolicy
->expire_mode
== 3) {
283 snprintf(buf
, sizeof buf
, "%d", mbx_expirepolicy
->expire_value
);
284 strprompt("Keep messages for how many days?", buf
, 10);
285 mbx_expirepolicy
->expire_value
= atol(buf
);
288 strprompt("How often to run network jobs (in seconds)", &sc
[28][0], 5);
289 strprompt("Default frequency to run POP3 collection (in seconds)", &sc
[64][0], 5);
290 strprompt("Fastest frequency to run POP3 collection (in seconds)", &sc
[65][0], 5);
291 strprompt("Hour to run purges (0-23)", &sc
[31][0], 2);
292 snprintf(sc
[42], sizeof sc
[42], "%d", (boolprompt(
293 "Enable full text search index (warning: resource intensive)",
296 snprintf(sc
[46], sizeof sc
[46], "%d", (boolprompt(
297 "Perform journaling of email messages",
299 snprintf(sc
[47], sizeof sc
[47], "%d", (boolprompt(
300 "Perform journaling of non-email messages",
302 if ( (atoi(&sc
[46][0])) || (atoi(&sc
[47][0])) ) {
303 strprompt("Email destination of journalized messages",
307 /* Funambol push stuff */
308 int yes_funambol
= 0;
309 if (strlen(sc
[53]) > 0) yes_funambol
= 1;
310 yes_funambol
= boolprompt("Connect to an external Funambol sync server", yes_funambol
);
312 strprompt("Funambol server (blank to disable)", &sc
[53][0], 63);
313 strprompt("Funambol server port", &sc
[54][0], 5);
314 strprompt("Funambol sync source", &sc
[55][0], 63);
315 strprompt("Funambol authentication details (user:pass in Base64)", &sc
[56][0],63);
324 /* External pager stuff */
326 if (strlen(sc
[60]) > 0) yes_pager
= 1;
327 yes_pager
= boolprompt("Configure an external pager tool", yes_pager
);
329 strprompt("External pager tool", &sc
[60][0], 255);
335 /* Master user account */
337 if (strlen(sc
[58]) > 0) yes_muacct
= 1;
338 yes_muacct
= boolprompt("Enable a 'master user' account", yes_muacct
);
340 strprompt("Master user name", &sc
[58][0], 31);
341 strprompt("Master user password", &sc
[59][0], -31);
344 strcpy(&sc
[58][0], "");
345 strcpy(&sc
[59][0], "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
349 scr_printf("Save this configuration? ");
352 for (a
= 0; a
< NUM_CONFIGS
; a
++)
353 r
+= 1 + strlen(sc
[a
]);
354 resp
= (char *)calloc(1, r
);
356 err_printf("Can't save config - out of memory!\n");
359 for (a
= 0; a
< NUM_CONFIGS
; a
++) {
363 r
= CtdlIPCSetSystemConfig(ipc
, resp
, buf
);
365 err_printf("%s\n", buf
);
369 r
= CtdlIPCSetMessageExpirationPolicy(ipc
, 2, site_expirepolicy
, buf
);
371 err_printf("%s\n", buf
);
374 r
= CtdlIPCSetMessageExpirationPolicy(ipc
, 3, mbx_expirepolicy
, buf
);
376 err_printf("%s\n", buf
);
380 if (site_expirepolicy
) free(site_expirepolicy
);
381 if (mbx_expirepolicy
) free(mbx_expirepolicy
);
386 * support function for do_internet_configuration()
388 void get_inet_rec_type(CtdlIPC
*ipc
, char *buf
) {
391 keyopt(" <1> localhost (Alias for this computer)\n");
392 keyopt(" <2> smart-host (Forward all outbound mail to this host)\n");
393 keyopt(" <3> directory (Consult the Global Address Book)\n");
394 keyopt(" <4> SpamAssassin (Address of SpamAssassin server)\n");
395 keyopt(" <5> RBL (domain suffix of spam hunting RBL)\n");
396 keyopt(" <6> masq domains (Domains as which users are allowed to masquerade)\n");
397 keyopt(" <7> ClamAV (Address of ClamAV clamd server)\n");
398 sel
= intprompt("Which one", 1, 1, 7);
400 case 1: strcpy(buf
, "localhost");
402 case 2: strcpy(buf
, "smarthost");
404 case 3: strcpy(buf
, "directory");
406 case 4: strcpy(buf
, "spamassassin");
408 case 5: strcpy(buf
, "rbl");
410 case 6: strcpy(buf
, "masqdomain");
412 case 7: strcpy(buf
, "clamav");
419 * Internet mail configuration
421 void do_internet_configuration(CtdlIPC
*ipc
)
434 r
= CtdlIPCGetSystemConfigByType(ipc
, INTERNETCFG
, &resp
, buf
);
436 while (!IsEmptyStr(resp
)) {
437 extract_token(buf
, resp
, 0, '\n', sizeof buf
);
438 remove_token(resp
, 0, '\n');
440 if (num_recs
== 1) recs
= malloc(sizeof(char *));
441 else recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
442 recs
[num_recs
-1] = malloc(strlen(buf
) + 1);
443 strcpy(recs
[num_recs
-1], buf
);
446 if (resp
) free(resp
);
451 scr_printf("### Host or domain Record type \n");
453 scr_printf("--- -------------------------------------------------- --------------------\n");
454 for (i
=0; i
<num_recs
; ++i
) {
456 scr_printf("%3d ", i
+1);
457 extract_token(buf
, recs
[i
], 0, '|', sizeof buf
);
459 scr_printf("%-50s ", buf
);
460 extract_token(buf
, recs
[i
], 1, '|', sizeof buf
);
461 color(BRIGHT_MAGENTA
);
462 scr_printf("%-20s\n", buf
);
466 ch
= keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
469 newprompt("Enter host name: ",
472 if (!IsEmptyStr(buf
)) {
475 recs
= malloc(sizeof(char *));
476 else recs
= realloc(recs
,
477 (sizeof(char *)) * num_recs
);
479 get_inet_rec_type(ipc
,
481 recs
[num_recs
-1] = strdup(buf
);
486 i
= intprompt("Delete which one",
490 for (j
=i
; j
<num_recs
; ++j
)
496 for (i
= 0; i
< num_recs
; i
++)
497 r
+= 1 + strlen(recs
[i
]);
498 resp
= (char *)calloc(1, r
);
500 err_printf("Can't save config - out of memory!\n");
503 if (num_recs
) for (i
= 0; i
< num_recs
; i
++) {
504 strcat(resp
, recs
[i
]);
507 r
= CtdlIPCSetSystemConfigByType(ipc
, INTERNETCFG
, resp
, buf
);
509 err_printf("%s\n", buf
);
511 scr_printf("Wrote %d records.\n", num_recs
);
517 quitting
= !modified
|| boolprompt(
518 "Quit without saving", 0);
526 for (i
=0; i
<num_recs
; ++i
) free(recs
[i
]);
534 * Edit network configuration for room sharing, mailing lists, etc.
536 void network_config_management(CtdlIPC
*ipc
, char *entrytype
, char *comment
)
538 char filename
[PATH_MAX
];
539 char changefile
[PATH_MAX
];
549 char *listing
= NULL
;
552 if (IsEmptyStr(editor_paths
[0])) {
553 scr_printf("You must have an external editor configured in"
554 " order to use this function.\n");
558 CtdlMakeTempFileName(filename
, sizeof filename
);
559 CtdlMakeTempFileName(changefile
, sizeof changefile
);
561 tempfp
= fopen(filename
, "w");
562 if (tempfp
== NULL
) {
563 err_printf("Cannot open %s: %s\n", filename
, strerror(errno
));
567 fprintf(tempfp
, "# Configuration for room: %s\n", room_name
);
568 fprintf(tempfp
, "# %s\n", comment
);
569 fprintf(tempfp
, "# Specify one per line.\n"
572 r
= CtdlIPCGetRoomNetworkConfig(ipc
, &listing
, buf
);
574 while(listing
&& !IsEmptyStr(listing
)) {
575 extract_token(buf
, listing
, 0, '\n', sizeof buf
);
576 remove_token(listing
, 0, '\n');
577 extract_token(instr
, buf
, 0, '|', sizeof instr
);
578 if (!strcasecmp(instr
, entrytype
)) {
579 tokens
= num_tokens(buf
, '|');
580 for (i
=1; i
<tokens
; ++i
) {
581 extract_token(addr
, buf
, i
, '|', sizeof addr
);
582 fprintf(tempfp
, "%s", addr
);
583 if (i
< (tokens
-1)) {
584 fprintf(tempfp
, "|");
587 fprintf(tempfp
, "\n");
597 e_ex_code
= 1; /* start with a failed exit code */
599 stty_ctdl(SB_RESTORE
);
601 cksum
= file_checksum(filename
);
602 if (editor_pid
== 0) {
603 chmod(filename
, 0600);
604 putenv("WINDOW_TITLE=Network configuration");
605 execlp(editor_paths
[0], editor_paths
[0], filename
, NULL
);
608 if (editor_pid
> 0) {
611 b
= ka_wait(&e_ex_code
);
612 } while ((b
!= editor_pid
) && (b
>= 0));
618 if (file_checksum(filename
) == cksum
) {
619 err_printf("*** No changes to save.\n");
623 if (e_ex_code
== 0) { /* Save changes */
624 changefp
= fopen(changefile
, "w");
626 /* Load all netconfig entries that are *not* of the type we are editing */
627 r
= CtdlIPCGetRoomNetworkConfig(ipc
, &listing
, buf
);
629 while(listing
&& !IsEmptyStr(listing
)) {
630 extract_token(buf
, listing
, 0, '\n', sizeof buf
);
631 remove_token(listing
, 0, '\n');
632 extract_token(instr
, buf
, 0, '|', sizeof instr
);
633 if (strcasecmp(instr
, entrytype
)) {
634 fprintf(changefp
, "%s\n", buf
);
643 /* ...and merge that with the data we just edited */
644 tempfp
= fopen(filename
, "r");
645 while (fgets(buf
, sizeof buf
, tempfp
) != NULL
) {
646 for (i
=0; i
<strlen(buf
); ++i
) {
647 if (buf
[i
] == '#') buf
[i
] = 0;
650 if (!IsEmptyStr(buf
)) {
651 fprintf(changefp
, "%s|%s\n", entrytype
, buf
);
657 /* now write it to the server... */
658 changefp
= fopen(changefile
, "r");
659 if (changefp
!= NULL
) {
660 listing
= load_message_from_file(changefp
);
662 r
= CtdlIPCSetRoomNetworkConfig(ipc
, listing
, buf
);
670 unlink(filename
); /* Delete the temporary files */
676 * IGnet node configuration
678 void do_ignet_configuration(CtdlIPC
*ipc
) {
687 char *listing
= NULL
;
690 r
= CtdlIPCGetSystemConfigByType(ipc
, IGNETCFG
, &listing
, buf
);
691 if (r
/ 100 == 1) while (*listing
&& !IsEmptyStr(listing
)) {
692 extract_token(buf
, listing
, 0, '\n', sizeof buf
);
693 remove_token(listing
, 0, '\n');
696 if (num_recs
== 1) recs
= malloc(sizeof(char *));
697 else recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
698 recs
[num_recs
-1] = malloc(SIZ
);
699 strcpy(recs
[num_recs
-1], buf
);
701 if (listing
) free(listing
);
714 "------------------ "
715 "-------------------------------- "
717 for (i
=0; i
<num_recs
; ++i
) {
719 scr_printf("%3d ", i
+1);
720 extract_token(buf
, recs
[i
], 0, '|', sizeof buf
);
722 scr_printf("%-16s ", buf
);
723 extract_token(buf
, recs
[i
], 1, '|', sizeof buf
);
724 color(BRIGHT_MAGENTA
);
725 scr_printf("%-18s ", buf
);
726 extract_token(buf
, recs
[i
], 2, '|', sizeof buf
);
728 scr_printf("%-32s ", buf
);
729 extract_token(buf
, recs
[i
], 3, '|', sizeof buf
);
730 color(BRIGHT_MAGENTA
);
731 scr_printf("%-3s\n", buf
);
736 ch
= keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
741 recs
= malloc(sizeof(char *));
742 else recs
= realloc(recs
,
743 (sizeof(char *)) * num_recs
);
744 newprompt("Enter node name : ", buf
, 16);
746 newprompt("Enter shared secret: ",
747 &buf
[strlen(buf
)], 18);
749 newprompt("Enter host or IP : ",
750 &buf
[strlen(buf
)], 32);
752 strprompt("Enter port number : ",
753 &buf
[strlen(buf
)-3], 5);
754 recs
[num_recs
-1] = strdup(buf
);
758 i
= intprompt("Delete which one",
762 for (j
=i
; j
<num_recs
; ++j
)
768 for (i
= 0; i
< num_recs
; ++i
)
769 r
+= 1 + strlen(recs
[i
]);
770 listing
= (char*) calloc(1, r
);
772 err_printf("Can't save config - out of memory!\n");
775 if (num_recs
) for (i
= 0; i
< num_recs
; ++i
) {
776 strcat(listing
, recs
[i
]);
777 strcat(listing
, "\n");
779 r
= CtdlIPCSetSystemConfigByType(ipc
, IGNETCFG
, listing
, buf
);
781 scr_printf("%s\n", buf
);
783 scr_printf("Wrote %d records.\n", num_recs
);
789 quitting
= !modified
|| boolprompt(
790 "Quit without saving", 0);
798 for (i
=0; i
<num_recs
; ++i
) free(recs
[i
]);
805 * Filter list configuration
807 void do_filterlist_configuration(CtdlIPC
*ipc
)
817 char *listing
= NULL
;
820 r
= CtdlIPCGetSystemConfigByType(ipc
, FILTERLIST
, &listing
, buf
);
821 if (r
/ 100 == 1) while (*listing
&& !IsEmptyStr(listing
)) {
822 extract_token(buf
, listing
, 0, '\n', sizeof buf
);
823 remove_token(listing
, 0, '\n');
826 if (num_recs
== 1) recs
= malloc(sizeof(char *));
827 else recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
828 recs
[num_recs
-1] = malloc(SIZ
);
829 strcpy(recs
[num_recs
-1], buf
);
831 if (listing
) free(listing
);
843 "---------------------------- "
844 "---------------------------- "
847 for (i
=0; i
<num_recs
; ++i
) {
849 scr_printf("%3d ", i
+1);
850 extract_token(buf
, recs
[i
], 0, '|', sizeof buf
);
852 scr_printf("%-28s ", buf
);
853 extract_token(buf
, recs
[i
], 1, '|', sizeof buf
);
854 color(BRIGHT_MAGENTA
);
855 scr_printf("%-28s ", buf
);
856 extract_token(buf
, recs
[i
], 2, '|', sizeof buf
);
858 scr_printf("%-16s\n", buf
);
859 extract_token(buf
, recs
[i
], 3, '|', sizeof buf
);
863 ch
= keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
868 recs
= malloc(sizeof(char *));
869 else recs
= realloc(recs
,
870 (sizeof(char *)) * num_recs
);
871 newprompt("Enter user name: ", buf
, 28);
873 newprompt("Enter room name: ",
874 &buf
[strlen(buf
)], 28);
876 newprompt("Enter node name: ",
877 &buf
[strlen(buf
)], 16);
879 recs
[num_recs
-1] = strdup(buf
);
883 i
= intprompt("Delete which one",
887 for (j
=i
; j
<num_recs
; ++j
)
893 for (i
= 0; i
< num_recs
; ++i
)
894 r
+= 1 + strlen(recs
[i
]);
895 listing
= (char*) calloc(1, r
);
897 err_printf("Can't save config - out of memory!\n");
900 if (num_recs
) for (i
= 0; i
< num_recs
; ++i
) {
901 strcat(listing
, recs
[i
]);
902 strcat(listing
, "\n");
904 r
= CtdlIPCSetSystemConfigByType(ipc
, FILTERLIST
, listing
, buf
);
906 scr_printf("%s\n", buf
);
908 scr_printf("Wrote %d records.\n", num_recs
);
914 quitting
= !modified
|| boolprompt(
915 "Quit without saving", 0);
923 for (i
=0; i
<num_recs
; ++i
) free(recs
[i
]);
932 * POP3 aggregation client configuration
934 void do_pop3client_configuration(CtdlIPC
*ipc
)
944 char *listing
= NULL
;
945 char *other_listing
= NULL
;
949 r
= CtdlIPCGetRoomNetworkConfig(ipc
, &listing
, buf
);
951 while(listing
&& !IsEmptyStr(listing
)) {
952 extract_token(buf
, listing
, 0, '\n', sizeof buf
);
953 remove_token(listing
, 0, '\n');
954 extract_token(instr
, buf
, 0, '|', sizeof instr
);
955 if (!strcasecmp(instr
, "pop3client")) {
958 if (num_recs
== 1) recs
= malloc(sizeof(char *));
959 else recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
960 recs
[num_recs
-1] = malloc(SIZ
);
961 strcpy(recs
[num_recs
-1], buf
);
982 "---------------------------- "
983 "---------------------------- "
987 for (i
=0; i
<num_recs
; ++i
) {
989 scr_printf("%3d ", i
+1);
991 extract_token(buf
, recs
[i
], 1, '|', sizeof buf
);
993 scr_printf("%-28s ", buf
);
995 extract_token(buf
, recs
[i
], 2, '|', sizeof buf
);
996 color(BRIGHT_MAGENTA
);
997 scr_printf("%-28s ", buf
);
1000 scr_printf("%-15s ", (extract_int(recs
[i
], 4) ? "Yes" : "No") );
1001 color(BRIGHT_MAGENTA
);
1002 scr_printf("%ld\n", extract_long(recs
[i
], 5) );
1006 ch
= keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1010 if (num_recs
== 1) {
1011 recs
= malloc(sizeof(char *));
1014 recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
1016 strcpy(buf
, "pop3client|");
1017 newprompt("Enter host name: ", &buf
[strlen(buf
)], 28);
1019 newprompt("Enter user name: ", &buf
[strlen(buf
)], 28);
1021 newprompt("Enter password : ", &buf
[strlen(buf
)], 16);
1023 scr_printf("Keep messages on server instead of deleting them? ");
1024 sprintf(&buf
[strlen(buf
)], "%d", yesno());
1026 newprompt("Enter interval : ", &buf
[strlen(buf
)], 5);
1028 recs
[num_recs
-1] = strdup(buf
);
1032 i
= intprompt("Delete which one",
1033 1, 1, num_recs
) - 1;
1036 for (j
=i
; j
<num_recs
; ++j
)
1037 recs
[j
] = recs
[j
+1];
1042 for (i
= 0; i
< num_recs
; ++i
) {
1043 r
+= 1 + strlen(recs
[i
]);
1045 listing
= (char*) calloc(1, r
);
1047 err_printf("Can't save config - out of memory!\n");
1050 if (num_recs
) for (i
= 0; i
< num_recs
; ++i
) {
1051 strcat(listing
, recs
[i
]);
1052 strcat(listing
, "\n");
1055 /* Retrieve all the *other* records for merging */
1056 r
= CtdlIPCGetRoomNetworkConfig(ipc
, &other_listing
, buf
);
1058 for (i
=0; i
<num_tokens(other_listing
, '\n'); ++i
) {
1059 extract_token(buf
, other_listing
, i
, '\n', sizeof buf
);
1060 if (strncasecmp(buf
, "pop3client|", 11)) {
1061 listing
= realloc(listing
, strlen(listing
) +
1063 strcat(listing
, buf
);
1064 strcat(listing
, "\n");
1068 free(other_listing
);
1069 r
= CtdlIPCSetRoomNetworkConfig(ipc
, listing
, buf
);
1074 scr_printf("%s\n", buf
);
1076 scr_printf("Wrote %d records.\n", num_recs
);
1082 quitting
= !modified
|| boolprompt(
1083 "Quit without saving", 0);
1088 } while (!quitting
);
1091 for (i
=0; i
<num_recs
; ++i
) free(recs
[i
]);
1102 * RSS feed retrieval client configuration
1104 void do_rssclient_configuration(CtdlIPC
*ipc
)
1114 char *listing
= NULL
;
1115 char *other_listing
= NULL
;
1119 r
= CtdlIPCGetRoomNetworkConfig(ipc
, &listing
, buf
);
1121 while(listing
&& !IsEmptyStr(listing
)) {
1122 extract_token(buf
, listing
, 0, '\n', sizeof buf
);
1123 remove_token(listing
, 0, '\n');
1124 extract_token(instr
, buf
, 0, '|', sizeof instr
);
1125 if (!strcasecmp(instr
, "rssclient")) {
1128 if (num_recs
== 1) recs
= malloc(sizeof(char *));
1129 else recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
1130 recs
[num_recs
-1] = malloc(SIZ
);
1131 strcpy(recs
[num_recs
-1], buf
);
1143 color(BRIGHT_WHITE
);
1144 scr_printf("### Feed URL\n");
1147 "---------------------------------------------------------------------------"
1150 for (i
=0; i
<num_recs
; ++i
) {
1152 scr_printf("%3d ", i
+1);
1154 extract_token(buf
, recs
[i
], 1, '|', sizeof buf
);
1156 scr_printf("%-75s\n", buf
);
1161 ch
= keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
1165 if (num_recs
== 1) {
1166 recs
= malloc(sizeof(char *));
1169 recs
= realloc(recs
, (sizeof(char *)) * num_recs
);
1171 strcpy(buf
, "rssclient|");
1172 newprompt("Enter feed URL: ", &buf
[strlen(buf
)], 75);
1174 recs
[num_recs
-1] = strdup(buf
);
1178 i
= intprompt("Delete which one", 1, 1, num_recs
) - 1;
1181 for (j
=i
; j
<num_recs
; ++j
)
1182 recs
[j
] = recs
[j
+1];
1187 for (i
= 0; i
< num_recs
; ++i
) {
1188 r
+= 1 + strlen(recs
[i
]);
1190 listing
= (char*) calloc(1, r
);
1192 err_printf("Can't save config - out of memory!\n");
1195 if (num_recs
) for (i
= 0; i
< num_recs
; ++i
) {
1196 strcat(listing
, recs
[i
]);
1197 strcat(listing
, "\n");
1200 /* Retrieve all the *other* records for merging */
1201 r
= CtdlIPCGetRoomNetworkConfig(ipc
, &other_listing
, buf
);
1203 for (i
=0; i
<num_tokens(other_listing
, '\n'); ++i
) {
1204 extract_token(buf
, other_listing
, i
, '\n', sizeof buf
);
1205 if (strncasecmp(buf
, "rssclient|", 10)) {
1206 listing
= realloc(listing
, strlen(listing
) +
1208 strcat(listing
, buf
);
1209 strcat(listing
, "\n");
1213 free(other_listing
);
1214 r
= CtdlIPCSetRoomNetworkConfig(ipc
, listing
, buf
);
1219 scr_printf("%s\n", buf
);
1221 scr_printf("Wrote %d records.\n", num_recs
);
1227 quitting
= !modified
|| boolprompt(
1228 "Quit without saving", 0);
1233 } while (!quitting
);
1236 for (i
=0; i
<num_recs
; ++i
) free(recs
[i
]);