* Implement a different way to delete a password from the cache.
[alpine.git] / alpine / ldapconf.c
blob5ccc61bed5ff98eb22b3accadb8a2ce2a7b44f2c
1 /*
2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2006-2008 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include "headers.h"
16 #include "ldapconf.h"
17 #include "keymenu.h"
18 #include "radio.h"
19 #include "status.h"
20 #include "confscroll.h"
21 #include "adrbkcmd.h"
22 #include "titlebar.h"
23 #include "takeaddr.h"
24 #include "../pith/ldap.h"
25 #include "../pith/state.h"
26 #include "../pith/bitmap.h"
27 #include "../pith/mailcmd.h"
28 #include "../pith/list.h"
32 * Internal prototypes
34 #ifdef ENABLE_LDAP
35 int addr_select_tool(struct pine *, int, CONF_S **, unsigned);
36 void dir_init_display(struct pine *, CONF_S **, char **, struct variable *, CONF_S **);
37 int dir_config_tool(struct pine *, int, CONF_S **, unsigned);
38 void dir_config_add(struct pine *, CONF_S **);
39 void dir_config_shuffle(struct pine *, CONF_S **);
40 void dir_config_edit(struct pine *, CONF_S **);
41 int dir_edit_screen(struct pine *, LDAP_SERV_S *, char *, char **);
42 int dir_edit_tool(struct pine *, int, CONF_S **, unsigned);
43 void dir_config_del(struct pine *, CONF_S **);
44 void add_ldap_fake_first_server(struct pine *, CONF_S **, struct variable *,
45 struct key_menu *, HelpType,
46 int (*)(struct pine *, int, CONF_S **, unsigned));
47 void add_ldap_server_to_display(struct pine *, CONF_S **, char *, char *,
48 struct variable *, int, struct key_menu *, HelpType,
49 int (*)(struct pine *, int, CONF_S **, unsigned),
50 int, CONF_S **);
51 int ldap_checkbox_tool(struct pine *, int, CONF_S **, unsigned);
52 void toggle_ldap_option_bit(struct pine *, int, struct variable *, char *);
53 NAMEVAL_S *ldap_feature_list(int);
56 static char *srch_res_help_title = N_("HELP FOR SEARCH RESULTS INDEX");
57 static char *set_choose = "--- ----------------------";
58 #define ADD_FIRST_LDAP_SERVER _("Use Add to add a directory server")
59 #define ADDR_SELECT_EXIT_VAL 5
60 #define ADDR_SELECT_GOBACK_VAL 6
61 #define ADDR_SELECT_FORCED_EXIT_VAL 7
64 static int some_selectable;
65 static char *dserv = N_("Directory Server on ");
68 * Let user choose an ldap entry (or return an entry if user doesn't need
69 * to be consulted).
71 * Returns 0 if ok,
72 * -1 if Exit was chosen
73 * -2 if none were selectable
74 * -3 if no entries existed at all
75 * -4 go back to Abook List was chosen
76 * -5 caller shouldn't free ac->res_head
78 * When 0 is returned the winner is pointed to by result.
79 * Result is an allocated LDAP_SEARCH_WINNER_S which has pointers
80 * to the ld and entry that were chosen. Those are pointers into
81 * the initial data, not copies. The two-pointer structure is
82 * allocated here and freed by the caller.
84 int
85 ldap_addr_select(struct pine *ps, ADDR_CHOOSE_S *ac, LDAP_CHOOSE_S **result,
86 LDAPLookupStyle style, WP_ERR_S *wp_err, char *srchstr)
88 LDAPMessage *e;
89 LDAP_SERV_RES_S *res_list;
90 CONF_S *ctmpa = NULL, *first_line = NULL, *alt_first_line = NULL;
91 int i, retval = 0, got_n_mail = 0, got_n_entries = 0;
92 int need_mail;
93 OPT_SCREEN_S screen;
94 struct key_menu *km;
95 char ee[200];
96 HelpType help;
97 void (*prev_redrawer) (void);
99 dprint((4, "ldap_addr_select()\n"));
101 need_mail = (style == AlwaysDisplay || style == DisplayForURL) ? 0 : 1;
102 if(style == AlwaysDisplay){
103 km = &addr_s_km_with_view;
104 help = h_address_display;
106 else if(style == AlwaysDisplayAndMailRequired){
107 km = &addr_s_km_with_goback;
108 help = h_address_select;
110 else if(style == DisplayForURL){
111 km = &addr_s_km_for_url;
112 help = h_address_display;
114 else{
115 km = &addr_s_km;
116 help = h_address_select;
119 if(result)
120 *result = NULL;
122 some_selectable = 0;
124 for(res_list = ac->res_head; res_list; res_list = res_list->next){
125 for(e = ldap_first_entry(res_list->ld, res_list->res);
126 e != NULL;
127 e = ldap_next_entry(res_list->ld, e)){
128 char *dn, *a;
129 struct berval **cn, **org, **unit, **title, **mail, **sn;
130 BerElement *ber;
131 int indent, have_mail;
133 dn = NULL;
134 cn = org = title = unit = mail = sn = NULL;
135 for(a = ldap_first_attribute(res_list->ld, e, &ber);
136 a != NULL;
137 a = ldap_next_attribute(res_list->ld, e, ber)){
139 dprint((9, " %s", a ? a : "?"));
140 if(strcmp(a, res_list->info_used->cnattr) == 0){
141 if(!cn)
142 cn = ldap_get_values_len(res_list->ld, e, a);
144 if(cn && !ALPINE_LDAP_can_use(cn)){
145 ldap_value_free_len(cn);
146 cn = NULL;
149 else if(strcmp(a, res_list->info_used->mailattr) == 0){
150 if(!mail)
151 mail = ldap_get_values_len(res_list->ld, e, a);
153 else if(strcmp(a, "o") == 0){
154 if(!org)
155 org = ldap_get_values_len(res_list->ld, e, a);
157 else if(strcmp(a, "ou") == 0){
158 if(!unit)
159 unit = ldap_get_values_len(res_list->ld, e, a);
161 else if(strcmp(a, "title") == 0){
162 if(!title)
163 title = ldap_get_values_len(res_list->ld, e, a);
166 our_ldap_memfree(a);
169 dprint((9, "\n"));
171 if(!cn){
172 for(a = ldap_first_attribute(res_list->ld, e, &ber);
173 a != NULL;
174 a = ldap_next_attribute(res_list->ld, e, ber)){
176 if(strcmp(a, res_list->info_used->snattr) == 0){
177 if(!sn)
178 sn = ldap_get_values_len(res_list->ld, e, a);
180 if(sn && !ALPINE_LDAP_can_use(sn)){
181 ldap_value_free_len(sn);
182 sn = NULL;
186 our_ldap_memfree(a);
190 if(ALPINE_LDAP_can_use(mail))
191 have_mail = 1;
192 else
193 have_mail = 0;
195 got_n_mail += have_mail;
196 got_n_entries++;
197 indent = 2;
200 * First line is either cn, sn, or dn.
202 if(cn){
203 new_confline(&ctmpa);
204 if(!alt_first_line)
205 alt_first_line = ctmpa;
207 ctmpa->flags |= CF_STARTITEM;
208 if(need_mail && !have_mail)
209 ctmpa->flags |= CF_PRIVATE;
211 ctmpa->value = cpystr(cn[0]->bv_val);
212 ldap_value_free_len(cn);
213 ctmpa->valoffset = indent;
214 ctmpa->keymenu = km;
215 ctmpa->help = help;
216 ctmpa->help_title = _(srch_res_help_title);
217 ctmpa->tool = addr_select_tool;
218 ctmpa->d.a.ld = res_list->ld;
219 ctmpa->d.a.entry = e;
220 ctmpa->d.a.info_used = res_list->info_used;
221 ctmpa->d.a.serv = res_list->serv;
222 ctmpa->d.a.ac = ac;
223 if(!first_line && (have_mail || !need_mail))
224 first_line = ctmpa;
227 /* only happens if no cn */
228 if(sn){
229 new_confline(&ctmpa);
230 if(!alt_first_line)
231 alt_first_line = ctmpa;
233 ctmpa->flags |= CF_STARTITEM;
234 if(need_mail && !have_mail)
235 ctmpa->flags |= CF_PRIVATE;
237 ctmpa->value = cpystr(sn[0]->bv_val);
238 ldap_value_free_len(sn);
239 ctmpa->valoffset = indent;
240 ctmpa->keymenu = km;
241 ctmpa->help = help;
242 ctmpa->help_title = _(srch_res_help_title);
243 ctmpa->tool = addr_select_tool;
244 ctmpa->d.a.ld = res_list->ld;
245 ctmpa->d.a.entry = e;
246 ctmpa->d.a.info_used = res_list->info_used;
247 ctmpa->d.a.serv = res_list->serv;
248 ctmpa->d.a.ac = ac;
249 if(!first_line && (have_mail || !need_mail))
250 first_line = ctmpa;
253 if(!sn && !cn){
254 new_confline(&ctmpa);
255 if(!alt_first_line)
256 alt_first_line = ctmpa;
258 ctmpa->flags |= CF_STARTITEM;
259 if(need_mail && !have_mail)
260 ctmpa->flags |= CF_PRIVATE;
262 dn = ldap_get_dn(res_list->ld, e);
264 if(dn && !dn[0]){
265 our_ldap_dn_memfree(dn);
266 dn = NULL;
269 ctmpa->value = cpystr(dn ? dn : "?");
270 if(dn)
271 our_ldap_dn_memfree(dn);
273 ctmpa->valoffset = indent;
274 ctmpa->keymenu = km;
275 ctmpa->help = help;
276 ctmpa->help_title = _(srch_res_help_title);
277 ctmpa->tool = addr_select_tool;
278 ctmpa->d.a.ld = res_list->ld;
279 ctmpa->d.a.entry = e;
280 ctmpa->d.a.info_used = res_list->info_used;
281 ctmpa->d.a.serv = res_list->serv;
282 ctmpa->d.a.ac = ac;
283 if(!first_line && (have_mail || !need_mail))
284 first_line = ctmpa;
287 if(title){
288 for(i = 0; ALPINE_LDAP_usable(title, i); i++){
289 new_confline(&ctmpa);
290 ctmpa->flags |= CF_NOSELECT;
291 ctmpa->valoffset = indent + 2;
292 ctmpa->value = cpystr(title[i]->bv_val);
293 ctmpa->keymenu = km;
294 ctmpa->help = help;
295 ctmpa->help_title = _(srch_res_help_title);
296 ctmpa->tool = addr_select_tool;
297 ctmpa->d.a.ld = res_list->ld;
298 ctmpa->d.a.entry = e;
299 ctmpa->d.a.info_used = res_list->info_used;
300 ctmpa->d.a.serv = res_list->serv;
301 ctmpa->d.a.ac = ac;
304 ldap_value_free_len(title);
307 if(unit){
308 for(i = 0; ALPINE_LDAP_usable(unit, i); i++){
309 new_confline(&ctmpa);
310 ctmpa->flags |= CF_NOSELECT;
311 ctmpa->valoffset = indent + 2;
312 ctmpa->value = cpystr(unit[i]->bv_val);
313 ctmpa->keymenu = km;
314 ctmpa->help = help;
315 ctmpa->help_title = _(srch_res_help_title);
316 ctmpa->tool = addr_select_tool;
317 ctmpa->d.a.ld = res_list->ld;
318 ctmpa->d.a.entry = e;
319 ctmpa->d.a.info_used = res_list->info_used;
320 ctmpa->d.a.serv = res_list->serv;
321 ctmpa->d.a.ac = ac;
324 ldap_value_free_len(unit);
327 if(org){
328 for(i = 0; ALPINE_LDAP_usable(org, i); i++){
329 new_confline(&ctmpa);
330 ctmpa->flags |= CF_NOSELECT;
331 ctmpa->valoffset = indent + 2;
332 ctmpa->value = cpystr(org[i]->bv_val);
333 ctmpa->keymenu = km;
334 ctmpa->help = help;
335 ctmpa->help_title = _(srch_res_help_title);
336 ctmpa->tool = addr_select_tool;
337 ctmpa->d.a.ld = res_list->ld;
338 ctmpa->d.a.entry = e;
339 ctmpa->d.a.info_used = res_list->info_used;
340 ctmpa->d.a.serv = res_list->serv;
341 ctmpa->d.a.ac = ac;
344 ldap_value_free_len(org);
347 if(have_mail){
348 /* Don't show long list of email addresses. */
349 if(!ALPINE_LDAP_can_use_num(mail, 0) ||
350 !ALPINE_LDAP_can_use_num(mail, 1) ||
351 !ALPINE_LDAP_can_use_num(mail, 2) ||
352 !ALPINE_LDAP_can_use_num(mail, 3)){
353 for(i = 0; ALPINE_LDAP_usable(mail, i); i++){
354 new_confline(&ctmpa);
355 ctmpa->flags |= CF_NOSELECT;
356 ctmpa->valoffset = indent + 2;
357 ctmpa->value = cpystr(mail[i]->bv_val);
358 ctmpa->keymenu = km;
359 ctmpa->help = help;
360 ctmpa->help_title = _(srch_res_help_title);
361 ctmpa->tool = addr_select_tool;
362 ctmpa->d.a.ld = res_list->ld;
363 ctmpa->d.a.entry = e;
364 ctmpa->d.a.info_used = res_list->info_used;
365 ctmpa->d.a.serv = res_list->serv;
366 ctmpa->d.a.ac = ac;
369 else{
370 char tmp[200];
372 for(i = 4; ALPINE_LDAP_usable(mail, i); i++)
375 new_confline(&ctmpa);
376 ctmpa->flags |= CF_NOSELECT;
377 ctmpa->valoffset = indent + 2;
378 snprintf(tmp, sizeof(tmp), _("(%d email addresses)"), i);
379 tmp[sizeof(tmp)-1] = '\0';
380 ctmpa->value = cpystr(tmp);
381 ctmpa->keymenu = km;
382 ctmpa->help = help;
383 ctmpa->help_title = _(srch_res_help_title);
384 ctmpa->tool = addr_select_tool;
385 ctmpa->d.a.ld = res_list->ld;
386 ctmpa->d.a.entry = e;
387 ctmpa->d.a.info_used = res_list->info_used;
388 ctmpa->d.a.serv = res_list->serv;
389 ctmpa->d.a.ac = ac;
392 else{
393 new_confline(&ctmpa);
394 ctmpa->flags |= CF_NOSELECT;
395 ctmpa->valoffset = indent + 2;
396 ctmpa->value = cpystr(_("<No Email Address Available>"));
397 ctmpa->keymenu = km;
398 ctmpa->help = help;
399 ctmpa->help_title = _(srch_res_help_title);
400 ctmpa->tool = addr_select_tool;
401 ctmpa->d.a.ld = res_list->ld;
402 ctmpa->d.a.entry = e;
403 ctmpa->d.a.info_used = res_list->info_used;
404 ctmpa->d.a.serv = res_list->serv;
405 ctmpa->d.a.ac = ac;
408 if(mail)
409 ldap_value_free_len(mail);
411 new_confline(&ctmpa); /* blank line */
412 ctmpa->keymenu = km;
413 ctmpa->help = help;
414 ctmpa->help_title = _(srch_res_help_title);
415 ctmpa->tool = addr_select_tool;
416 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
420 if(first_line)
421 some_selectable++;
422 else if(alt_first_line)
423 first_line = alt_first_line;
424 else{
425 new_confline(&ctmpa); /* blank line */
426 ctmpa->keymenu = need_mail ? &addr_s_km_exit : &addr_s_km_goback;
427 ctmpa->help = help;
428 ctmpa->help_title = _(srch_res_help_title);
429 ctmpa->tool = addr_select_tool;
430 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
432 new_confline(&ctmpa);
433 first_line = ctmpa;
434 strncpy(ee, "[ ", sizeof(ee));
435 ee[sizeof(ee)-1] = '\0';
436 if(wp_err && wp_err->ldap_errno)
437 /* TRANSLATORS: No matches returned for an LDAP search */
438 snprintf(ee+2, sizeof(ee)-2, _("%s, No Matches Returned"),
439 ldap_err2string(wp_err->ldap_errno));
440 else
441 strncpy(ee+2, _("No Matches"), sizeof(ee)-2);
443 ee[sizeof(ee)-1] = '\0';
445 /* TRANSLATORS: a request for user to choose Exit after they read text */
446 strncat(ee, _(" -- Choose Exit ]"), sizeof(ee)-strlen(ee)-1);
447 ee[sizeof(ee)-1] = '\0';
448 ctmpa->value = cpystr(ee);
449 ctmpa->valoffset = 10;
450 ctmpa->keymenu = need_mail ? &addr_s_km_exit : &addr_s_km_goback;
451 ctmpa->help = help;
452 ctmpa->help_title = _(srch_res_help_title);
453 ctmpa->tool = addr_select_tool;
454 ctmpa->flags |= CF_NOSELECT;
457 if(style == AlwaysDisplay || style == DisplayForURL ||
458 style == AlwaysDisplayAndMailRequired ||
459 (style == DisplayIfOne && got_n_mail >= 1) ||
460 (style == DisplayIfTwo && got_n_mail >= 1 && got_n_entries >= 2)){
461 if(wp_err && wp_err->mangled)
462 *wp_err->mangled = 1;
464 prev_redrawer = ps_global->redrawer;
465 push_titlebar_state();
467 memset(&screen, 0, sizeof(screen));
468 /* TRANSLATORS: Print something1 using something2.
469 "this" is something1 */
470 switch(conf_scroll_screen(ps,&screen,first_line,ac->title,_("this"),0, NULL)){
471 case ADDR_SELECT_EXIT_VAL:
472 retval = -1;
473 break;
475 case ADDR_SELECT_GOBACK_VAL:
476 retval = -4;
477 break;
479 case ADDR_SELECT_FORCED_EXIT_VAL:
480 if(alt_first_line) /* some entries, but none suitable */
481 retval = -2;
482 else
483 retval = -3;
485 break;
487 default:
488 retval = 0;
489 break;
492 ClearScreen();
493 pop_titlebar_state();
494 redraw_titlebar();
495 if((ps_global->redrawer = prev_redrawer) != NULL)
496 (*ps_global->redrawer)();
498 if(result && retval == 0 && ac->selected_ld && ac->selected_entry){
499 (*result) = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S));
500 (*result)->ld = ac->selected_ld;
501 (*result)->selected_entry = ac->selected_entry;
502 (*result)->info_used = ac->info_used;
503 (*result)->serv = ac->selected_serv;
506 else if(style == DisplayIfOne && got_n_mail < 1){
507 if(alt_first_line) /* some entries, but none suitable */
508 retval = -2;
509 else
510 retval = -3;
512 first_line = first_confline(ctmpa);
513 free_conflines(&first_line);
515 else if(style == DisplayIfTwo && (got_n_mail < 1 || got_n_entries < 2)){
516 if(got_n_mail < 1){
517 if(alt_first_line) /* some entries, but none suitable */
518 retval = -2;
519 else
520 retval = -3;
522 else{
523 retval = 0;
524 if(result){
525 (*result) = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S));
526 (*result)->ld = first_line->d.a.ld;
527 (*result)->selected_entry = first_line->d.a.entry;
528 (*result)->info_used = first_line->d.a.info_used;
529 (*result)->serv = first_line->d.a.serv;
533 first_line = first_confline(ctmpa);
534 free_conflines(&first_line);
537 return(retval);
542 addr_select_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
544 int retval = 0;
546 switch(cmd){
547 case MC_CHOICE :
548 if(flags & CF_PRIVATE){
549 q_status_message(SM_ORDER | SM_DING, 0, 3,
550 _("No email address available for this entry; choose another or ExitSelect"));
552 else if(some_selectable){
553 (*cl)->d.a.ac->selected_ld = (*cl)->d.a.ld;
554 (*cl)->d.a.ac->selected_entry = (*cl)->d.a.entry;
555 (*cl)->d.a.ac->info_used = (*cl)->d.a.info_used;
556 (*cl)->d.a.ac->selected_serv = (*cl)->d.a.serv;
557 retval = simple_exit_cmd(flags);
559 else
560 retval = ADDR_SELECT_FORCED_EXIT_VAL;
562 break;
564 case MC_VIEW_TEXT :
565 case MC_SAVE :
566 case MC_FWDTEXT :
567 case MC_COMPOSE :
568 case MC_ROLE :
569 {LDAP_CHOOSE_S *e;
571 if((*cl)->d.a.ld && (*cl)->d.a.entry){
572 e = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S));
573 e->ld = (*cl)->d.a.ld;
574 e->selected_entry = (*cl)->d.a.entry;
575 e->info_used = (*cl)->d.a.info_used;
576 e->serv = (*cl)->d.a.serv;
577 if(cmd == MC_VIEW_TEXT)
578 view_ldap_entry(ps, e);
579 else if(cmd == MC_SAVE)
580 save_ldap_entry(ps, e, 0);
581 else if(cmd == MC_COMPOSE)
582 compose_to_ldap_entry(ps, e, 0);
583 else if(cmd == MC_ROLE)
584 compose_to_ldap_entry(ps, e, 1);
585 else
586 forward_ldap_entry(ps, e);
588 fs_give((void **)&e);
592 break;
594 case MC_ADDRBOOK :
595 retval = ADDR_SELECT_GOBACK_VAL;
596 break;
598 case MC_EXIT :
599 retval = ADDR_SELECT_EXIT_VAL;
600 break;
602 default:
603 retval = -1;
604 break;
607 if(retval > 0)
608 ps->mangled_body = 1;
610 return(retval);
614 void
615 dir_init_display(struct pine *ps, CONF_S **ctmp, char **servers,
616 struct variable *var, CONF_S **first_line)
618 int i;
619 char *serv;
620 char *subtitle;
621 size_t sizeofsub;
622 LDAP_SERV_S *info;
624 if(first_line)
625 *first_line = NULL;
627 if(servers && servers[0] && servers[0][0]){
628 for(i = 0; servers[i]; i++){
629 info = break_up_ldap_server(servers[i]);
630 serv = (info && info->nick && *info->nick) ? cpystr(info->nick) :
631 (info && info->serv && *info->serv) ? cpystr(info->serv) :
632 cpystr(_("Bad Server Config, Delete this"));
633 sizeofsub = (((info && info->serv && *info->serv)
634 ? strlen(info->serv)
635 : 3) + strlen(_(dserv)) + 15) * sizeof(char);
636 subtitle = (char *)fs_get(sizeofsub);
637 if(info && info->port >= 0)
638 snprintf(subtitle, sizeofsub, "%s%s:%d",
639 _(dserv),
640 (info && info->serv && *info->serv) ? info->serv : "<?>",
641 info->port);
642 else
643 snprintf(subtitle, sizeofsub, "%s%s",
644 _(dserv),
645 (info && info->serv && *info->serv) ? info->serv : "<?>");
647 subtitle[sizeofsub-1] = '\0';
649 add_ldap_server_to_display(ps, ctmp, serv, subtitle, var,
650 i, &dir_conf_km, h_direct_config,
651 dir_config_tool, 0,
652 (first_line && *first_line == NULL)
653 ? first_line
654 : NULL);
656 free_ldap_server_info(&info);
659 else{
660 add_ldap_fake_first_server(ps, ctmp, var,
661 &dir_conf_km, h_direct_config,
662 dir_config_tool);
663 if(first_line)
664 *first_line = *ctmp;
669 void
670 directory_config(struct pine *ps, int edit_exceptions)
672 CONF_S *ctmp = NULL, *first_line = NULL;
673 OPT_SCREEN_S screen;
674 int no_ex, readonly_warning = 0;
676 if(edit_exceptions){
677 q_status_message(SM_ORDER, 3, 7,
678 _("Exception Setup not implemented for directory"));
679 return;
682 ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
684 no_ex = (ps_global->ew_for_except_vars == Main);
686 if(ps->restricted)
687 readonly_warning = 1;
688 else{
689 PINERC_S *prc = NULL;
691 switch(ew){
692 case Main:
693 prc = ps->prc;
694 break;
695 case Post:
696 prc = ps->post_prc;
697 break;
698 default:
699 break;
702 readonly_warning = prc ? prc->readonly : 1;
703 if(prc && prc->quit_to_edit){
704 quit_to_edit_msg(prc);
705 return;
709 if(ps->fix_fixed_warning)
710 offer_to_fix_pinerc(ps);
712 dir_init_display(ps, &ctmp, no_ex ? ps->VAR_LDAP_SERVERS
713 : LVAL(&ps->vars[V_LDAP_SERVERS], ew),
714 &ps->vars[V_LDAP_SERVERS], &first_line);
716 memset(&screen, 0, sizeof(screen));
717 screen.deferred_ro_warning = readonly_warning;
718 /* TRANSLATORS: Print something1 using something2.
719 "servers" is something1 */
720 (void)conf_scroll_screen(ps, &screen, first_line,
721 _("SETUP DIRECTORY SERVERS"), _("servers"), 0, NULL);
722 ps->mangled_screen = 1;
727 dir_config_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
729 int first_one, rv = 0;
731 first_one = (*cl)->value &&
732 (strcmp((*cl)->value, ADD_FIRST_LDAP_SERVER) == 0);
733 switch(cmd){
734 case MC_DELETE :
735 if(first_one)
736 q_status_message(SM_ORDER|SM_DING, 0, 3,
737 _("Nothing to Delete, use Add"));
738 else
739 dir_config_del(ps, cl);
741 break;
743 case MC_ADD :
744 if(!fixed_var((*cl)->var, NULL, "directory list"))
745 dir_config_add(ps, cl);
747 break;
749 case MC_EDIT :
750 if(!fixed_var((*cl)->var, NULL, "directory list")){
751 if(first_one)
752 dir_config_add(ps, cl);
753 else
754 dir_config_edit(ps, cl);
757 break;
759 case MC_SHUFFLE :
760 if(!fixed_var((*cl)->var, NULL, "directory list")){
761 if(first_one)
762 q_status_message(SM_ORDER|SM_DING, 0, 3,
763 _("Nothing to Shuffle, use Add"));
764 else
765 dir_config_shuffle(ps, cl);
768 break;
770 case MC_EXIT :
771 rv = 2;
772 break;
774 default:
775 rv = -1;
776 break;
779 return(rv);
784 * Add LDAP directory entry
786 void
787 dir_config_add(struct pine *ps, CONF_S **cl)
789 char *raw_server = NULL;
790 LDAP_SERV_S *info = NULL;
791 char **lval;
792 int no_ex;
794 no_ex = (ps_global->ew_for_except_vars == Main);
796 if(dir_edit_screen(ps, NULL, "ADD A", &raw_server) == 1){
798 info = break_up_ldap_server(raw_server);
800 if(info && info->serv && *info->serv){
801 char *subtitle;
802 size_t sizeofsub;
803 int i, cnt = 0;
804 char **new_list;
805 CONF_S *cp;
807 lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
808 if(lval)
809 while(lval[cnt])
810 cnt++;
812 /* catch the special "" case */
813 if(cnt == 0 ||
814 (cnt == 1 && lval[0][0] == '\0')){
815 new_list = (char **)fs_get((1 + 1) * sizeof(char *));
816 new_list[0] = raw_server;
817 new_list[1] = NULL;
819 else{
820 /* add one for new value */
821 cnt++;
822 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
824 for(i = 0; i < (*cl)->varmem; i++)
825 new_list[i] = cpystr(lval[i]);
827 new_list[(*cl)->varmem] = raw_server;
829 for(i = (*cl)->varmem; i < cnt; i++)
830 new_list[i+1] = cpystr(lval[i]);
833 raw_server = NULL;
834 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
835 free_list_array(&new_list);
836 set_current_val((*cl)->var, TRUE, FALSE);
837 sizeofsub = (((info && info->serv && *info->serv)
838 ? strlen(info->serv)
839 : 3) + strlen(_(dserv)) + 15) * sizeof(char);
840 subtitle = (char *)fs_get(sizeofsub);
841 if(info && info->port >= 0)
842 snprintf(subtitle, sizeofsub, "%s%s:%d",
843 _(dserv),
844 (info && info->serv && *info->serv) ? info->serv : "<?>",
845 info->port);
846 else
847 snprintf(subtitle, sizeofsub, "%s%s",
848 _(dserv),
849 (info && info->serv && *info->serv) ? info->serv : "<?>");
851 subtitle[sizeofsub-1] = '\0';
853 if(cnt < 2){ /* first one */
854 struct variable *var;
855 struct key_menu *keymenu;
856 HelpType help;
857 int (*tool)(struct pine *, int, CONF_S **, unsigned);
859 var = (*cl)->var;
860 keymenu = (*cl)->keymenu;
861 help = (*cl)->help;
862 tool = (*cl)->tool;
863 *cl = first_confline(*cl);
864 free_conflines(cl);
865 add_ldap_server_to_display(ps, cl,
866 (info && info->nick && *info->nick)
867 ? cpystr(info->nick)
868 : cpystr(info->serv),
869 subtitle, var, 0, keymenu, help,
870 tool, 0, NULL);
872 opt_screen->top_line = NULL;
874 else{
876 * Insert new server.
878 add_ldap_server_to_display(ps, cl,
879 (info && info->nick && *info->nick)
880 ? cpystr(info->nick)
881 : cpystr(info->serv),
882 subtitle,
883 (*cl)->var,
884 (*cl)->varmem,
885 (*cl)->keymenu,
886 (*cl)->help,
887 (*cl)->tool,
889 NULL);
890 /* adjust the rest of the varmems */
891 for(cp = (*cl)->next; cp; cp = cp->next)
892 cp->varmem++;
895 /* because add_ldap advanced cl to its third line */
896 (*cl) = (*cl)->prev->prev;
898 fix_side_effects(ps, (*cl)->var, 0);
899 write_pinerc(ps, ew, WRP_NONE);
901 else
902 q_status_message(SM_ORDER, 0, 3, _("Add cancelled, no server name"));
905 free_ldap_server_info(&info);
906 if(raw_server)
907 fs_give((void **)&raw_server);
912 * Shuffle order of LDAP directory entries
914 void
915 dir_config_shuffle(struct pine *ps, CONF_S **cl)
917 int cnt, rv, current_num, new_num = 0, i, j, deefault;
918 char **new_list, **lval;
919 char tmp[200];
920 HelpType help;
921 ESCKEY_S opts[3];
922 CONF_S *a = NULL, *b = NULL;
923 int no_ex;
925 no_ex = (ps_global->ew_for_except_vars == Main);
927 /* how many are in our current list? */
928 lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
929 for(cnt = 0; lval && lval[cnt]; cnt++)
932 if(cnt < 2){
933 q_status_message(SM_ORDER, 0, 3,
934 _("Shuffle only makes sense when there is more than one server in list"));
935 return;
938 current_num = (*cl)->varmem; /* variable number of highlighted directory */
940 /* Move it up or down? */
941 i = 0;
942 opts[i].ch = 'u';
943 opts[i].rval = 'u';
944 opts[i].name = "U";
945 opts[i++].label = _("Up");
947 opts[i].ch = 'd';
948 opts[i].rval = 'd';
949 opts[i].name = "D";
950 opts[i++].label = _("Down");
952 opts[i].ch = -1;
953 deefault = 'u';
955 if(current_num == 0){ /* no up */
956 opts[0].ch = -2;
957 deefault = 'd';
959 else if(current_num == cnt - 1) /* no down */
960 opts[1].ch = -2;
962 snprintf(tmp, sizeof(tmp), "Shuffle \"%s\" %s%s%s ? ",
963 (*cl)->value,
964 (opts[0].ch != -2) ? _("UP") : "",
965 (opts[0].ch != -2 && opts[1].ch != -2) ? " or " : "",
966 (opts[1].ch != -2) ? _("DOWN") : "");
967 tmp[sizeof(tmp)-1] = '\0';
968 help = (opts[0].ch == -2) ? h_dir_shuf_down
969 : (opts[1].ch == -2) ? h_dir_shuf_up
970 : h_dir_shuf;
972 rv = radio_buttons(tmp, -FOOTER_ROWS(ps), opts, deefault, 'x',
973 help, RB_NORM);
975 switch(rv){
976 case 'x':
977 cmd_cancelled("Shuffle");
978 return;
980 case 'u':
981 new_num = current_num - 1;
982 a = (*cl)->prev->prev->prev;
983 b = *cl;
984 break;
986 case 'd':
987 new_num = current_num + 1;
988 a = *cl;
989 b = (*cl)->next->next->next;
990 break;
993 /* allocate space for new list */
994 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
996 /* fill in new_list */
997 for(i = 0; i < cnt; i++){
998 if(i == current_num)
999 j = new_num;
1000 else if (i == new_num)
1001 j = current_num;
1002 else
1003 j = i;
1005 /* notice this works even if we were using default */
1006 new_list[i] = cpystr(lval[j]);
1009 new_list[i] = NULL;
1011 j = set_variable_list((*cl)->var - ps->vars, new_list, TRUE, ew);
1012 free_list_array(&new_list);
1013 if(j){
1014 q_status_message(SM_ORDER, 0, 3,
1015 _("Shuffle cancelled: couldn't save configuration file"));
1016 set_current_val((*cl)->var, TRUE, FALSE);
1017 return;
1020 set_current_val((*cl)->var, TRUE, FALSE);
1022 if(a == opt_screen->top_line)
1023 opt_screen->top_line = b;
1025 j = a->varmem;
1026 a->varmem = b->varmem;
1027 b->varmem = j;
1030 * Swap display lines. To start with, a is lower in list, b is higher.
1031 * The fact that there are 3 lines per entry is totally entangled in
1032 * the code.
1034 a->next->next->next = b->next->next->next;
1035 if(b->next->next->next)
1036 b->next->next->next->prev = a->next->next;
1037 b->prev = a->prev;
1038 if(a->prev)
1039 a->prev->next = b;
1040 b->next->next->next = a;
1041 a->prev = b->next->next;
1043 ps->mangled_body = 1;
1044 write_pinerc(ps, ew, WRP_NONE);
1049 * Edit LDAP directory entry
1051 void
1052 dir_config_edit(struct pine *ps, CONF_S **cl)
1054 char *raw_server = NULL, **lval;
1055 LDAP_SERV_S *info;
1056 int no_ex;
1058 no_ex = (ps_global->ew_for_except_vars == Main);
1060 lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
1061 info = break_up_ldap_server((lval && lval[(*cl)->varmem])
1062 ? lval[(*cl)->varmem] : NULL);
1064 if(dir_edit_screen(ps, info, "CHANGE THIS", &raw_server) == 1){
1066 free_ldap_server_info(&info);
1067 info = break_up_ldap_server(raw_server);
1069 if(lval && lval[(*cl)->varmem] &&
1070 strcmp(lval[(*cl)->varmem], raw_server) == 0)
1071 q_status_message(SM_ORDER, 0, 3, _("No change, cancelled"));
1072 else if(!(info && info->serv && *info->serv))
1073 q_status_message(SM_ORDER, 0, 3,
1074 _("Change cancelled, use Delete if you want to remove this server"));
1075 else{
1076 char *subtitle;
1077 int i, cnt;
1078 char **new_list;
1079 size_t sizeofsub;
1081 for(cnt = 0; lval && lval[cnt]; cnt++)
1084 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
1086 for(i = 0; i < (*cl)->varmem; i++)
1087 new_list[i] = cpystr(lval[i]);
1089 new_list[(*cl)->varmem] = raw_server;
1090 raw_server = NULL;
1092 for(i = (*cl)->varmem + 1; i < cnt; i++)
1093 new_list[i] = cpystr(lval[i]);
1095 new_list[cnt] = NULL;
1096 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
1097 free_list_array(&new_list);
1098 set_current_val((*cl)->var, TRUE, FALSE);
1100 if((*cl)->value)
1101 fs_give((void **)&(*cl)->value);
1103 (*cl)->value = cpystr((info->nick && *info->nick) ? info->nick
1104 : info->serv);
1106 if((*cl)->next->value)
1107 fs_give((void **)&(*cl)->next->value);
1109 sizeofsub = (((info && info->serv && *info->serv)
1110 ? strlen(info->serv)
1111 : 3) + strlen(_(dserv)) + 15) * sizeof(char);
1113 subtitle = (char *)fs_get(sizeofsub);
1114 if(info && info->port >= 0)
1115 snprintf(subtitle, sizeofsub, "%s%s:%d",
1116 _(dserv),
1117 (info && info->serv && *info->serv) ? info->serv : "<?>",
1118 info->port);
1119 else
1120 snprintf(subtitle, sizeofsub, "%s%s",
1121 _(dserv),
1122 (info && info->serv && *info->serv) ? info->serv : "<?>");
1124 subtitle[sizeofsub] = '\0';
1126 (*cl)->next->value = subtitle;
1128 fix_side_effects(ps, (*cl)->var, 0);
1129 write_pinerc(ps, ew, WRP_NONE);
1133 free_ldap_server_info(&info);
1134 if(raw_server)
1135 fs_give((void **)&raw_server);
1139 #define LDAP_F_IMPL 0
1140 #define LDAP_F_RHS 1
1141 #define LDAP_F_REF 2
1142 #define LDAP_F_NOSUB 3
1143 #define LDAP_F_TLS 4
1144 #define LDAP_F_TLSMUST 5
1145 #define LDAP_F_LDAPS 6
1146 bitmap_t ldap_option_list;
1147 struct variable *ldap_srch_rule_ptr;
1150 * Gives user screen to edit config values for ldap server.
1152 * Args ps -- pine struct
1153 * def -- default values to start with
1154 * title -- part of title at top of screen
1155 * raw_server -- This is the returned item, allocated here and freed by caller.
1157 * Returns: 0 if no change
1158 * 1 if user requested a change
1159 * (change is stored in raw_server and hasn't been acted upon yet)
1160 * 10 user says abort
1163 dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_server)
1165 OPT_SCREEN_S screen, *saved_screen;
1166 CONF_S *ctmp = NULL, *ctmpb, *first_line = NULL;
1167 char tmp[MAXPATH+1], custom_scope[MAXPATH], **apval;
1168 int rv, i, j, lv, indent, rindent;
1169 NAMEVAL_S *f;
1170 struct variable server_var, base_var, binddn_var, port_var, nick_var,
1171 srch_type_var, srch_rule_var, time_var,
1172 size_var, mailattr_var, cnattr_var,
1173 snattr_var, gnattr_var, cust_var,
1174 opt_var, *v, *varlist[21];
1175 char *server = NULL, *base = NULL, *port = NULL, *nick = NULL,
1176 *srch_type = NULL, *srch_rule = NULL, *ttime = NULL,
1177 *c_s_f = "custom-search-filter", *binddn = NULL,
1178 *ssize = NULL, *mailattr = NULL, *cnattr = NULL,
1179 *snattr = NULL, *gnattr = NULL, *cust = NULL;
1182 * We edit by making a nested call to conf_scroll_screen.
1183 * We use some fake struct variables to get back the results in, and
1184 * so we can use the existing tools from the config screen.
1187 custom_scope[0] = '\0';
1189 varlist[j = 0] = &server_var;
1190 varlist[++j] = &base_var;
1191 varlist[++j] = &port_var;
1192 varlist[++j] = &binddn_var;
1193 varlist[++j] = &nick_var;
1194 varlist[++j] = &srch_type_var;
1195 varlist[++j] = &srch_rule_var;
1196 varlist[++j] = &time_var;
1197 varlist[++j] = &size_var;
1198 varlist[++j] = &mailattr_var;
1199 varlist[++j] = &cnattr_var;
1200 varlist[++j] = &snattr_var;
1201 varlist[++j] = &gnattr_var;
1202 varlist[++j] = &cust_var;
1203 varlist[++j] = &opt_var;
1204 varlist[++j] = NULL;
1205 for(j = 0; varlist[j]; j++)
1206 memset(varlist[j], 0, sizeof(struct variable));
1208 server_var.name = cpystr("ldap-server");
1209 server_var.is_used = 1;
1210 server_var.is_user = 1;
1211 apval = APVAL(&server_var, ew);
1212 *apval = (def && def->serv && def->serv[0]) ? cpystr(def->serv) : NULL;
1213 set_current_val(&server_var, FALSE, FALSE);
1215 base_var.name = cpystr("search-base");
1216 base_var.is_used = 1;
1217 base_var.is_user = 1;
1218 apval = APVAL(&base_var, ew);
1219 *apval = (def && def->base && def->base[0]) ? cpystr(def->base) : NULL;
1220 set_current_val(&base_var, FALSE, FALSE);
1222 port_var.name = cpystr("port");
1223 port_var.is_used = 1;
1224 port_var.is_user = 1;
1225 if(def && def->port >= 0){
1226 apval = APVAL(&port_var, ew);
1227 *apval = cpystr(int2string(def->port));
1230 port_var.global_val.p = cpystr(int2string(LDAP_PORT));
1231 set_current_val(&port_var, FALSE, FALSE);
1233 binddn_var.name = cpystr("bind-dn");
1234 binddn_var.is_used = 1;
1235 binddn_var.is_user = 1;
1236 apval = APVAL(&binddn_var, ew);
1237 *apval = (def && def->binddn && def->binddn[0]) ? cpystr(def->binddn) : NULL;
1238 set_current_val(&binddn_var, FALSE, FALSE);
1240 nick_var.name = cpystr("nickname");
1241 nick_var.is_used = 1;
1242 nick_var.is_user = 1;
1243 apval = APVAL(&nick_var, ew);
1244 *apval = (def && def->nick && def->nick[0]) ? cpystr(def->nick) : NULL;
1245 set_current_val(&nick_var, FALSE, FALSE);
1247 srch_type_var.name = cpystr("search-type");
1248 srch_type_var.is_used = 1;
1249 srch_type_var.is_user = 1;
1250 apval = APVAL(&srch_type_var, ew);
1251 *apval = (f=ldap_search_types(def ? def->type : -1))
1252 ? cpystr(f->name) : NULL;
1253 srch_type_var.global_val.p =
1254 (f=ldap_search_types(DEF_LDAP_TYPE)) ? cpystr(f->name) : NULL;
1255 set_current_val(&srch_type_var, FALSE, FALSE);
1257 ldap_srch_rule_ptr = &srch_rule_var; /* so radiobuttons can tell */
1258 srch_rule_var.name = cpystr("search-rule");
1259 srch_rule_var.is_used = 1;
1260 srch_rule_var.is_user = 1;
1261 apval = APVAL(&srch_rule_var, ew);
1262 *apval = (f=ldap_search_rules(def ? def->srch : -1))
1263 ? cpystr(f->name) : NULL;
1264 srch_rule_var.global_val.p =
1265 (f=ldap_search_rules(DEF_LDAP_SRCH)) ? cpystr(f->name) : NULL;
1266 set_current_val(&srch_rule_var, FALSE, FALSE);
1268 time_var.name = cpystr("timelimit");
1269 time_var.is_used = 1;
1270 time_var.is_user = 1;
1271 if(def && def->time >= 0){
1272 apval = APVAL(&time_var, ew);
1273 *apval = cpystr(int2string(def->time));
1276 time_var.global_val.p = cpystr(int2string(DEF_LDAP_TIME));
1277 set_current_val(&time_var, FALSE, FALSE);
1279 size_var.name = cpystr("sizelimit");
1280 size_var.is_used = 1;
1281 size_var.is_user = 1;
1282 if(def && def->size >= 0){
1283 apval = APVAL(&size_var, ew);
1284 *apval = cpystr(int2string(def->size));
1287 size_var.global_val.p = cpystr(int2string(DEF_LDAP_SIZE));
1288 set_current_val(&size_var, FALSE, FALSE);
1290 mailattr_var.name = cpystr("email-attribute");
1291 mailattr_var.is_used = 1;
1292 mailattr_var.is_user = 1;
1293 apval = APVAL(&mailattr_var, ew);
1294 *apval = (def && def->mailattr && def->mailattr[0])
1295 ? cpystr(def->mailattr) : NULL;
1296 mailattr_var.global_val.p = cpystr(DEF_LDAP_MAILATTR);
1297 set_current_val(&mailattr_var, FALSE, FALSE);
1299 cnattr_var.name = cpystr("name-attribute");
1300 cnattr_var.is_used = 1;
1301 cnattr_var.is_user = 1;
1302 apval = APVAL(&cnattr_var, ew);
1303 *apval = (def && def->cnattr && def->cnattr[0])
1304 ? cpystr(def->cnattr) : NULL;
1305 cnattr_var.global_val.p = cpystr(DEF_LDAP_CNATTR);
1306 set_current_val(&cnattr_var, FALSE, FALSE);
1308 snattr_var.name = cpystr("surname-attribute");
1309 snattr_var.is_used = 1;
1310 snattr_var.is_user = 1;
1311 apval = APVAL(&snattr_var, ew);
1312 *apval = (def && def->snattr && def->snattr[0])
1313 ? cpystr(def->snattr) : NULL;
1314 snattr_var.global_val.p = cpystr(DEF_LDAP_SNATTR);
1315 set_current_val(&snattr_var, FALSE, FALSE);
1317 gnattr_var.name = cpystr("givenname-attribute");
1318 gnattr_var.is_used = 1;
1319 gnattr_var.is_user = 1;
1320 apval = APVAL(&gnattr_var, ew);
1321 *apval = (def && def->gnattr && def->gnattr[0])
1322 ? cpystr(def->gnattr) : NULL;
1323 gnattr_var.global_val.p = cpystr(DEF_LDAP_GNATTR);
1324 set_current_val(&gnattr_var, FALSE, FALSE);
1326 cust_var.name = cpystr(c_s_f);
1327 cust_var.is_used = 1;
1328 cust_var.is_user = 1;
1329 apval = APVAL(&cust_var, ew);
1330 *apval = (def && def->cust && def->cust[0]) ? cpystr(def->cust) : NULL;
1331 set_current_val(&cust_var, FALSE, FALSE);
1333 /* TRANSLATORS: Features is a section title in the LDAP configuration screen. Following
1334 this are a list of features or options that can be turned on or off. */
1335 opt_var.name = cpystr(_("Features"));
1336 opt_var.is_used = 1;
1337 opt_var.is_user = 1;
1338 opt_var.is_list = 1;
1339 clrbitmap(ldap_option_list);
1340 if(def && def->impl)
1341 setbitn(LDAP_F_IMPL, ldap_option_list);
1342 if(def && def->rhs)
1343 setbitn(LDAP_F_RHS, ldap_option_list);
1344 if(def && def->ref)
1345 setbitn(LDAP_F_REF, ldap_option_list);
1346 if(def && def->nosub)
1347 setbitn(LDAP_F_NOSUB, ldap_option_list);
1348 if(def && def->tls)
1349 setbitn(LDAP_F_TLS, ldap_option_list);
1350 if(def && def->tlsmust)
1351 setbitn(LDAP_F_TLSMUST, ldap_option_list);
1352 if(def && def->ldaps)
1353 setbitn(LDAP_F_LDAPS, ldap_option_list);
1355 /* save the old opt_screen before calling scroll screen again */
1356 saved_screen = opt_screen;
1358 indent = utf8_width(c_s_f) + 3;
1359 rindent = 12;
1361 /* Server */
1362 new_confline(&ctmp);
1363 ctmp->help_title= _("HELP FOR LDAP SERVER");
1364 ctmp->var = &server_var;
1365 ctmp->valoffset = indent;
1366 ctmp->keymenu = &config_text_keymenu;
1367 ctmp->help = h_config_ldap_server;
1368 ctmp->tool = dir_edit_tool;
1369 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,server_var.name);
1370 tmp[sizeof(tmp)-1] = '\0';
1371 ctmp->varname = cpystr(tmp);
1372 ctmp->varnamep = ctmp;
1373 ctmp->value = pretty_value(ps, ctmp);
1375 first_line = ctmp;
1377 /* Search Base */
1378 new_confline(&ctmp);
1379 ctmp->help_title= _("HELP FOR SERVER SEARCH BASE");
1380 ctmp->var = &base_var;
1381 ctmp->valoffset = indent;
1382 ctmp->keymenu = &config_text_keymenu;
1383 ctmp->help = h_config_ldap_base;
1384 ctmp->tool = dir_edit_tool;
1385 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,base_var.name);
1386 tmp[sizeof(tmp)-1] = '\0';
1387 ctmp->varname = cpystr(tmp);
1388 ctmp->varnamep = ctmp;
1389 ctmp->value = pretty_value(ps, ctmp);
1391 /* Port */
1392 new_confline(&ctmp);
1393 ctmp->help_title= _("HELP FOR PORT NUMBER");
1394 ctmp->var = &port_var;
1395 ctmp->valoffset = indent;
1396 ctmp->keymenu = &config_text_keymenu;
1397 ctmp->help = h_config_ldap_port;
1398 ctmp->tool = dir_edit_tool;
1399 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,port_var.name);
1400 tmp[sizeof(tmp)-1] = '\0';
1401 ctmp->varname = cpystr(tmp);
1402 ctmp->varnamep = ctmp;
1403 ctmp->value = pretty_value(ps, ctmp);
1404 ctmp->flags |= CF_NUMBER;
1406 /* Bind DN (DN to bind to if needed) */
1407 new_confline(&ctmp);
1408 ctmp->help_title= _("HELP FOR SERVER BIND DN");
1409 ctmp->var = &binddn_var;
1410 ctmp->valoffset = indent;
1411 ctmp->keymenu = &config_text_keymenu;
1412 ctmp->help = h_config_ldap_binddn;
1413 ctmp->tool = dir_edit_tool;
1414 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,binddn_var.name);
1415 tmp[sizeof(tmp)-1] = '\0';
1416 ctmp->varname = cpystr(tmp);
1417 ctmp->varnamep = ctmp;
1418 ctmp->value = pretty_value(ps, ctmp);
1420 /* Nickname */
1421 new_confline(&ctmp);
1422 ctmp->help_title= _("HELP FOR SERVER NICKNAME");
1423 ctmp->var = &nick_var;
1424 ctmp->valoffset = indent;
1425 ctmp->keymenu = &config_text_keymenu;
1426 ctmp->help = h_config_ldap_nick;
1427 ctmp->tool = dir_edit_tool;
1428 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,nick_var.name);
1429 tmp[sizeof(tmp)-1] = '\0';
1430 ctmp->varname = cpystr(tmp);
1431 ctmp->varnamep = ctmp;
1432 ctmp->value = pretty_value(ps, ctmp);
1434 /* Blank line */
1435 new_confline(&ctmp);
1436 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1438 /* Options */
1439 new_confline(&ctmp);
1440 ctmp->var = &opt_var;
1441 ctmp->keymenu = &config_checkbox_keymenu;
1442 ctmp->help = NO_HELP;
1443 ctmp->tool = NULL;
1444 snprintf(tmp, sizeof(tmp), "%s =", opt_var.name);
1445 tmp[sizeof(tmp)-1] = '\0';
1446 ctmp->varname = cpystr(tmp);
1447 ctmp->varnamep = ctmpb = ctmp;
1448 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM);
1450 new_confline(&ctmp);
1451 ctmp->var = NULL;
1452 ctmp->valoffset = rindent;
1453 ctmp->keymenu = &config_checkbox_keymenu;
1454 ctmp->help = NO_HELP;
1455 ctmp->tool = ldap_checkbox_tool;
1456 ctmp->varnamep = ctmpb;
1457 ctmp->flags |= CF_NOSELECT;
1458 ctmp->value = cpystr("Set Feature Name");
1460 new_confline(&ctmp);
1461 ctmp->var = NULL;
1462 ctmp->valoffset = rindent;
1463 ctmp->keymenu = &config_checkbox_keymenu;
1464 ctmp->help = NO_HELP;
1465 ctmp->tool = ldap_checkbox_tool;
1466 ctmp->varnamep = ctmpb;
1467 ctmp->flags |= CF_NOSELECT;
1468 ctmp->value = cpystr(set_choose);
1470 /* find longest value's name */
1471 for(lv = 0, i = 0; (f = ldap_feature_list(i)); i++)
1472 if(lv < (j = utf8_width(f->name)))
1473 lv = j;
1475 lv = MIN(lv, 100);
1477 /* enabling ldaps disables tls */
1478 if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
1479 && bitnset(f->value, ldap_option_list)){
1480 int clear = 0;
1481 if((f = ldap_feature_list(LDAP_F_TLS)) != NULL
1482 && bitnset(f->value, ldap_option_list)){
1483 clear++;
1484 clrbitn(f->value, ldap_option_list);
1486 if((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
1487 && bitnset(f->value, ldap_option_list)){
1488 clear++;
1489 clrbitn(f->value, ldap_option_list);
1491 if(clear > 0)
1492 q_status_message(SM_ORDER, 3, 3,
1493 _("Can not use TLS when connecting using LDAPS"));
1496 /* enabling tls disables ldaps */
1497 if(((f = ldap_feature_list(LDAP_F_TLS)) != NULL
1498 && bitnset(f->value, ldap_option_list))
1499 || ((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
1500 && bitnset(f->value, ldap_option_list))){
1501 if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
1502 && bitnset(f->value, ldap_option_list)){
1503 clrbitn(f->value, ldap_option_list);
1504 q_status_message(SM_ORDER, 3, 3,
1505 _("Can not use LDAPS when connecting using TLS"));
1509 for(i = 0; (f = ldap_feature_list(i)); i++){
1510 new_confline(&ctmp);
1511 ctmp->var = &opt_var;
1512 ctmp->help_title= _("HELP FOR LDAP FEATURES");
1513 ctmp->varnamep = ctmpb;
1514 ctmp->keymenu = &config_checkbox_keymenu;
1515 switch(i){
1516 case LDAP_F_IMPL:
1517 ctmp->help = h_config_ldap_opts_impl;
1518 break;
1519 case LDAP_F_RHS:
1520 ctmp->help = h_config_ldap_opts_rhs;
1521 break;
1522 case LDAP_F_REF:
1523 ctmp->help = h_config_ldap_opts_ref;
1524 break;
1525 case LDAP_F_NOSUB:
1526 ctmp->help = h_config_ldap_opts_nosub;
1527 break;
1528 case LDAP_F_TLS:
1529 ctmp->help = h_config_ldap_opts_tls;
1530 break;
1531 case LDAP_F_TLSMUST:
1532 ctmp->help = h_config_ldap_opts_tlsmust;
1533 break;
1534 case LDAP_F_LDAPS:
1535 ctmp->help = h_config_ldap_opts_ldaps;
1536 break;
1539 ctmp->tool = ldap_checkbox_tool;
1540 ctmp->valoffset = rindent;
1541 ctmp->varmem = i;
1542 utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w",
1543 bitnset(f->value, ldap_option_list) ? 'X' : ' ',
1544 lv, lv, f->name);
1545 tmp[sizeof(tmp)-1] = '\0';
1546 ctmp->value = cpystr(tmp);
1549 /* Blank line */
1550 new_confline(&ctmp);
1551 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1553 /* Search Type */
1554 new_confline(&ctmp);
1555 ctmp->var = &srch_type_var;
1556 ctmp->keymenu = &config_radiobutton_keymenu;
1557 ctmp->help = NO_HELP;
1558 ctmp->tool = NULL;
1559 snprintf(tmp, sizeof(tmp), "%s =", srch_type_var.name);
1560 tmp[sizeof(tmp)-1] = '\0';
1561 ctmp->varname = cpystr(tmp);
1562 ctmp->varnamep = ctmpb = ctmp;
1563 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM);
1565 new_confline(&ctmp);
1566 ctmp->var = NULL;
1567 ctmp->valoffset = rindent;
1568 ctmp->keymenu = &config_radiobutton_keymenu;
1569 ctmp->help = NO_HELP;
1570 ctmp->tool = NULL;
1571 ctmp->varnamep = ctmpb;
1572 ctmp->flags |= CF_NOSELECT;
1573 ctmp->value = cpystr("Set Rule Values");
1575 new_confline(&ctmp);
1576 ctmp->var = NULL;
1577 ctmp->valoffset = rindent;
1578 ctmp->keymenu = &config_radiobutton_keymenu;
1579 ctmp->help = NO_HELP;
1580 ctmp->tool = ldap_radiobutton_tool;
1581 ctmp->varnamep = ctmpb;
1582 ctmp->flags |= CF_NOSELECT;
1583 ctmp->value = cpystr(set_choose);
1585 /* find longest value's name */
1586 for(lv = 0, i = 0; (f = ldap_search_types(i)); i++)
1587 if(lv < (j = utf8_width(f->name)))
1588 lv = j;
1590 lv = MIN(lv, 100);
1592 for(i = 0; (f = ldap_search_types(i)); i++){
1593 new_confline(&ctmp);
1594 ctmp->help_title= _("HELP FOR SEARCH TYPE");
1595 ctmp->var = &srch_type_var;
1596 ctmp->valoffset = rindent;
1597 ctmp->keymenu = &config_radiobutton_keymenu;
1598 ctmp->help = h_config_ldap_searchtypes;
1599 ctmp->varmem = i;
1600 ctmp->tool = ldap_radiobutton_tool;
1601 ctmp->varnamep = ctmpb;
1602 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!def || def->type == -1) &&
1603 f->value == DEF_LDAP_TYPE) ||
1604 (def && f->value == def->type))
1605 ? R_SELD : ' ',
1606 lv, lv, f->name);
1607 tmp[sizeof(tmp)-1] = '\0';
1608 ctmp->value = cpystr(tmp);
1611 /* Blank line */
1612 new_confline(&ctmp);
1613 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1614 ctmp->varname = cpystr("");
1616 /* Search Rule */
1617 new_confline(&ctmp);
1618 ctmp->var = &srch_rule_var;
1619 ctmp->keymenu = &config_radiobutton_keymenu;
1620 ctmp->help = NO_HELP;
1621 ctmp->tool = NULL;
1622 snprintf(tmp, sizeof(tmp), "%s =", srch_rule_var.name);
1623 tmp[sizeof(tmp)-1] = '\0';
1624 ctmp->varname = cpystr(tmp);
1625 ctmp->varnamep = ctmpb = ctmp;
1626 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM);
1628 /* Search Rule */
1629 new_confline(&ctmp);
1630 ctmp->var = NULL;
1631 ctmp->valoffset = rindent;
1632 ctmp->keymenu = &config_radiobutton_keymenu;
1633 ctmp->help = NO_HELP;
1634 ctmp->tool = NULL;
1635 ctmp->varnamep = ctmpb;
1636 ctmp->flags |= CF_NOSELECT;
1637 ctmp->value = cpystr("Set Rule Values");
1639 new_confline(&ctmp);
1640 ctmp->var = NULL;
1641 ctmp->valoffset = rindent;
1642 ctmp->keymenu = &config_radiobutton_keymenu;
1643 ctmp->help = NO_HELP;
1644 ctmp->tool = ldap_radiobutton_tool;
1645 ctmp->varnamep = ctmpb;
1646 ctmp->flags |= CF_NOSELECT;
1647 ctmp->value = cpystr(set_choose);
1649 /* find longest value's name */
1650 for(lv = 0, i = 0; (f = ldap_search_rules(i)); i++)
1651 if(lv < (j = utf8_width(f->name)))
1652 lv = j;
1654 lv = MIN(lv, 100);
1656 for(i = 0; (f = ldap_search_rules(i)); i++){
1657 new_confline(&ctmp);
1658 ctmp->help_title= _("HELP FOR SEARCH RULE");
1659 ctmp->var = &srch_rule_var;
1660 ctmp->valoffset = rindent;
1661 ctmp->keymenu = &config_radiobutton_keymenu;
1662 ctmp->help = h_config_ldap_searchrules;
1663 ctmp->varmem = i;
1664 ctmp->tool = ldap_radiobutton_tool;
1665 ctmp->varnamep = ctmpb;
1666 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!def || def->srch == -1) &&
1667 f->value == DEF_LDAP_SRCH) ||
1668 (def && f->value == def->srch))
1669 ? R_SELD : ' ',
1670 lv, lv, f->name);
1671 tmp[sizeof(tmp)-1] = '\0';
1672 ctmp->value = cpystr(tmp);
1675 /* Blank line */
1676 new_confline(&ctmp);
1677 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1678 ctmp->varname = cpystr("");
1680 /* Email attribute name */
1681 new_confline(&ctmp);
1682 ctmp->help_title= _("HELP FOR EMAIL ATTRIBUTE NAME");
1683 ctmp->var = &mailattr_var;
1684 ctmp->valoffset = indent;
1685 ctmp->keymenu = &config_text_keymenu;
1686 ctmp->help = h_config_ldap_email_attr;
1687 ctmp->tool = dir_edit_tool;
1688 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,mailattr_var.name);
1689 tmp[sizeof(tmp)-1] = '\0';
1690 ctmp->varname = cpystr(tmp);
1691 ctmp->varnamep = ctmp;
1692 ctmp->value = pretty_value(ps, ctmp);
1694 /* Name attribute name */
1695 new_confline(&ctmp);
1696 ctmp->help_title= _("HELP FOR NAME ATTRIBUTE NAME");
1697 ctmp->var = &cnattr_var;
1698 ctmp->valoffset = indent;
1699 ctmp->keymenu = &config_text_keymenu;
1700 ctmp->help = h_config_ldap_cn_attr;
1701 ctmp->tool = dir_edit_tool;
1702 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,cnattr_var.name);
1703 tmp[sizeof(tmp)-1] = '\0';
1704 ctmp->varname = cpystr(tmp);
1705 ctmp->varnamep = ctmp;
1706 ctmp->value = pretty_value(ps, ctmp);
1708 /* Surname attribute name */
1709 new_confline(&ctmp);
1710 ctmp->help_title= _("HELP FOR SURNAME ATTRIBUTE NAME");
1711 ctmp->var = &snattr_var;
1712 ctmp->valoffset = indent;
1713 ctmp->keymenu = &config_text_keymenu;
1714 ctmp->help = h_config_ldap_sn_attr;
1715 ctmp->tool = dir_edit_tool;
1716 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,snattr_var.name);
1717 tmp[sizeof(tmp)-1] = '\0';
1718 ctmp->varname = cpystr(tmp);
1719 ctmp->varnamep = ctmp;
1720 ctmp->value = pretty_value(ps, ctmp);
1722 /* Givenname attribute name */
1723 new_confline(&ctmp);
1724 ctmp->help_title= _("HELP FOR GIVEN NAME ATTRIBUTE NAME");
1725 ctmp->var = &gnattr_var;
1726 ctmp->valoffset = indent;
1727 ctmp->keymenu = &config_text_keymenu;
1728 ctmp->help = h_config_ldap_gn_attr;
1729 ctmp->tool = dir_edit_tool;
1730 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,gnattr_var.name);
1731 tmp[sizeof(tmp)-1] = '\0';
1732 ctmp->varname = cpystr(tmp);
1733 ctmp->varnamep = ctmp;
1734 ctmp->value = pretty_value(ps, ctmp);
1736 /* Blank line */
1737 new_confline(&ctmp);
1738 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1739 ctmp->varname = cpystr("");
1741 /* Time limit */
1742 new_confline(&ctmp);
1743 ctmp->help_title= _("HELP FOR SERVER TIMELIMIT");
1744 ctmp->var = &time_var;
1745 ctmp->valoffset = indent;
1746 ctmp->keymenu = &config_text_keymenu;
1747 ctmp->help = h_config_ldap_time;
1748 ctmp->tool = dir_edit_tool;
1749 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,time_var.name);
1750 tmp[sizeof(tmp)-1] = '\0';
1751 ctmp->varname = cpystr(tmp);
1752 ctmp->varnamep = ctmp;
1753 ctmp->value = pretty_value(ps, ctmp);
1754 ctmp->flags |= CF_NUMBER;
1756 /* Size limit */
1757 new_confline(&ctmp);
1758 ctmp->var = &size_var;
1759 ctmp->help_title= _("HELP FOR SERVER SIZELIMIT");
1760 ctmp->valoffset = indent;
1761 ctmp->keymenu = &config_text_keymenu;
1762 ctmp->help = h_config_ldap_size;
1763 ctmp->tool = dir_edit_tool;
1764 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,size_var.name);
1765 tmp[sizeof(tmp)-1] = '\0';
1766 ctmp->varname = cpystr(tmp);
1767 ctmp->varnamep = ctmp;
1768 ctmp->value = pretty_value(ps, ctmp);
1769 ctmp->flags |= CF_NUMBER;
1771 /* Blank line */
1772 new_confline(&ctmp);
1773 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1775 /* Custom Search Filter */
1776 new_confline(&ctmp);
1777 ctmp->help_title= _("HELP FOR CUSTOM SEARCH FILTER");
1778 ctmp->var = &cust_var;
1779 ctmp->valoffset = indent;
1780 ctmp->keymenu = &config_text_keymenu;
1781 ctmp->help = h_config_ldap_cust;
1782 ctmp->tool = dir_edit_tool;
1783 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,cust_var.name);
1784 tmp[sizeof(tmp)-1] = '\0';
1785 ctmp->varname = cpystr(tmp);
1786 ctmp->varnamep = ctmp;
1787 ctmp->value = pretty_value(ps, ctmp);
1790 snprintf(tmp, sizeof(tmp), "%s DIRECTORY SERVER", title);
1791 tmp[sizeof(tmp)-1] = '\0';
1792 memset(&screen, 0, sizeof(screen));
1793 screen.ro_warning = saved_screen ? saved_screen->deferred_ro_warning : 0;
1794 /* TRANSLATORS: Print something1 using something2.
1795 servers is something1 */
1796 rv = conf_scroll_screen(ps, &screen, first_line, tmp, _("servers"), 0, NULL);
1799 * Now look at the fake variables and extract the information we
1800 * want from them.
1803 if(rv == 1 && raw_server){
1804 char dir_tmp[2200+MAXPATH], *p;
1805 int portval = -1, timeval = -1, sizeval = -1;
1807 apval = APVAL(&server_var, ew);
1808 server = *apval;
1809 *apval = NULL;
1811 apval = APVAL(&base_var, ew);
1812 base = *apval;
1813 *apval = NULL;
1815 apval = APVAL(&port_var, ew);
1816 port = *apval;
1817 *apval = NULL;
1819 apval = APVAL(&binddn_var, ew);
1820 binddn = *apval;
1821 *apval = NULL;
1823 apval = APVAL(&nick_var, ew);
1824 nick = *apval;
1825 *apval = NULL;
1827 apval = APVAL(&srch_type_var, ew);
1828 srch_type = *apval;
1829 *apval = NULL;
1831 apval = APVAL(&srch_rule_var, ew);
1832 srch_rule = *apval;
1833 *apval = NULL;
1835 apval = APVAL(&time_var, ew);
1836 ttime = *apval;
1837 *apval = NULL;
1839 apval = APVAL(&size_var, ew);
1840 ssize = *apval;
1841 *apval = NULL;
1843 apval = APVAL(&cust_var, ew);
1844 cust = *apval;
1845 *apval = NULL;
1847 apval = APVAL(&mailattr_var, ew);
1848 mailattr = *apval;
1849 *apval = NULL;
1851 apval = APVAL(&snattr_var, ew);
1852 snattr = *apval;
1853 *apval = NULL;
1855 apval = APVAL(&gnattr_var, ew);
1856 gnattr = *apval;
1857 *apval = NULL;
1859 apval = APVAL(&cnattr_var, ew);
1860 cnattr = *apval;
1861 *apval = NULL;
1863 if(server)
1864 removing_leading_and_trailing_white_space(server);
1866 if(base){
1867 removing_leading_and_trailing_white_space(base);
1868 (void)removing_double_quotes(base);
1869 p = add_backslash_escapes(base);
1870 fs_give((void **)&base);
1871 base = p;
1874 if(port){
1875 removing_leading_and_trailing_white_space(port);
1876 if(*port)
1877 portval = atoi(port);
1880 if(binddn){
1881 removing_leading_and_trailing_white_space(binddn);
1882 (void)removing_double_quotes(binddn);
1883 p = add_backslash_escapes(binddn);
1884 fs_give((void **)&binddn);
1885 binddn = p;
1888 if(nick){
1889 removing_leading_and_trailing_white_space(nick);
1890 (void)removing_double_quotes(nick);
1891 p = add_backslash_escapes(nick);
1892 fs_give((void **)&nick);
1893 nick = p;
1896 if(ttime){
1897 removing_leading_and_trailing_white_space(ttime);
1898 if(*ttime)
1899 timeval = atoi(ttime);
1902 if(ssize){
1903 removing_leading_and_trailing_white_space(ssize);
1904 if(*ssize)
1905 sizeval = atoi(ssize);
1908 if(cust){
1909 removing_leading_and_trailing_white_space(cust);
1910 p = add_backslash_escapes(cust);
1911 fs_give((void **)&cust);
1912 cust = p;
1915 if(mailattr){
1916 removing_leading_and_trailing_white_space(mailattr);
1917 p = add_backslash_escapes(mailattr);
1918 fs_give((void **)&mailattr);
1919 mailattr = p;
1922 if(snattr){
1923 removing_leading_and_trailing_white_space(snattr);
1924 p = add_backslash_escapes(snattr);
1925 fs_give((void **)&snattr);
1926 snattr = p;
1929 if(gnattr){
1930 removing_leading_and_trailing_white_space(gnattr);
1931 p = add_backslash_escapes(gnattr);
1932 fs_give((void **)&gnattr);
1933 gnattr = p;
1936 if(cnattr){
1937 removing_leading_and_trailing_white_space(cnattr);
1938 p = add_backslash_escapes(cnattr);
1939 fs_give((void **)&cnattr);
1940 cnattr = p;
1944 * Don't allow user to edit scope but if one is present then we
1945 * leave it (so they could edit it by hand).
1947 if(def && def->scope != -1 && def->scope != DEF_LDAP_SCOPE){
1948 NAMEVAL_S *v;
1950 v = ldap_search_scope(def->scope);
1951 if(v){
1952 snprintf(custom_scope, sizeof(custom_scope), "/scope=%s", v->name);
1953 custom_scope[sizeof(custom_scope)-1] = '\0';
1957 snprintf(dir_tmp, sizeof(dir_tmp), "%s%s%s \"/base=%s/binddn=%s/impl=%d/rhs=%d/ref=%d/nosub=%d/tls=%d/tlsm=%d/ldaps=%d/type=%s/srch=%s%s/time=%s/size=%s/cust=%s/nick=%s/matr=%s/catr=%s/satr=%s/gatr=%s\"",
1958 server ? server : "",
1959 (portval >= 0 && port && *port) ? ":" : "",
1960 (portval >= 0 && port && *port) ? port : "",
1961 base ? base : "",
1962 binddn ? binddn : "",
1963 bitnset(LDAP_F_IMPL, ldap_option_list) ? 1 : 0,
1964 bitnset(LDAP_F_RHS, ldap_option_list) ? 1 : 0,
1965 bitnset(LDAP_F_REF, ldap_option_list) ? 1 : 0,
1966 bitnset(LDAP_F_NOSUB, ldap_option_list) ? 1 : 0,
1967 bitnset(LDAP_F_TLS, ldap_option_list) ? 1 : 0,
1968 bitnset(LDAP_F_TLSMUST, ldap_option_list) ? 1 : 0,
1969 bitnset(LDAP_F_LDAPS, ldap_option_list) ? 1 : 0,
1970 srch_type ? srch_type : "",
1971 srch_rule ? srch_rule : "",
1972 custom_scope,
1973 (timeval >= 0 && ttime && *ttime) ? ttime : "",
1974 (sizeval >= 0 && ssize && *ssize) ? ssize : "",
1975 cust ? cust : "",
1976 nick ? nick : "",
1977 mailattr ? mailattr : "",
1978 cnattr ? cnattr : "",
1979 snattr ? snattr : "",
1980 gnattr ? gnattr : "");
1981 dir_tmp[sizeof(dir_tmp)-1] = '\0';
1983 *raw_server = cpystr(dir_tmp);
1986 for(j = 0; varlist[j]; j++){
1987 v = varlist[j];
1988 if(v->current_val.p)
1989 fs_give((void **)&v->current_val.p);
1990 if(v->global_val.p)
1991 fs_give((void **)&v->global_val.p);
1992 if(v->main_user_val.p)
1993 fs_give((void **)&v->main_user_val.p);
1994 if(v->post_user_val.p)
1995 fs_give((void **)&v->post_user_val.p);
1996 if(v->name)
1997 fs_give((void **)&v->name);
2000 if(server)
2001 fs_give((void **)&server);
2002 if(base)
2003 fs_give((void **)&base);
2004 if(port)
2005 fs_give((void **)&port);
2006 if(binddn)
2007 fs_give((void **)&binddn);
2008 if(nick)
2009 fs_give((void **)&nick);
2010 if(srch_type)
2011 fs_give((void **)&srch_type);
2012 if(srch_rule)
2013 fs_give((void **)&srch_rule);
2014 if(ttime)
2015 fs_give((void **)&ttime);
2016 if(ssize)
2017 fs_give((void **)&ssize);
2018 if(mailattr)
2019 fs_give((void **)&mailattr);
2020 if(cnattr)
2021 fs_give((void **)&cnattr);
2022 if(snattr)
2023 fs_give((void **)&snattr);
2024 if(gnattr)
2025 fs_give((void **)&gnattr);
2026 if(cust)
2027 fs_give((void **)&cust);
2029 opt_screen = saved_screen;
2030 ps->mangled_screen = 1;
2031 return(rv);
2036 * Just calls text_tool except for intercepting MC_EXIT.
2039 dir_edit_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
2041 if(cmd == MC_EXIT)
2042 return(config_exit_cmd(flags));
2043 else
2044 return(text_tool(ps, cmd, cl, flags));
2049 * Delete LDAP directory entry
2051 void
2052 dir_config_del(struct pine *ps, CONF_S **cl)
2054 char prompt[81];
2055 int rv = 0, i;
2057 if(fixed_var((*cl)->var, NULL, NULL)){
2058 if((*cl)->var->post_user_val.l || (*cl)->var->main_user_val.l){
2059 if(want_to(_("Delete (unused) directory servers "),
2060 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){
2061 rv = 1;
2062 delete_user_vals((*cl)->var);
2065 else
2066 q_status_message(SM_ORDER, 3, 3,
2067 _("Can't delete sys-admin defined value"));
2069 else{
2070 int cnt, ans = 0, no_ex;
2071 char **new_list, **lval, **nelval;
2073 no_ex = (ps_global->ew_for_except_vars == Main);
2075 /* This can't happen, intercepted at caller by first_one case */
2076 nelval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
2077 lval = LVAL((*cl)->var, ew);
2078 if(lval && lval[0] && lval[0][0] == '\0')
2079 ans = 'r';
2081 /* how many servers defined? */
2082 for(cnt = 0; nelval[cnt]; cnt++)
2086 * If using default and there is more than one in list, ask if user
2087 * wants to ignore them all or delete just this one. If just this
2088 * one, copy rest to user_val. If ignore all, copy "" to user_val
2089 * to override.
2091 if(!lval && cnt > 1){
2092 static ESCKEY_S opts[] = {
2093 {'i', 'i', "I", N_("Ignore All")},
2094 {'r', 'r', "R", N_("Remove One")},
2095 {-1, 0, NULL, NULL}};
2096 ans = radio_buttons(
2097 _("Ignore all default directory servers or just remove this one ? "),
2098 -FOOTER_ROWS(ps), opts, 'i', 'x',
2099 h_ab_del_dir_ignore, RB_NORM);
2102 if(ans == 0){
2103 snprintf(prompt, sizeof(prompt), _("Really delete %s \"%s\" from directory servers "),
2104 ((*cl)->value && *(*cl)->value)
2105 ? "server"
2106 : "item",
2107 ((*cl)->value && *(*cl)->value)
2108 ? (*cl)->value
2109 : int2string((*cl)->varmem + 1));
2110 prompt[sizeof(prompt)-1] = '\0';
2114 ps->mangled_footer = 1;
2115 if(ans == 'i'){
2116 rv = ps->mangled_body = 1;
2119 * Ignore all of default by adding an empty string. Make it
2120 * look just like there are no servers defined.
2123 new_list = (char **)fs_get((1 + 1) * sizeof(char *));
2124 new_list[0] = cpystr("");
2125 new_list[1] = NULL;
2126 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
2127 free_list_array(&new_list);
2128 *cl = first_confline(*cl);
2129 free_conflines(cl);
2130 opt_screen->top_line = NULL;
2132 add_ldap_fake_first_server(ps, cl, &ps->vars[V_LDAP_SERVERS],
2133 &dir_conf_km, h_direct_config,
2134 dir_config_tool);
2136 else if(ans == 'r' ||
2137 (ans != 'x' &&
2138 want_to(prompt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y')){
2139 CONF_S *cp;
2140 char **servers;
2141 int move_top = 0, this_one, revert_to_default,
2142 default_there_to_revert_to = 0;
2145 * Remove one from current list.
2148 rv = ps->mangled_body = 1;
2150 this_one = (*cl)->varmem;
2152 /* might have to re-adjust screen to see new current */
2153 move_top = (this_one > 0) &&
2154 (this_one == cnt - 1) &&
2155 (((*cl) == opt_screen->top_line) ||
2156 ((*cl)->prev == opt_screen->top_line) ||
2157 ((*cl)->prev->prev == opt_screen->top_line));
2160 * If this is last one and there is a default available, revert
2161 * to it.
2163 revert_to_default = ((cnt == 1) && lval);
2164 if(cnt > 1){
2165 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
2166 for(i = 0; i < this_one; i++)
2167 new_list[i] = cpystr(nelval[i]);
2169 for(i = this_one; i < cnt; i++)
2170 new_list[i] = cpystr(nelval[i+1]);
2172 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
2173 free_list_array(&new_list);
2175 else if(revert_to_default){
2176 char ***alval;
2178 alval = ALVAL((*cl)->var, ew);
2179 if(alval && *alval)
2180 free_list_array(alval);
2182 else{
2183 /* cnt is one and we want to hide default */
2184 new_list = (char **)fs_get((1 + 1) * sizeof(char *));
2185 new_list[0] = cpystr("");
2186 new_list[1] = NULL;
2187 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
2188 free_list_array(&new_list);
2191 if(cnt == 1){ /* delete display line for this_one */
2192 if(revert_to_default){
2193 servers = (*cl)->var->global_val.l;
2194 default_there_to_revert_to = (servers != NULL);
2197 *cl = first_confline(*cl);
2198 free_conflines(cl);
2199 opt_screen->top_line = NULL;
2200 if(revert_to_default && default_there_to_revert_to){
2201 CONF_S *first_line = NULL;
2203 q_status_message(SM_ORDER, 0, 3,
2204 _("Reverting to default directory server"));
2205 dir_init_display(ps, cl, servers,
2206 &ps->vars[V_LDAP_SERVERS], &first_line);
2207 *cl = first_line;
2209 else{
2210 add_ldap_fake_first_server(ps, cl,
2211 &ps->vars[V_LDAP_SERVERS],
2212 &dir_conf_km, h_direct_config,
2213 dir_config_tool);
2216 else if(this_one == cnt - 1){ /* deleted last one */
2217 /* back up and delete it */
2218 *cl = (*cl)->prev;
2219 free_conflines(&(*cl)->next);
2220 /* now back up to first line of this server */
2221 *cl = (*cl)->prev->prev;
2222 if(move_top)
2223 opt_screen->top_line = *cl;
2225 else{ /* deleted one out of the middle */
2226 if(*cl == opt_screen->top_line)
2227 opt_screen->top_line = (*cl)->next->next->next;
2229 cp = *cl;
2230 *cl = (*cl)->next; /* move to next line, then */
2231 snip_confline(&cp); /* snip 1st deleted line */
2232 cp = *cl;
2233 *cl = (*cl)->next; /* move to next line, then */
2234 snip_confline(&cp); /* snip 2nd deleted line */
2235 cp = *cl;
2236 *cl = (*cl)->next; /* move to next line, then */
2237 snip_confline(&cp); /* snip 3rd deleted line */
2238 /* adjust varmems */
2239 for(cp = *cl; cp; cp = cp->next)
2240 cp->varmem--;
2243 else
2244 q_status_message(SM_ORDER, 0, 3, _("Server not deleted"));
2247 if(rv == 1){
2248 set_current_val((*cl)->var, TRUE, FALSE);
2249 fix_side_effects(ps, (*cl)->var, 0);
2250 write_pinerc(ps, ew, WRP_NONE);
2256 * Utility routine to help set up display
2258 void
2259 add_ldap_fake_first_server(struct pine *ps, CONF_S **ctmp, struct variable *var,
2260 struct key_menu *km, HelpType help,
2261 int (*tool)(struct pine *, int, CONF_S **, unsigned))
2263 new_confline(ctmp);
2264 (*ctmp)->help_title= _("HELP FOR DIRECTORY SERVER CONFIGURATION");
2265 (*ctmp)->value = cpystr(ADD_FIRST_LDAP_SERVER);
2266 (*ctmp)->var = var;
2267 (*ctmp)->varmem = 0;
2268 (*ctmp)->keymenu = km;
2269 (*ctmp)->help = help;
2270 (*ctmp)->tool = tool;
2271 (*ctmp)->valoffset = 2;
2276 * Add an ldap server to the display list.
2278 * Args before -- Insert it before current, else append it after.
2280 void
2281 add_ldap_server_to_display(struct pine *ps, CONF_S **ctmp, char *serv, char *subtitle,
2282 struct variable *var, int member, struct key_menu *km,
2283 HelpType help,
2284 int (*tool)(struct pine *, int, CONF_S **, unsigned),
2285 int before, CONF_S **first_line)
2287 new_confline(ctmp);
2288 if(first_line)
2289 *first_line = *ctmp;
2291 if(before){
2293 * New_confline appends ctmp after old current instead of inserting
2294 * it, so we have to adjust. We have
2295 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
2298 CONF_S *a, *b, *c, *p;
2300 p = *ctmp;
2301 b = (*ctmp)->prev;
2302 c = (*ctmp)->next;
2303 a = b ? b->prev : NULL;
2304 if(a)
2305 a->next = p;
2307 if(b){
2308 b->prev = p;
2309 b->next = c;
2312 if(c)
2313 c->prev = b;
2315 p->prev = a;
2316 p->next = b;
2319 (*ctmp)->help_title= _("HELP FOR DIRECTORY SERVER CONFIGURATION");
2320 (*ctmp)->value = serv;
2321 (*ctmp)->var = var;
2322 (*ctmp)->varmem = member;
2323 (*ctmp)->keymenu = km;
2324 (*ctmp)->help = help;
2325 (*ctmp)->tool = tool;
2326 (*ctmp)->flags |= CF_STARTITEM;
2327 (*ctmp)->valoffset = 4;
2329 new_confline(ctmp);
2330 (*ctmp)->value = subtitle;
2331 (*ctmp)->keymenu = km;
2332 (*ctmp)->help = help;
2333 (*ctmp)->tool = tool;
2334 (*ctmp)->flags |= CF_NOSELECT;
2335 (*ctmp)->valoffset = 8;
2337 new_confline(ctmp);
2338 (*ctmp)->keymenu = km;
2339 (*ctmp)->help = help;
2340 (*ctmp)->tool = tool;
2341 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
2342 (*ctmp)->valoffset = 0;
2347 * ldap option list manipulation tool
2350 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
2353 ldap_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
2355 int rv = 0;
2357 switch(cmd){
2358 case MC_TOGGLE: /* mark/unmark option */
2359 rv = 1;
2360 toggle_ldap_option_bit(ps, (*cl)->varmem, (*cl)->var, (*cl)->value);
2361 break;
2363 case MC_EXIT: /* exit */
2364 rv = config_exit_cmd(flags);
2365 break;
2367 default :
2368 rv = -1;
2369 break;
2372 return(rv);
2376 void
2377 toggle_ldap_option_bit(struct pine *ps, int index, struct variable *var, char *value)
2379 NAMEVAL_S *f;
2380 int tls_is_on_now;
2381 int tlsmust_is_on_now;
2382 int ldaps_is_on_now;
2383 int tls_is_on_after;
2384 int tlsmust_is_on_after;
2385 int ldaps_is_on_after;
2387 tls_is_on_now = (f = ldap_feature_list(LDAP_F_TLS)) != NULL
2388 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2390 tlsmust_is_on_now = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
2391 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2393 ldaps_is_on_now = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
2394 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2396 f = ldap_feature_list(index);
2398 /* flip the bit */
2399 if(bitnset(f->value, ldap_option_list))
2400 clrbitn(f->value, ldap_option_list);
2401 else
2402 setbitn(f->value, ldap_option_list);
2404 tls_is_on_after = (f = ldap_feature_list(LDAP_F_TLS)) != NULL
2405 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2407 tlsmust_is_on_after = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
2408 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2410 ldaps_is_on_after = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
2411 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2413 f = ldap_feature_list(index);
2415 if(!ldaps_is_on_now && ldaps_is_on_after){
2416 if(tlsmust_is_on_after || tls_is_on_after){
2417 char *name;
2418 if(tlsmust_is_on_after)
2419 name = ldap_feature_list(LDAP_F_TLSMUST)->name;
2420 else
2421 name = ldap_feature_list(LDAP_F_TLS)->name;
2422 clrbitn(f->value, ldap_option_list);
2423 q_status_message1(SM_ORDER, 3, 3,
2424 _("Can not use LDAPS when using TLS. Disable \"%s\" first."), name);
2427 else if(!tls_is_on_now && tls_is_on_after){
2428 if(ldaps_is_on_after){
2429 char *name = ldap_feature_list(LDAP_F_LDAPS)->name;
2430 clrbitn(f->value, ldap_option_list);
2431 q_status_message1(SM_ORDER, 3, 3,
2432 _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name);
2435 else if(!tlsmust_is_on_now && tlsmust_is_on_after){
2436 if(ldaps_is_on_after){
2437 char *name = ldap_feature_list(LDAP_F_LDAPS)->name;
2438 clrbitn(f->value, ldap_option_list);
2439 q_status_message1(SM_ORDER, 3, 3,
2440 _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name);
2444 if(value)
2445 value[1] = bitnset(f->value, ldap_option_list) ? 'X' : ' ';
2449 NAMEVAL_S *
2450 ldap_feature_list(int index)
2452 static NAMEVAL_S ldap_feat_list[] = {
2453 {"use-implicitly-from-composer", NULL, LDAP_F_IMPL},
2454 {"lookup-addrbook-contents", NULL, LDAP_F_RHS},
2455 {"save-search-criteria-not-result", NULL, LDAP_F_REF},
2456 {"disable-ad-hoc-space-substitution", NULL, LDAP_F_NOSUB},
2457 {"attempt-tls-on-connection", NULL, LDAP_F_TLS},
2458 {"require-tls-on-connection", NULL, LDAP_F_TLSMUST},
2459 {"require-ldaps-on-connection", NULL, LDAP_F_LDAPS}
2462 return((index >= 0 &&
2463 index < (sizeof(ldap_feat_list)/sizeof(ldap_feat_list[0])))
2464 ? &ldap_feat_list[index] : NULL);
2469 * simple radio-button style variable handler
2472 ldap_radiobutton_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
2474 int rv = 0;
2475 CONF_S *ctmp;
2476 NAMEVAL_S *rule;
2477 char **apval;
2479 switch(cmd){
2480 case MC_CHOICE : /* set/unset feature */
2482 /* hunt backwards, turning off old values */
2483 for(ctmp = *cl; ctmp && !(ctmp->flags & CF_NOSELECT) && !ctmp->varname;
2484 ctmp = prev_confline(ctmp))
2485 ctmp->value[1] = ' ';
2487 /* hunt forwards, turning off old values */
2488 for(ctmp = *cl; ctmp && !(ctmp->flags & CF_NOSELECT) && !ctmp->varname;
2489 ctmp = next_confline(ctmp))
2490 ctmp->value[1] = ' ';
2492 /* turn on current value */
2493 (*cl)->value[1] = R_SELD;
2495 if((*cl)->var == ldap_srch_rule_ptr)
2496 rule = ldap_search_rules((*cl)->varmem);
2497 else
2498 rule = ldap_search_types((*cl)->varmem);
2500 apval = APVAL((*cl)->var, ew);
2501 if(apval && *apval)
2502 fs_give((void **)apval);
2504 if(apval)
2505 *apval = cpystr(rule->name);
2507 ps->mangled_body = 1; /* BUG: redraw it all for now? */
2508 rv = 1;
2510 break;
2512 case MC_EXIT: /* exit */
2513 rv = config_exit_cmd(flags);
2514 break;
2516 default :
2517 rv = -1;
2518 break;
2521 return(rv);
2524 #endif /* ENABLE_LDAP */