* NTLM authentication support with the ntlm library, in Unix systems.
[alpine.git] / alpine / ldapconf.c
blob9b7d999fa2b9f19ff72be6676b3c70351cd43663
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: ldapconf.c 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2013-2017 Eduardo Chappa
8 * Copyright 2006-2008 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 #include "headers.h"
20 #include "ldapconf.h"
21 #include "keymenu.h"
22 #include "radio.h"
23 #include "status.h"
24 #include "confscroll.h"
25 #include "adrbkcmd.h"
26 #include "titlebar.h"
27 #include "takeaddr.h"
28 #include "../pith/ldap.h"
29 #include "../pith/state.h"
30 #include "../pith/bitmap.h"
31 #include "../pith/mailcmd.h"
32 #include "../pith/list.h"
36 * Internal prototypes
38 #ifdef ENABLE_LDAP
39 int addr_select_tool(struct pine *, int, CONF_S **, unsigned);
40 void dir_init_display(struct pine *, CONF_S **, char **, struct variable *, CONF_S **);
41 int dir_config_tool(struct pine *, int, CONF_S **, unsigned);
42 void dir_config_add(struct pine *, CONF_S **);
43 void dir_config_shuffle(struct pine *, CONF_S **);
44 void dir_config_edit(struct pine *, CONF_S **);
45 int dir_edit_screen(struct pine *, LDAP_SERV_S *, char *, char **);
46 int dir_edit_tool(struct pine *, int, CONF_S **, unsigned);
47 void dir_config_del(struct pine *, CONF_S **);
48 void add_ldap_fake_first_server(struct pine *, CONF_S **, struct variable *,
49 struct key_menu *, HelpType,
50 int (*)(struct pine *, int, CONF_S **, unsigned));
51 void add_ldap_server_to_display(struct pine *, CONF_S **, char *, char *,
52 struct variable *, int, struct key_menu *, HelpType,
53 int (*)(struct pine *, int, CONF_S **, unsigned),
54 int, CONF_S **);
55 int ldap_checkbox_tool(struct pine *, int, CONF_S **, unsigned);
56 void toggle_ldap_option_bit(struct pine *, int, struct variable *, char *);
57 NAMEVAL_S *ldap_feature_list(int);
60 static char *srch_res_help_title = N_("HELP FOR SEARCH RESULTS INDEX");
61 static char *set_choose = "--- ----------------------";
62 #define ADD_FIRST_LDAP_SERVER _("Use Add to add a directory server")
63 #define ADDR_SELECT_EXIT_VAL 5
64 #define ADDR_SELECT_GOBACK_VAL 6
65 #define ADDR_SELECT_FORCED_EXIT_VAL 7
68 static int some_selectable;
69 static char *dserv = N_("Directory Server on ");
72 * Let user choose an ldap entry (or return an entry if user doesn't need
73 * to be consulted).
75 * Returns 0 if ok,
76 * -1 if Exit was chosen
77 * -2 if none were selectable
78 * -3 if no entries existed at all
79 * -4 go back to Abook List was chosen
80 * -5 caller shouldn't free ac->res_head
82 * When 0 is returned the winner is pointed to by result.
83 * Result is an allocated LDAP_SEARCH_WINNER_S which has pointers
84 * to the ld and entry that were chosen. Those are pointers into
85 * the initial data, not copies. The two-pointer structure is
86 * allocated here and freed by the caller.
88 int
89 ldap_addr_select(struct pine *ps, ADDR_CHOOSE_S *ac, LDAP_CHOOSE_S **result,
90 LDAPLookupStyle style, WP_ERR_S *wp_err, char *srchstr)
92 LDAPMessage *e;
93 LDAP_SERV_RES_S *res_list;
94 CONF_S *ctmpa = NULL, *first_line = NULL, *alt_first_line = NULL;
95 int i, retval = 0, got_n_mail = 0, got_n_entries = 0;
96 int need_mail;
97 OPT_SCREEN_S screen;
98 struct key_menu *km;
99 char ee[200];
100 HelpType help;
101 void (*prev_redrawer) (void);
103 dprint((4, "ldap_addr_select()\n"));
105 need_mail = (style == AlwaysDisplay || style == DisplayForURL) ? 0 : 1;
106 if(style == AlwaysDisplay){
107 km = &addr_s_km_with_view;
108 help = h_address_display;
110 else if(style == AlwaysDisplayAndMailRequired){
111 km = &addr_s_km_with_goback;
112 help = h_address_select;
114 else if(style == DisplayForURL){
115 km = &addr_s_km_for_url;
116 help = h_address_display;
118 else{
119 km = &addr_s_km;
120 help = h_address_select;
123 if(result)
124 *result = NULL;
126 some_selectable = 0;
128 for(res_list = ac->res_head; res_list; res_list = res_list->next){
129 for(e = ldap_first_entry(res_list->ld, res_list->res);
130 e != NULL;
131 e = ldap_next_entry(res_list->ld, e)){
132 char *dn, *a;
133 struct berval **cn, **org, **unit, **title, **mail, **sn;
134 BerElement *ber;
135 int indent, have_mail;
137 dn = NULL;
138 cn = org = title = unit = mail = sn = NULL;
139 for(a = ldap_first_attribute(res_list->ld, e, &ber);
140 a != NULL;
141 a = ldap_next_attribute(res_list->ld, e, ber)){
143 dprint((9, " %s", a ? a : "?"));
144 if(strcmp(a, res_list->info_used->cnattr) == 0){
145 if(!cn)
146 cn = ldap_get_values_len(res_list->ld, e, a);
148 if(cn && !ALPINE_LDAP_can_use(cn)){
149 ldap_value_free_len(cn);
150 cn = NULL;
153 else if(strcmp(a, res_list->info_used->mailattr) == 0){
154 if(!mail)
155 mail = ldap_get_values_len(res_list->ld, e, a);
157 else if(strcmp(a, "o") == 0){
158 if(!org)
159 org = ldap_get_values_len(res_list->ld, e, a);
161 else if(strcmp(a, "ou") == 0){
162 if(!unit)
163 unit = ldap_get_values_len(res_list->ld, e, a);
165 else if(strcmp(a, "title") == 0){
166 if(!title)
167 title = ldap_get_values_len(res_list->ld, e, a);
170 our_ldap_memfree(a);
173 dprint((9, "\n"));
175 if(!cn){
176 for(a = ldap_first_attribute(res_list->ld, e, &ber);
177 a != NULL;
178 a = ldap_next_attribute(res_list->ld, e, ber)){
180 if(strcmp(a, res_list->info_used->snattr) == 0){
181 if(!sn)
182 sn = ldap_get_values_len(res_list->ld, e, a);
184 if(sn && !ALPINE_LDAP_can_use(sn)){
185 ldap_value_free_len(sn);
186 sn = NULL;
190 our_ldap_memfree(a);
194 if(ALPINE_LDAP_can_use(mail))
195 have_mail = 1;
196 else
197 have_mail = 0;
199 got_n_mail += have_mail;
200 got_n_entries++;
201 indent = 2;
204 * First line is either cn, sn, or dn.
206 if(cn){
207 new_confline(&ctmpa);
208 if(!alt_first_line)
209 alt_first_line = ctmpa;
211 ctmpa->flags |= CF_STARTITEM;
212 if(need_mail && !have_mail)
213 ctmpa->flags |= CF_PRIVATE;
215 ctmpa->value = cpystr(cn[0]->bv_val);
216 ldap_value_free_len(cn);
217 ctmpa->valoffset = indent;
218 ctmpa->keymenu = km;
219 ctmpa->help = help;
220 ctmpa->help_title = _(srch_res_help_title);
221 ctmpa->tool = addr_select_tool;
222 ctmpa->d.a.ld = res_list->ld;
223 ctmpa->d.a.entry = e;
224 ctmpa->d.a.info_used = res_list->info_used;
225 ctmpa->d.a.serv = res_list->serv;
226 ctmpa->d.a.ac = ac;
227 if(!first_line && (have_mail || !need_mail))
228 first_line = ctmpa;
231 /* only happens if no cn */
232 if(sn){
233 new_confline(&ctmpa);
234 if(!alt_first_line)
235 alt_first_line = ctmpa;
237 ctmpa->flags |= CF_STARTITEM;
238 if(need_mail && !have_mail)
239 ctmpa->flags |= CF_PRIVATE;
241 ctmpa->value = cpystr(sn[0]->bv_val);
242 ldap_value_free_len(sn);
243 ctmpa->valoffset = indent;
244 ctmpa->keymenu = km;
245 ctmpa->help = help;
246 ctmpa->help_title = _(srch_res_help_title);
247 ctmpa->tool = addr_select_tool;
248 ctmpa->d.a.ld = res_list->ld;
249 ctmpa->d.a.entry = e;
250 ctmpa->d.a.info_used = res_list->info_used;
251 ctmpa->d.a.serv = res_list->serv;
252 ctmpa->d.a.ac = ac;
253 if(!first_line && (have_mail || !need_mail))
254 first_line = ctmpa;
257 if(!sn && !cn){
258 new_confline(&ctmpa);
259 if(!alt_first_line)
260 alt_first_line = ctmpa;
262 ctmpa->flags |= CF_STARTITEM;
263 if(need_mail && !have_mail)
264 ctmpa->flags |= CF_PRIVATE;
266 dn = ldap_get_dn(res_list->ld, e);
268 if(dn && !dn[0]){
269 our_ldap_dn_memfree(dn);
270 dn = NULL;
273 ctmpa->value = cpystr(dn ? dn : "?");
274 if(dn)
275 our_ldap_dn_memfree(dn);
277 ctmpa->valoffset = indent;
278 ctmpa->keymenu = km;
279 ctmpa->help = help;
280 ctmpa->help_title = _(srch_res_help_title);
281 ctmpa->tool = addr_select_tool;
282 ctmpa->d.a.ld = res_list->ld;
283 ctmpa->d.a.entry = e;
284 ctmpa->d.a.info_used = res_list->info_used;
285 ctmpa->d.a.serv = res_list->serv;
286 ctmpa->d.a.ac = ac;
287 if(!first_line && (have_mail || !need_mail))
288 first_line = ctmpa;
291 if(title){
292 for(i = 0; ALPINE_LDAP_usable(title, i); i++){
293 new_confline(&ctmpa);
294 ctmpa->flags |= CF_NOSELECT;
295 ctmpa->valoffset = indent + 2;
296 ctmpa->value = cpystr(title[i]->bv_val);
297 ctmpa->keymenu = km;
298 ctmpa->help = help;
299 ctmpa->help_title = _(srch_res_help_title);
300 ctmpa->tool = addr_select_tool;
301 ctmpa->d.a.ld = res_list->ld;
302 ctmpa->d.a.entry = e;
303 ctmpa->d.a.info_used = res_list->info_used;
304 ctmpa->d.a.serv = res_list->serv;
305 ctmpa->d.a.ac = ac;
308 ldap_value_free_len(title);
311 if(unit){
312 for(i = 0; ALPINE_LDAP_usable(unit, i); i++){
313 new_confline(&ctmpa);
314 ctmpa->flags |= CF_NOSELECT;
315 ctmpa->valoffset = indent + 2;
316 ctmpa->value = cpystr(unit[i]->bv_val);
317 ctmpa->keymenu = km;
318 ctmpa->help = help;
319 ctmpa->help_title = _(srch_res_help_title);
320 ctmpa->tool = addr_select_tool;
321 ctmpa->d.a.ld = res_list->ld;
322 ctmpa->d.a.entry = e;
323 ctmpa->d.a.info_used = res_list->info_used;
324 ctmpa->d.a.serv = res_list->serv;
325 ctmpa->d.a.ac = ac;
328 ldap_value_free_len(unit);
331 if(org){
332 for(i = 0; ALPINE_LDAP_usable(org, i); i++){
333 new_confline(&ctmpa);
334 ctmpa->flags |= CF_NOSELECT;
335 ctmpa->valoffset = indent + 2;
336 ctmpa->value = cpystr(org[i]->bv_val);
337 ctmpa->keymenu = km;
338 ctmpa->help = help;
339 ctmpa->help_title = _(srch_res_help_title);
340 ctmpa->tool = addr_select_tool;
341 ctmpa->d.a.ld = res_list->ld;
342 ctmpa->d.a.entry = e;
343 ctmpa->d.a.info_used = res_list->info_used;
344 ctmpa->d.a.serv = res_list->serv;
345 ctmpa->d.a.ac = ac;
348 ldap_value_free_len(org);
351 if(have_mail){
352 /* Don't show long list of email addresses. */
353 if(!ALPINE_LDAP_can_use_num(mail, 0) ||
354 !ALPINE_LDAP_can_use_num(mail, 1) ||
355 !ALPINE_LDAP_can_use_num(mail, 2) ||
356 !ALPINE_LDAP_can_use_num(mail, 3)){
357 for(i = 0; ALPINE_LDAP_usable(mail, i); i++){
358 new_confline(&ctmpa);
359 ctmpa->flags |= CF_NOSELECT;
360 ctmpa->valoffset = indent + 2;
361 ctmpa->value = cpystr(mail[i]->bv_val);
362 ctmpa->keymenu = km;
363 ctmpa->help = help;
364 ctmpa->help_title = _(srch_res_help_title);
365 ctmpa->tool = addr_select_tool;
366 ctmpa->d.a.ld = res_list->ld;
367 ctmpa->d.a.entry = e;
368 ctmpa->d.a.info_used = res_list->info_used;
369 ctmpa->d.a.serv = res_list->serv;
370 ctmpa->d.a.ac = ac;
373 else{
374 char tmp[200];
376 for(i = 4; ALPINE_LDAP_usable(mail, i); i++)
379 new_confline(&ctmpa);
380 ctmpa->flags |= CF_NOSELECT;
381 ctmpa->valoffset = indent + 2;
382 snprintf(tmp, sizeof(tmp), _("(%d email addresses)"), i);
383 tmp[sizeof(tmp)-1] = '\0';
384 ctmpa->value = cpystr(tmp);
385 ctmpa->keymenu = km;
386 ctmpa->help = help;
387 ctmpa->help_title = _(srch_res_help_title);
388 ctmpa->tool = addr_select_tool;
389 ctmpa->d.a.ld = res_list->ld;
390 ctmpa->d.a.entry = e;
391 ctmpa->d.a.info_used = res_list->info_used;
392 ctmpa->d.a.serv = res_list->serv;
393 ctmpa->d.a.ac = ac;
396 else{
397 new_confline(&ctmpa);
398 ctmpa->flags |= CF_NOSELECT;
399 ctmpa->valoffset = indent + 2;
400 ctmpa->value = cpystr(_("<No Email Address Available>"));
401 ctmpa->keymenu = km;
402 ctmpa->help = help;
403 ctmpa->help_title = _(srch_res_help_title);
404 ctmpa->tool = addr_select_tool;
405 ctmpa->d.a.ld = res_list->ld;
406 ctmpa->d.a.entry = e;
407 ctmpa->d.a.info_used = res_list->info_used;
408 ctmpa->d.a.serv = res_list->serv;
409 ctmpa->d.a.ac = ac;
412 if(mail)
413 ldap_value_free_len(mail);
415 new_confline(&ctmpa); /* blank line */
416 ctmpa->keymenu = km;
417 ctmpa->help = help;
418 ctmpa->help_title = _(srch_res_help_title);
419 ctmpa->tool = addr_select_tool;
420 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
424 if(first_line)
425 some_selectable++;
426 else if(alt_first_line)
427 first_line = alt_first_line;
428 else{
429 new_confline(&ctmpa); /* blank line */
430 ctmpa->keymenu = need_mail ? &addr_s_km_exit : &addr_s_km_goback;
431 ctmpa->help = help;
432 ctmpa->help_title = _(srch_res_help_title);
433 ctmpa->tool = addr_select_tool;
434 ctmpa->flags |= CF_NOSELECT | CF_B_LINE;
436 new_confline(&ctmpa);
437 first_line = ctmpa;
438 strncpy(ee, "[ ", sizeof(ee));
439 ee[sizeof(ee)-1] = '\0';
440 if(wp_err && wp_err->ldap_errno)
441 /* TRANSLATORS: No matches returned for an LDAP search */
442 snprintf(ee+2, sizeof(ee)-2, _("%s, No Matches Returned"),
443 ldap_err2string(wp_err->ldap_errno));
444 else
445 strncpy(ee+2, _("No Matches"), sizeof(ee)-2);
447 ee[sizeof(ee)-1] = '\0';
449 /* TRANSLATORS: a request for user to choose Exit after they read text */
450 strncat(ee, _(" -- Choose Exit ]"), sizeof(ee)-strlen(ee)-1);
451 ee[sizeof(ee)-1] = '\0';
452 ctmpa->value = cpystr(ee);
453 ctmpa->valoffset = 10;
454 ctmpa->keymenu = need_mail ? &addr_s_km_exit : &addr_s_km_goback;
455 ctmpa->help = help;
456 ctmpa->help_title = _(srch_res_help_title);
457 ctmpa->tool = addr_select_tool;
458 ctmpa->flags |= CF_NOSELECT;
461 if(style == AlwaysDisplay || style == DisplayForURL ||
462 style == AlwaysDisplayAndMailRequired ||
463 (style == DisplayIfOne && got_n_mail >= 1) ||
464 (style == DisplayIfTwo && got_n_mail >= 1 && got_n_entries >= 2)){
465 if(wp_err && wp_err->mangled)
466 *wp_err->mangled = 1;
468 prev_redrawer = ps_global->redrawer;
469 push_titlebar_state();
471 memset(&screen, 0, sizeof(screen));
472 /* TRANSLATORS: Print something1 using something2.
473 "this" is something1 */
474 switch(conf_scroll_screen(ps,&screen,first_line,ac->title,_("this"),0, NULL)){
475 case ADDR_SELECT_EXIT_VAL:
476 retval = -1;
477 break;
479 case ADDR_SELECT_GOBACK_VAL:
480 retval = -4;
481 break;
483 case ADDR_SELECT_FORCED_EXIT_VAL:
484 if(alt_first_line) /* some entries, but none suitable */
485 retval = -2;
486 else
487 retval = -3;
489 break;
491 default:
492 retval = 0;
493 break;
496 ClearScreen();
497 pop_titlebar_state();
498 redraw_titlebar();
499 if((ps_global->redrawer = prev_redrawer) != NULL)
500 (*ps_global->redrawer)();
502 if(result && retval == 0 && ac->selected_ld && ac->selected_entry){
503 (*result) = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S));
504 (*result)->ld = ac->selected_ld;
505 (*result)->selected_entry = ac->selected_entry;
506 (*result)->info_used = ac->info_used;
507 (*result)->serv = ac->selected_serv;
510 else if(style == DisplayIfOne && got_n_mail < 1){
511 if(alt_first_line) /* some entries, but none suitable */
512 retval = -2;
513 else
514 retval = -3;
516 first_line = first_confline(ctmpa);
517 free_conflines(&first_line);
519 else if(style == DisplayIfTwo && (got_n_mail < 1 || got_n_entries < 2)){
520 if(got_n_mail < 1){
521 if(alt_first_line) /* some entries, but none suitable */
522 retval = -2;
523 else
524 retval = -3;
526 else{
527 retval = 0;
528 if(result){
529 (*result) = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S));
530 (*result)->ld = first_line->d.a.ld;
531 (*result)->selected_entry = first_line->d.a.entry;
532 (*result)->info_used = first_line->d.a.info_used;
533 (*result)->serv = first_line->d.a.serv;
537 first_line = first_confline(ctmpa);
538 free_conflines(&first_line);
541 return(retval);
546 addr_select_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
548 int retval = 0;
550 switch(cmd){
551 case MC_CHOICE :
552 if(flags & CF_PRIVATE){
553 q_status_message(SM_ORDER | SM_DING, 0, 3,
554 _("No email address available for this entry; choose another or ExitSelect"));
556 else if(some_selectable){
557 (*cl)->d.a.ac->selected_ld = (*cl)->d.a.ld;
558 (*cl)->d.a.ac->selected_entry = (*cl)->d.a.entry;
559 (*cl)->d.a.ac->info_used = (*cl)->d.a.info_used;
560 (*cl)->d.a.ac->selected_serv = (*cl)->d.a.serv;
561 retval = simple_exit_cmd(flags);
563 else
564 retval = ADDR_SELECT_FORCED_EXIT_VAL;
566 break;
568 case MC_VIEW_TEXT :
569 case MC_SAVE :
570 case MC_FWDTEXT :
571 case MC_COMPOSE :
572 case MC_ROLE :
573 {LDAP_CHOOSE_S *e;
575 if((*cl)->d.a.ld && (*cl)->d.a.entry){
576 e = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S));
577 e->ld = (*cl)->d.a.ld;
578 e->selected_entry = (*cl)->d.a.entry;
579 e->info_used = (*cl)->d.a.info_used;
580 e->serv = (*cl)->d.a.serv;
581 if(cmd == MC_VIEW_TEXT)
582 view_ldap_entry(ps, e);
583 else if(cmd == MC_SAVE)
584 save_ldap_entry(ps, e, 0);
585 else if(cmd == MC_COMPOSE)
586 compose_to_ldap_entry(ps, e, 0);
587 else if(cmd == MC_ROLE)
588 compose_to_ldap_entry(ps, e, 1);
589 else
590 forward_ldap_entry(ps, e);
592 fs_give((void **)&e);
596 break;
598 case MC_ADDRBOOK :
599 retval = ADDR_SELECT_GOBACK_VAL;
600 break;
602 case MC_EXIT :
603 retval = ADDR_SELECT_EXIT_VAL;
604 break;
606 default:
607 retval = -1;
608 break;
611 if(retval > 0)
612 ps->mangled_body = 1;
614 return(retval);
618 void
619 dir_init_display(struct pine *ps, CONF_S **ctmp, char **servers,
620 struct variable *var, CONF_S **first_line)
622 int i;
623 char *serv;
624 char *subtitle;
625 size_t sizeofsub;
626 LDAP_SERV_S *info;
628 if(first_line)
629 *first_line = NULL;
631 if(servers && servers[0] && servers[0][0]){
632 for(i = 0; servers[i]; i++){
633 info = break_up_ldap_server(servers[i]);
634 serv = (info && info->nick && *info->nick) ? cpystr(info->nick) :
635 (info && info->serv && *info->serv) ? cpystr(info->serv) :
636 cpystr(_("Bad Server Config, Delete this"));
637 sizeofsub = (((info && info->serv && *info->serv)
638 ? strlen(info->serv)
639 : 3) + strlen(_(dserv)) + 15) * sizeof(char);
640 subtitle = (char *)fs_get(sizeofsub);
641 if(info && info->port >= 0)
642 snprintf(subtitle, sizeofsub, "%s%s:%d",
643 _(dserv),
644 (info && info->serv && *info->serv) ? info->serv : "<?>",
645 info->port);
646 else
647 snprintf(subtitle, sizeofsub, "%s%s",
648 _(dserv),
649 (info && info->serv && *info->serv) ? info->serv : "<?>");
651 subtitle[sizeofsub-1] = '\0';
653 add_ldap_server_to_display(ps, ctmp, serv, subtitle, var,
654 i, &dir_conf_km, h_direct_config,
655 dir_config_tool, 0,
656 (first_line && *first_line == NULL)
657 ? first_line
658 : NULL);
660 free_ldap_server_info(&info);
663 else{
664 add_ldap_fake_first_server(ps, ctmp, var,
665 &dir_conf_km, h_direct_config,
666 dir_config_tool);
667 if(first_line)
668 *first_line = *ctmp;
673 void
674 directory_config(struct pine *ps, int edit_exceptions)
676 CONF_S *ctmp = NULL, *first_line = NULL;
677 OPT_SCREEN_S screen;
678 int no_ex, readonly_warning = 0;
680 if(edit_exceptions){
681 q_status_message(SM_ORDER, 3, 7,
682 _("Exception Setup not implemented for directory"));
683 return;
686 ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
688 no_ex = (ps_global->ew_for_except_vars == Main);
690 if(ps->restricted)
691 readonly_warning = 1;
692 else{
693 PINERC_S *prc = NULL;
695 switch(ew){
696 case Main:
697 prc = ps->prc;
698 break;
699 case Post:
700 prc = ps->post_prc;
701 break;
702 default:
703 break;
706 readonly_warning = prc ? prc->readonly : 1;
707 if(prc && prc->quit_to_edit){
708 quit_to_edit_msg(prc);
709 return;
713 if(ps->fix_fixed_warning)
714 offer_to_fix_pinerc(ps);
716 dir_init_display(ps, &ctmp, no_ex ? ps->VAR_LDAP_SERVERS
717 : LVAL(&ps->vars[V_LDAP_SERVERS], ew),
718 &ps->vars[V_LDAP_SERVERS], &first_line);
720 memset(&screen, 0, sizeof(screen));
721 screen.deferred_ro_warning = readonly_warning;
722 /* TRANSLATORS: Print something1 using something2.
723 "servers" is something1 */
724 (void)conf_scroll_screen(ps, &screen, first_line,
725 _("SETUP DIRECTORY SERVERS"), _("servers"), 0, NULL);
726 ps->mangled_screen = 1;
731 dir_config_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
733 int first_one, rv = 0;
735 first_one = (*cl)->value &&
736 (strcmp((*cl)->value, ADD_FIRST_LDAP_SERVER) == 0);
737 switch(cmd){
738 case MC_DELETE :
739 if(first_one)
740 q_status_message(SM_ORDER|SM_DING, 0, 3,
741 _("Nothing to Delete, use Add"));
742 else
743 dir_config_del(ps, cl);
745 break;
747 case MC_ADD :
748 if(!fixed_var((*cl)->var, NULL, "directory list"))
749 dir_config_add(ps, cl);
751 break;
753 case MC_EDIT :
754 if(!fixed_var((*cl)->var, NULL, "directory list")){
755 if(first_one)
756 dir_config_add(ps, cl);
757 else
758 dir_config_edit(ps, cl);
761 break;
763 case MC_SHUFFLE :
764 if(!fixed_var((*cl)->var, NULL, "directory list")){
765 if(first_one)
766 q_status_message(SM_ORDER|SM_DING, 0, 3,
767 _("Nothing to Shuffle, use Add"));
768 else
769 dir_config_shuffle(ps, cl);
772 break;
774 case MC_EXIT :
775 rv = 2;
776 break;
778 default:
779 rv = -1;
780 break;
783 return(rv);
788 * Add LDAP directory entry
790 void
791 dir_config_add(struct pine *ps, CONF_S **cl)
793 char *raw_server = NULL;
794 LDAP_SERV_S *info = NULL;
795 char **lval;
796 int no_ex;
798 no_ex = (ps_global->ew_for_except_vars == Main);
800 if(dir_edit_screen(ps, NULL, "ADD A", &raw_server) == 1){
802 info = break_up_ldap_server(raw_server);
804 if(info && info->serv && *info->serv){
805 char *subtitle;
806 size_t sizeofsub;
807 int i, cnt = 0;
808 char **new_list;
809 CONF_S *cp;
811 lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
812 if(lval)
813 while(lval[cnt])
814 cnt++;
816 /* catch the special "" case */
817 if(cnt == 0 ||
818 (cnt == 1 && lval[0][0] == '\0')){
819 new_list = (char **)fs_get((1 + 1) * sizeof(char *));
820 new_list[0] = raw_server;
821 new_list[1] = NULL;
823 else{
824 /* add one for new value */
825 cnt++;
826 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
828 for(i = 0; i < (*cl)->varmem; i++)
829 new_list[i] = cpystr(lval[i]);
831 new_list[(*cl)->varmem] = raw_server;
833 for(i = (*cl)->varmem; i < cnt; i++)
834 new_list[i+1] = cpystr(lval[i]);
837 raw_server = NULL;
838 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
839 free_list_array(&new_list);
840 set_current_val((*cl)->var, TRUE, FALSE);
841 sizeofsub = (((info && info->serv && *info->serv)
842 ? strlen(info->serv)
843 : 3) + strlen(_(dserv)) + 15) * sizeof(char);
844 subtitle = (char *)fs_get(sizeofsub);
845 if(info && info->port >= 0)
846 snprintf(subtitle, sizeofsub, "%s%s:%d",
847 _(dserv),
848 (info && info->serv && *info->serv) ? info->serv : "<?>",
849 info->port);
850 else
851 snprintf(subtitle, sizeofsub, "%s%s",
852 _(dserv),
853 (info && info->serv && *info->serv) ? info->serv : "<?>");
855 subtitle[sizeofsub-1] = '\0';
857 if(cnt < 2){ /* first one */
858 struct variable *var;
859 struct key_menu *keymenu;
860 HelpType help;
861 int (*tool)(struct pine *, int, CONF_S **, unsigned);
863 var = (*cl)->var;
864 keymenu = (*cl)->keymenu;
865 help = (*cl)->help;
866 tool = (*cl)->tool;
867 *cl = first_confline(*cl);
868 free_conflines(cl);
869 add_ldap_server_to_display(ps, cl,
870 (info && info->nick && *info->nick)
871 ? cpystr(info->nick)
872 : cpystr(info->serv),
873 subtitle, var, 0, keymenu, help,
874 tool, 0, NULL);
876 opt_screen->top_line = NULL;
878 else{
880 * Insert new server.
882 add_ldap_server_to_display(ps, cl,
883 (info && info->nick && *info->nick)
884 ? cpystr(info->nick)
885 : cpystr(info->serv),
886 subtitle,
887 (*cl)->var,
888 (*cl)->varmem,
889 (*cl)->keymenu,
890 (*cl)->help,
891 (*cl)->tool,
893 NULL);
894 /* adjust the rest of the varmems */
895 for(cp = (*cl)->next; cp; cp = cp->next)
896 cp->varmem++;
899 /* because add_ldap advanced cl to its third line */
900 (*cl) = (*cl)->prev->prev;
902 fix_side_effects(ps, (*cl)->var, 0);
903 write_pinerc(ps, ew, WRP_NONE);
905 else
906 q_status_message(SM_ORDER, 0, 3, _("Add cancelled, no server name"));
909 free_ldap_server_info(&info);
910 if(raw_server)
911 fs_give((void **)&raw_server);
916 * Shuffle order of LDAP directory entries
918 void
919 dir_config_shuffle(struct pine *ps, CONF_S **cl)
921 int cnt, rv, current_num, new_num, i, j, deefault;
922 char **new_list, **lval;
923 char tmp[200];
924 HelpType help;
925 ESCKEY_S opts[3];
926 CONF_S *a, *b;
927 int no_ex;
929 no_ex = (ps_global->ew_for_except_vars == Main);
931 /* how many are in our current list? */
932 lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
933 for(cnt = 0; lval && lval[cnt]; cnt++)
936 if(cnt < 2){
937 q_status_message(SM_ORDER, 0, 3,
938 _("Shuffle only makes sense when there is more than one server in list"));
939 return;
942 current_num = (*cl)->varmem; /* variable number of highlighted directory */
944 /* Move it up or down? */
945 i = 0;
946 opts[i].ch = 'u';
947 opts[i].rval = 'u';
948 opts[i].name = "U";
949 opts[i++].label = _("Up");
951 opts[i].ch = 'd';
952 opts[i].rval = 'd';
953 opts[i].name = "D";
954 opts[i++].label = _("Down");
956 opts[i].ch = -1;
957 deefault = 'u';
959 if(current_num == 0){ /* no up */
960 opts[0].ch = -2;
961 deefault = 'd';
963 else if(current_num == cnt - 1) /* no down */
964 opts[1].ch = -2;
966 snprintf(tmp, sizeof(tmp), "Shuffle \"%s\" %s%s%s ? ",
967 (*cl)->value,
968 (opts[0].ch != -2) ? _("UP") : "",
969 (opts[0].ch != -2 && opts[1].ch != -2) ? " or " : "",
970 (opts[1].ch != -2) ? _("DOWN") : "");
971 tmp[sizeof(tmp)-1] = '\0';
972 help = (opts[0].ch == -2) ? h_dir_shuf_down
973 : (opts[1].ch == -2) ? h_dir_shuf_up
974 : h_dir_shuf;
976 rv = radio_buttons(tmp, -FOOTER_ROWS(ps), opts, deefault, 'x',
977 help, RB_NORM);
979 switch(rv){
980 case 'x':
981 cmd_cancelled("Shuffle");
982 return;
984 case 'u':
985 new_num = current_num - 1;
986 a = (*cl)->prev->prev->prev;
987 b = *cl;
988 break;
990 case 'd':
991 new_num = current_num + 1;
992 a = *cl;
993 b = (*cl)->next->next->next;
994 break;
997 /* allocate space for new list */
998 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
1000 /* fill in new_list */
1001 for(i = 0; i < cnt; i++){
1002 if(i == current_num)
1003 j = new_num;
1004 else if (i == new_num)
1005 j = current_num;
1006 else
1007 j = i;
1009 /* notice this works even if we were using default */
1010 new_list[i] = cpystr(lval[j]);
1013 new_list[i] = NULL;
1015 j = set_variable_list((*cl)->var - ps->vars, new_list, TRUE, ew);
1016 free_list_array(&new_list);
1017 if(j){
1018 q_status_message(SM_ORDER, 0, 3,
1019 _("Shuffle cancelled: couldn't save configuration file"));
1020 set_current_val((*cl)->var, TRUE, FALSE);
1021 return;
1024 set_current_val((*cl)->var, TRUE, FALSE);
1026 if(a == opt_screen->top_line)
1027 opt_screen->top_line = b;
1029 j = a->varmem;
1030 a->varmem = b->varmem;
1031 b->varmem = j;
1034 * Swap display lines. To start with, a is lower in list, b is higher.
1035 * The fact that there are 3 lines per entry is totally entangled in
1036 * the code.
1038 a->next->next->next = b->next->next->next;
1039 if(b->next->next->next)
1040 b->next->next->next->prev = a->next->next;
1041 b->prev = a->prev;
1042 if(a->prev)
1043 a->prev->next = b;
1044 b->next->next->next = a;
1045 a->prev = b->next->next;
1047 ps->mangled_body = 1;
1048 write_pinerc(ps, ew, WRP_NONE);
1053 * Edit LDAP directory entry
1055 void
1056 dir_config_edit(struct pine *ps, CONF_S **cl)
1058 char *raw_server = NULL, **lval;
1059 LDAP_SERV_S *info;
1060 int no_ex;
1062 no_ex = (ps_global->ew_for_except_vars == Main);
1064 lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
1065 info = break_up_ldap_server((lval && lval[(*cl)->varmem])
1066 ? lval[(*cl)->varmem] : NULL);
1068 if(dir_edit_screen(ps, info, "CHANGE THIS", &raw_server) == 1){
1070 free_ldap_server_info(&info);
1071 info = break_up_ldap_server(raw_server);
1073 if(lval && lval[(*cl)->varmem] &&
1074 strcmp(lval[(*cl)->varmem], raw_server) == 0)
1075 q_status_message(SM_ORDER, 0, 3, _("No change, cancelled"));
1076 else if(!(info && info->serv && *info->serv))
1077 q_status_message(SM_ORDER, 0, 3,
1078 _("Change cancelled, use Delete if you want to remove this server"));
1079 else{
1080 char *subtitle;
1081 int i, cnt;
1082 char **new_list;
1083 size_t sizeofsub;
1085 for(cnt = 0; lval && lval[cnt]; cnt++)
1088 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
1090 for(i = 0; i < (*cl)->varmem; i++)
1091 new_list[i] = cpystr(lval[i]);
1093 new_list[(*cl)->varmem] = raw_server;
1094 raw_server = NULL;
1096 for(i = (*cl)->varmem + 1; i < cnt; i++)
1097 new_list[i] = cpystr(lval[i]);
1099 new_list[cnt] = NULL;
1100 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
1101 free_list_array(&new_list);
1102 set_current_val((*cl)->var, TRUE, FALSE);
1104 if((*cl)->value)
1105 fs_give((void **)&(*cl)->value);
1107 (*cl)->value = cpystr((info->nick && *info->nick) ? info->nick
1108 : info->serv);
1110 if((*cl)->next->value)
1111 fs_give((void **)&(*cl)->next->value);
1113 sizeofsub = (((info && info->serv && *info->serv)
1114 ? strlen(info->serv)
1115 : 3) + strlen(_(dserv)) + 15) * sizeof(char);
1117 subtitle = (char *)fs_get(sizeofsub);
1118 if(info && info->port >= 0)
1119 snprintf(subtitle, sizeofsub, "%s%s:%d",
1120 _(dserv),
1121 (info && info->serv && *info->serv) ? info->serv : "<?>",
1122 info->port);
1123 else
1124 snprintf(subtitle, sizeofsub, "%s%s",
1125 _(dserv),
1126 (info && info->serv && *info->serv) ? info->serv : "<?>");
1128 subtitle[sizeofsub] = '\0';
1130 (*cl)->next->value = subtitle;
1132 fix_side_effects(ps, (*cl)->var, 0);
1133 write_pinerc(ps, ew, WRP_NONE);
1137 free_ldap_server_info(&info);
1138 if(raw_server)
1139 fs_give((void **)&raw_server);
1143 #define LDAP_F_IMPL 0
1144 #define LDAP_F_RHS 1
1145 #define LDAP_F_REF 2
1146 #define LDAP_F_NOSUB 3
1147 #define LDAP_F_TLS 4
1148 #define LDAP_F_TLSMUST 5
1149 #define LDAP_F_LDAPS 6
1150 bitmap_t ldap_option_list;
1151 struct variable *ldap_srch_rule_ptr;
1154 * Gives user screen to edit config values for ldap server.
1156 * Args ps -- pine struct
1157 * def -- default values to start with
1158 * title -- part of title at top of screen
1159 * raw_server -- This is the returned item, allocated here and freed by caller.
1161 * Returns: 0 if no change
1162 * 1 if user requested a change
1163 * (change is stored in raw_server and hasn't been acted upon yet)
1164 * 10 user says abort
1167 dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_server)
1169 OPT_SCREEN_S screen, *saved_screen;
1170 CONF_S *ctmp = NULL, *ctmpb, *first_line = NULL;
1171 char tmp[MAXPATH+1], custom_scope[MAXPATH], **apval;
1172 int rv, i, j, lv, indent, rindent;
1173 NAMEVAL_S *f;
1174 struct variable server_var, base_var, binddn_var, port_var, nick_var,
1175 srch_type_var, srch_rule_var, time_var,
1176 size_var, mailattr_var, cnattr_var,
1177 snattr_var, gnattr_var, cust_var,
1178 opt_var, *v, *varlist[21];
1179 char *server = NULL, *base = NULL, *port = NULL, *nick = NULL,
1180 *srch_type = NULL, *srch_rule = NULL, *ttime = NULL,
1181 *c_s_f = "custom-search-filter", *binddn = NULL,
1182 *ssize = NULL, *mailattr = NULL, *cnattr = NULL,
1183 *snattr = NULL, *gnattr = NULL, *cust = NULL;
1186 * We edit by making a nested call to conf_scroll_screen.
1187 * We use some fake struct variables to get back the results in, and
1188 * so we can use the existing tools from the config screen.
1191 custom_scope[0] = '\0';
1193 varlist[j = 0] = &server_var;
1194 varlist[++j] = &base_var;
1195 varlist[++j] = &port_var;
1196 varlist[++j] = &binddn_var;
1197 varlist[++j] = &nick_var;
1198 varlist[++j] = &srch_type_var;
1199 varlist[++j] = &srch_rule_var;
1200 varlist[++j] = &time_var;
1201 varlist[++j] = &size_var;
1202 varlist[++j] = &mailattr_var;
1203 varlist[++j] = &cnattr_var;
1204 varlist[++j] = &snattr_var;
1205 varlist[++j] = &gnattr_var;
1206 varlist[++j] = &cust_var;
1207 varlist[++j] = &opt_var;
1208 varlist[++j] = NULL;
1209 for(j = 0; varlist[j]; j++)
1210 memset(varlist[j], 0, sizeof(struct variable));
1212 server_var.name = cpystr("ldap-server");
1213 server_var.is_used = 1;
1214 server_var.is_user = 1;
1215 apval = APVAL(&server_var, ew);
1216 *apval = (def && def->serv && def->serv[0]) ? cpystr(def->serv) : NULL;
1217 set_current_val(&server_var, FALSE, FALSE);
1219 base_var.name = cpystr("search-base");
1220 base_var.is_used = 1;
1221 base_var.is_user = 1;
1222 apval = APVAL(&base_var, ew);
1223 *apval = (def && def->base && def->base[0]) ? cpystr(def->base) : NULL;
1224 set_current_val(&base_var, FALSE, FALSE);
1226 port_var.name = cpystr("port");
1227 port_var.is_used = 1;
1228 port_var.is_user = 1;
1229 if(def && def->port >= 0){
1230 apval = APVAL(&port_var, ew);
1231 *apval = cpystr(int2string(def->port));
1234 port_var.global_val.p = cpystr(int2string(LDAP_PORT));
1235 set_current_val(&port_var, FALSE, FALSE);
1237 binddn_var.name = cpystr("bind-dn");
1238 binddn_var.is_used = 1;
1239 binddn_var.is_user = 1;
1240 apval = APVAL(&binddn_var, ew);
1241 *apval = (def && def->binddn && def->binddn[0]) ? cpystr(def->binddn) : NULL;
1242 set_current_val(&binddn_var, FALSE, FALSE);
1244 nick_var.name = cpystr("nickname");
1245 nick_var.is_used = 1;
1246 nick_var.is_user = 1;
1247 apval = APVAL(&nick_var, ew);
1248 *apval = (def && def->nick && def->nick[0]) ? cpystr(def->nick) : NULL;
1249 set_current_val(&nick_var, FALSE, FALSE);
1251 srch_type_var.name = cpystr("search-type");
1252 srch_type_var.is_used = 1;
1253 srch_type_var.is_user = 1;
1254 apval = APVAL(&srch_type_var, ew);
1255 *apval = (f=ldap_search_types(def ? def->type : -1))
1256 ? cpystr(f->name) : NULL;
1257 srch_type_var.global_val.p =
1258 (f=ldap_search_types(DEF_LDAP_TYPE)) ? cpystr(f->name) : NULL;
1259 set_current_val(&srch_type_var, FALSE, FALSE);
1261 ldap_srch_rule_ptr = &srch_rule_var; /* so radiobuttons can tell */
1262 srch_rule_var.name = cpystr("search-rule");
1263 srch_rule_var.is_used = 1;
1264 srch_rule_var.is_user = 1;
1265 apval = APVAL(&srch_rule_var, ew);
1266 *apval = (f=ldap_search_rules(def ? def->srch : -1))
1267 ? cpystr(f->name) : NULL;
1268 srch_rule_var.global_val.p =
1269 (f=ldap_search_rules(DEF_LDAP_SRCH)) ? cpystr(f->name) : NULL;
1270 set_current_val(&srch_rule_var, FALSE, FALSE);
1272 time_var.name = cpystr("timelimit");
1273 time_var.is_used = 1;
1274 time_var.is_user = 1;
1275 if(def && def->time >= 0){
1276 apval = APVAL(&time_var, ew);
1277 *apval = cpystr(int2string(def->time));
1280 time_var.global_val.p = cpystr(int2string(DEF_LDAP_TIME));
1281 set_current_val(&time_var, FALSE, FALSE);
1283 size_var.name = cpystr("sizelimit");
1284 size_var.is_used = 1;
1285 size_var.is_user = 1;
1286 if(def && def->size >= 0){
1287 apval = APVAL(&size_var, ew);
1288 *apval = cpystr(int2string(def->size));
1291 size_var.global_val.p = cpystr(int2string(DEF_LDAP_SIZE));
1292 set_current_val(&size_var, FALSE, FALSE);
1294 mailattr_var.name = cpystr("email-attribute");
1295 mailattr_var.is_used = 1;
1296 mailattr_var.is_user = 1;
1297 apval = APVAL(&mailattr_var, ew);
1298 *apval = (def && def->mailattr && def->mailattr[0])
1299 ? cpystr(def->mailattr) : NULL;
1300 mailattr_var.global_val.p = cpystr(DEF_LDAP_MAILATTR);
1301 set_current_val(&mailattr_var, FALSE, FALSE);
1303 cnattr_var.name = cpystr("name-attribute");
1304 cnattr_var.is_used = 1;
1305 cnattr_var.is_user = 1;
1306 apval = APVAL(&cnattr_var, ew);
1307 *apval = (def && def->cnattr && def->cnattr[0])
1308 ? cpystr(def->cnattr) : NULL;
1309 cnattr_var.global_val.p = cpystr(DEF_LDAP_CNATTR);
1310 set_current_val(&cnattr_var, FALSE, FALSE);
1312 snattr_var.name = cpystr("surname-attribute");
1313 snattr_var.is_used = 1;
1314 snattr_var.is_user = 1;
1315 apval = APVAL(&snattr_var, ew);
1316 *apval = (def && def->snattr && def->snattr[0])
1317 ? cpystr(def->snattr) : NULL;
1318 snattr_var.global_val.p = cpystr(DEF_LDAP_SNATTR);
1319 set_current_val(&snattr_var, FALSE, FALSE);
1321 gnattr_var.name = cpystr("givenname-attribute");
1322 gnattr_var.is_used = 1;
1323 gnattr_var.is_user = 1;
1324 apval = APVAL(&gnattr_var, ew);
1325 *apval = (def && def->gnattr && def->gnattr[0])
1326 ? cpystr(def->gnattr) : NULL;
1327 gnattr_var.global_val.p = cpystr(DEF_LDAP_GNATTR);
1328 set_current_val(&gnattr_var, FALSE, FALSE);
1330 cust_var.name = cpystr(c_s_f);
1331 cust_var.is_used = 1;
1332 cust_var.is_user = 1;
1333 apval = APVAL(&cust_var, ew);
1334 *apval = (def && def->cust && def->cust[0]) ? cpystr(def->cust) : NULL;
1335 set_current_val(&cust_var, FALSE, FALSE);
1337 /* TRANSLATORS: Features is a section title in the LDAP configuration screen. Following
1338 this are a list of features or options that can be turned on or off. */
1339 opt_var.name = cpystr(_("Features"));
1340 opt_var.is_used = 1;
1341 opt_var.is_user = 1;
1342 opt_var.is_list = 1;
1343 clrbitmap(ldap_option_list);
1344 if(def && def->impl)
1345 setbitn(LDAP_F_IMPL, ldap_option_list);
1346 if(def && def->rhs)
1347 setbitn(LDAP_F_RHS, ldap_option_list);
1348 if(def && def->ref)
1349 setbitn(LDAP_F_REF, ldap_option_list);
1350 if(def && def->nosub)
1351 setbitn(LDAP_F_NOSUB, ldap_option_list);
1352 if(def && def->tls)
1353 setbitn(LDAP_F_TLS, ldap_option_list);
1354 if(def && def->tlsmust)
1355 setbitn(LDAP_F_TLSMUST, ldap_option_list);
1356 if(def && def->ldaps)
1357 setbitn(LDAP_F_LDAPS, ldap_option_list);
1359 /* save the old opt_screen before calling scroll screen again */
1360 saved_screen = opt_screen;
1362 indent = utf8_width(c_s_f) + 3;
1363 rindent = 12;
1365 /* Server */
1366 new_confline(&ctmp);
1367 ctmp->help_title= _("HELP FOR LDAP SERVER");
1368 ctmp->var = &server_var;
1369 ctmp->valoffset = indent;
1370 ctmp->keymenu = &config_text_keymenu;
1371 ctmp->help = h_config_ldap_server;
1372 ctmp->tool = dir_edit_tool;
1373 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,server_var.name);
1374 tmp[sizeof(tmp)-1] = '\0';
1375 ctmp->varname = cpystr(tmp);
1376 ctmp->varnamep = ctmp;
1377 ctmp->value = pretty_value(ps, ctmp);
1379 first_line = ctmp;
1381 /* Search Base */
1382 new_confline(&ctmp);
1383 ctmp->help_title= _("HELP FOR SERVER SEARCH BASE");
1384 ctmp->var = &base_var;
1385 ctmp->valoffset = indent;
1386 ctmp->keymenu = &config_text_keymenu;
1387 ctmp->help = h_config_ldap_base;
1388 ctmp->tool = dir_edit_tool;
1389 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,base_var.name);
1390 tmp[sizeof(tmp)-1] = '\0';
1391 ctmp->varname = cpystr(tmp);
1392 ctmp->varnamep = ctmp;
1393 ctmp->value = pretty_value(ps, ctmp);
1395 /* Port */
1396 new_confline(&ctmp);
1397 ctmp->help_title= _("HELP FOR PORT NUMBER");
1398 ctmp->var = &port_var;
1399 ctmp->valoffset = indent;
1400 ctmp->keymenu = &config_text_keymenu;
1401 ctmp->help = h_config_ldap_port;
1402 ctmp->tool = dir_edit_tool;
1403 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,port_var.name);
1404 tmp[sizeof(tmp)-1] = '\0';
1405 ctmp->varname = cpystr(tmp);
1406 ctmp->varnamep = ctmp;
1407 ctmp->value = pretty_value(ps, ctmp);
1408 ctmp->flags |= CF_NUMBER;
1410 /* Bind DN (DN to bind to if needed) */
1411 new_confline(&ctmp);
1412 ctmp->help_title= _("HELP FOR SERVER BIND DN");
1413 ctmp->var = &binddn_var;
1414 ctmp->valoffset = indent;
1415 ctmp->keymenu = &config_text_keymenu;
1416 ctmp->help = h_config_ldap_binddn;
1417 ctmp->tool = dir_edit_tool;
1418 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,binddn_var.name);
1419 tmp[sizeof(tmp)-1] = '\0';
1420 ctmp->varname = cpystr(tmp);
1421 ctmp->varnamep = ctmp;
1422 ctmp->value = pretty_value(ps, ctmp);
1424 /* Nickname */
1425 new_confline(&ctmp);
1426 ctmp->help_title= _("HELP FOR SERVER NICKNAME");
1427 ctmp->var = &nick_var;
1428 ctmp->valoffset = indent;
1429 ctmp->keymenu = &config_text_keymenu;
1430 ctmp->help = h_config_ldap_nick;
1431 ctmp->tool = dir_edit_tool;
1432 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,nick_var.name);
1433 tmp[sizeof(tmp)-1] = '\0';
1434 ctmp->varname = cpystr(tmp);
1435 ctmp->varnamep = ctmp;
1436 ctmp->value = pretty_value(ps, ctmp);
1438 /* Blank line */
1439 new_confline(&ctmp);
1440 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1442 /* Options */
1443 new_confline(&ctmp);
1444 ctmp->var = &opt_var;
1445 ctmp->keymenu = &config_checkbox_keymenu;
1446 ctmp->help = NO_HELP;
1447 ctmp->tool = NULL;
1448 snprintf(tmp, sizeof(tmp), "%s =", opt_var.name);
1449 tmp[sizeof(tmp)-1] = '\0';
1450 ctmp->varname = cpystr(tmp);
1451 ctmp->varnamep = ctmpb = ctmp;
1452 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM);
1454 new_confline(&ctmp);
1455 ctmp->var = NULL;
1456 ctmp->valoffset = rindent;
1457 ctmp->keymenu = &config_checkbox_keymenu;
1458 ctmp->help = NO_HELP;
1459 ctmp->tool = ldap_checkbox_tool;
1460 ctmp->varnamep = ctmpb;
1461 ctmp->flags |= CF_NOSELECT;
1462 ctmp->value = cpystr("Set Feature Name");
1464 new_confline(&ctmp);
1465 ctmp->var = NULL;
1466 ctmp->valoffset = rindent;
1467 ctmp->keymenu = &config_checkbox_keymenu;
1468 ctmp->help = NO_HELP;
1469 ctmp->tool = ldap_checkbox_tool;
1470 ctmp->varnamep = ctmpb;
1471 ctmp->flags |= CF_NOSELECT;
1472 ctmp->value = cpystr(set_choose);
1474 /* find longest value's name */
1475 for(lv = 0, i = 0; (f = ldap_feature_list(i)); i++)
1476 if(lv < (j = utf8_width(f->name)))
1477 lv = j;
1479 lv = MIN(lv, 100);
1481 /* enabling ldaps disables tls */
1482 if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
1483 && bitnset(f->value, ldap_option_list)){
1484 int clear = 0;
1485 if((f = ldap_feature_list(LDAP_F_TLS)) != NULL
1486 && bitnset(f->value, ldap_option_list)){
1487 clear++;
1488 clrbitn(f->value, ldap_option_list);
1490 if((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
1491 && bitnset(f->value, ldap_option_list)){
1492 clear++;
1493 clrbitn(f->value, ldap_option_list);
1495 if(clear > 0)
1496 q_status_message(SM_ORDER, 3, 3,
1497 _("Can not use TLS when connecting using LDAPS"));
1500 /* enabling tls disables ldaps */
1501 if(((f = ldap_feature_list(LDAP_F_TLS)) != NULL
1502 && bitnset(f->value, ldap_option_list))
1503 || ((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
1504 && bitnset(f->value, ldap_option_list))){
1505 if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
1506 && bitnset(f->value, ldap_option_list)){
1507 clrbitn(f->value, ldap_option_list);
1508 q_status_message(SM_ORDER, 3, 3,
1509 _("Can not use LDAPS when connecting using TLS"));
1513 for(i = 0; (f = ldap_feature_list(i)); i++){
1514 new_confline(&ctmp);
1515 ctmp->var = &opt_var;
1516 ctmp->help_title= _("HELP FOR LDAP FEATURES");
1517 ctmp->varnamep = ctmpb;
1518 ctmp->keymenu = &config_checkbox_keymenu;
1519 switch(i){
1520 case LDAP_F_IMPL:
1521 ctmp->help = h_config_ldap_opts_impl;
1522 break;
1523 case LDAP_F_RHS:
1524 ctmp->help = h_config_ldap_opts_rhs;
1525 break;
1526 case LDAP_F_REF:
1527 ctmp->help = h_config_ldap_opts_ref;
1528 break;
1529 case LDAP_F_NOSUB:
1530 ctmp->help = h_config_ldap_opts_nosub;
1531 break;
1532 case LDAP_F_TLS:
1533 ctmp->help = h_config_ldap_opts_tls;
1534 break;
1535 case LDAP_F_TLSMUST:
1536 ctmp->help = h_config_ldap_opts_tlsmust;
1537 break;
1538 case LDAP_F_LDAPS:
1539 ctmp->help = h_config_ldap_opts_ldaps;
1540 break;
1543 ctmp->tool = ldap_checkbox_tool;
1544 ctmp->valoffset = rindent;
1545 ctmp->varmem = i;
1546 utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w",
1547 bitnset(f->value, ldap_option_list) ? 'X' : ' ',
1548 lv, lv, f->name);
1549 tmp[sizeof(tmp)-1] = '\0';
1550 ctmp->value = cpystr(tmp);
1553 /* Blank line */
1554 new_confline(&ctmp);
1555 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1557 /* Search Type */
1558 new_confline(&ctmp);
1559 ctmp->var = &srch_type_var;
1560 ctmp->keymenu = &config_radiobutton_keymenu;
1561 ctmp->help = NO_HELP;
1562 ctmp->tool = NULL;
1563 snprintf(tmp, sizeof(tmp), "%s =", srch_type_var.name);
1564 tmp[sizeof(tmp)-1] = '\0';
1565 ctmp->varname = cpystr(tmp);
1566 ctmp->varnamep = ctmpb = ctmp;
1567 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM);
1569 new_confline(&ctmp);
1570 ctmp->var = NULL;
1571 ctmp->valoffset = rindent;
1572 ctmp->keymenu = &config_radiobutton_keymenu;
1573 ctmp->help = NO_HELP;
1574 ctmp->tool = NULL;
1575 ctmp->varnamep = ctmpb;
1576 ctmp->flags |= CF_NOSELECT;
1577 ctmp->value = cpystr("Set Rule Values");
1579 new_confline(&ctmp);
1580 ctmp->var = NULL;
1581 ctmp->valoffset = rindent;
1582 ctmp->keymenu = &config_radiobutton_keymenu;
1583 ctmp->help = NO_HELP;
1584 ctmp->tool = ldap_radiobutton_tool;
1585 ctmp->varnamep = ctmpb;
1586 ctmp->flags |= CF_NOSELECT;
1587 ctmp->value = cpystr(set_choose);
1589 /* find longest value's name */
1590 for(lv = 0, i = 0; (f = ldap_search_types(i)); i++)
1591 if(lv < (j = utf8_width(f->name)))
1592 lv = j;
1594 lv = MIN(lv, 100);
1596 for(i = 0; (f = ldap_search_types(i)); i++){
1597 new_confline(&ctmp);
1598 ctmp->help_title= _("HELP FOR SEARCH TYPE");
1599 ctmp->var = &srch_type_var;
1600 ctmp->valoffset = rindent;
1601 ctmp->keymenu = &config_radiobutton_keymenu;
1602 ctmp->help = h_config_ldap_searchtypes;
1603 ctmp->varmem = i;
1604 ctmp->tool = ldap_radiobutton_tool;
1605 ctmp->varnamep = ctmpb;
1606 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!def || def->type == -1) &&
1607 f->value == DEF_LDAP_TYPE) ||
1608 (def && f->value == def->type))
1609 ? R_SELD : ' ',
1610 lv, lv, f->name);
1611 tmp[sizeof(tmp)-1] = '\0';
1612 ctmp->value = cpystr(tmp);
1615 /* Blank line */
1616 new_confline(&ctmp);
1617 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1618 ctmp->varname = cpystr("");
1620 /* Search Rule */
1621 new_confline(&ctmp);
1622 ctmp->var = &srch_rule_var;
1623 ctmp->keymenu = &config_radiobutton_keymenu;
1624 ctmp->help = NO_HELP;
1625 ctmp->tool = NULL;
1626 snprintf(tmp, sizeof(tmp), "%s =", srch_rule_var.name);
1627 tmp[sizeof(tmp)-1] = '\0';
1628 ctmp->varname = cpystr(tmp);
1629 ctmp->varnamep = ctmpb = ctmp;
1630 ctmp->flags |= (CF_NOSELECT | CF_STARTITEM);
1632 /* Search Rule */
1633 new_confline(&ctmp);
1634 ctmp->var = NULL;
1635 ctmp->valoffset = rindent;
1636 ctmp->keymenu = &config_radiobutton_keymenu;
1637 ctmp->help = NO_HELP;
1638 ctmp->tool = NULL;
1639 ctmp->varnamep = ctmpb;
1640 ctmp->flags |= CF_NOSELECT;
1641 ctmp->value = cpystr("Set Rule Values");
1643 new_confline(&ctmp);
1644 ctmp->var = NULL;
1645 ctmp->valoffset = rindent;
1646 ctmp->keymenu = &config_radiobutton_keymenu;
1647 ctmp->help = NO_HELP;
1648 ctmp->tool = ldap_radiobutton_tool;
1649 ctmp->varnamep = ctmpb;
1650 ctmp->flags |= CF_NOSELECT;
1651 ctmp->value = cpystr(set_choose);
1653 /* find longest value's name */
1654 for(lv = 0, i = 0; (f = ldap_search_rules(i)); i++)
1655 if(lv < (j = utf8_width(f->name)))
1656 lv = j;
1658 lv = MIN(lv, 100);
1660 for(i = 0; (f = ldap_search_rules(i)); i++){
1661 new_confline(&ctmp);
1662 ctmp->help_title= _("HELP FOR SEARCH RULE");
1663 ctmp->var = &srch_rule_var;
1664 ctmp->valoffset = rindent;
1665 ctmp->keymenu = &config_radiobutton_keymenu;
1666 ctmp->help = h_config_ldap_searchrules;
1667 ctmp->varmem = i;
1668 ctmp->tool = ldap_radiobutton_tool;
1669 ctmp->varnamep = ctmpb;
1670 utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!def || def->srch == -1) &&
1671 f->value == DEF_LDAP_SRCH) ||
1672 (def && f->value == def->srch))
1673 ? R_SELD : ' ',
1674 lv, lv, f->name);
1675 tmp[sizeof(tmp)-1] = '\0';
1676 ctmp->value = cpystr(tmp);
1679 /* Blank line */
1680 new_confline(&ctmp);
1681 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1682 ctmp->varname = cpystr("");
1684 /* Email attribute name */
1685 new_confline(&ctmp);
1686 ctmp->help_title= _("HELP FOR EMAIL ATTRIBUTE NAME");
1687 ctmp->var = &mailattr_var;
1688 ctmp->valoffset = indent;
1689 ctmp->keymenu = &config_text_keymenu;
1690 ctmp->help = h_config_ldap_email_attr;
1691 ctmp->tool = dir_edit_tool;
1692 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,mailattr_var.name);
1693 tmp[sizeof(tmp)-1] = '\0';
1694 ctmp->varname = cpystr(tmp);
1695 ctmp->varnamep = ctmp;
1696 ctmp->value = pretty_value(ps, ctmp);
1698 /* Name attribute name */
1699 new_confline(&ctmp);
1700 ctmp->help_title= _("HELP FOR NAME ATTRIBUTE NAME");
1701 ctmp->var = &cnattr_var;
1702 ctmp->valoffset = indent;
1703 ctmp->keymenu = &config_text_keymenu;
1704 ctmp->help = h_config_ldap_cn_attr;
1705 ctmp->tool = dir_edit_tool;
1706 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,cnattr_var.name);
1707 tmp[sizeof(tmp)-1] = '\0';
1708 ctmp->varname = cpystr(tmp);
1709 ctmp->varnamep = ctmp;
1710 ctmp->value = pretty_value(ps, ctmp);
1712 /* Surname attribute name */
1713 new_confline(&ctmp);
1714 ctmp->help_title= _("HELP FOR SURNAME ATTRIBUTE NAME");
1715 ctmp->var = &snattr_var;
1716 ctmp->valoffset = indent;
1717 ctmp->keymenu = &config_text_keymenu;
1718 ctmp->help = h_config_ldap_sn_attr;
1719 ctmp->tool = dir_edit_tool;
1720 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,snattr_var.name);
1721 tmp[sizeof(tmp)-1] = '\0';
1722 ctmp->varname = cpystr(tmp);
1723 ctmp->varnamep = ctmp;
1724 ctmp->value = pretty_value(ps, ctmp);
1726 /* Givenname attribute name */
1727 new_confline(&ctmp);
1728 ctmp->help_title= _("HELP FOR GIVEN NAME ATTRIBUTE NAME");
1729 ctmp->var = &gnattr_var;
1730 ctmp->valoffset = indent;
1731 ctmp->keymenu = &config_text_keymenu;
1732 ctmp->help = h_config_ldap_gn_attr;
1733 ctmp->tool = dir_edit_tool;
1734 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,gnattr_var.name);
1735 tmp[sizeof(tmp)-1] = '\0';
1736 ctmp->varname = cpystr(tmp);
1737 ctmp->varnamep = ctmp;
1738 ctmp->value = pretty_value(ps, ctmp);
1740 /* Blank line */
1741 new_confline(&ctmp);
1742 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1743 ctmp->varname = cpystr("");
1745 /* Time limit */
1746 new_confline(&ctmp);
1747 ctmp->help_title= _("HELP FOR SERVER TIMELIMIT");
1748 ctmp->var = &time_var;
1749 ctmp->valoffset = indent;
1750 ctmp->keymenu = &config_text_keymenu;
1751 ctmp->help = h_config_ldap_time;
1752 ctmp->tool = dir_edit_tool;
1753 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,time_var.name);
1754 tmp[sizeof(tmp)-1] = '\0';
1755 ctmp->varname = cpystr(tmp);
1756 ctmp->varnamep = ctmp;
1757 ctmp->value = pretty_value(ps, ctmp);
1758 ctmp->flags |= CF_NUMBER;
1760 /* Size limit */
1761 new_confline(&ctmp);
1762 ctmp->var = &size_var;
1763 ctmp->help_title= _("HELP FOR SERVER SIZELIMIT");
1764 ctmp->valoffset = indent;
1765 ctmp->keymenu = &config_text_keymenu;
1766 ctmp->help = h_config_ldap_size;
1767 ctmp->tool = dir_edit_tool;
1768 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,size_var.name);
1769 tmp[sizeof(tmp)-1] = '\0';
1770 ctmp->varname = cpystr(tmp);
1771 ctmp->varnamep = ctmp;
1772 ctmp->value = pretty_value(ps, ctmp);
1773 ctmp->flags |= CF_NUMBER;
1775 /* Blank line */
1776 new_confline(&ctmp);
1777 ctmp->flags |= CF_NOSELECT | CF_B_LINE;
1779 /* Custom Search Filter */
1780 new_confline(&ctmp);
1781 ctmp->help_title= _("HELP FOR CUSTOM SEARCH FILTER");
1782 ctmp->var = &cust_var;
1783 ctmp->valoffset = indent;
1784 ctmp->keymenu = &config_text_keymenu;
1785 ctmp->help = h_config_ldap_cust;
1786 ctmp->tool = dir_edit_tool;
1787 utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,cust_var.name);
1788 tmp[sizeof(tmp)-1] = '\0';
1789 ctmp->varname = cpystr(tmp);
1790 ctmp->varnamep = ctmp;
1791 ctmp->value = pretty_value(ps, ctmp);
1794 snprintf(tmp, sizeof(tmp), "%s DIRECTORY SERVER", title);
1795 tmp[sizeof(tmp)-1] = '\0';
1796 memset(&screen, 0, sizeof(screen));
1797 screen.ro_warning = saved_screen ? saved_screen->deferred_ro_warning : 0;
1798 /* TRANSLATORS: Print something1 using something2.
1799 servers is something1 */
1800 rv = conf_scroll_screen(ps, &screen, first_line, tmp, _("servers"), 0, NULL);
1803 * Now look at the fake variables and extract the information we
1804 * want from them.
1807 if(rv == 1 && raw_server){
1808 char dir_tmp[2200], *p;
1809 int portval = -1, timeval = -1, sizeval = -1;
1811 apval = APVAL(&server_var, ew);
1812 server = *apval;
1813 *apval = NULL;
1815 apval = APVAL(&base_var, ew);
1816 base = *apval;
1817 *apval = NULL;
1819 apval = APVAL(&port_var, ew);
1820 port = *apval;
1821 *apval = NULL;
1823 apval = APVAL(&binddn_var, ew);
1824 binddn = *apval;
1825 *apval = NULL;
1827 apval = APVAL(&nick_var, ew);
1828 nick = *apval;
1829 *apval = NULL;
1831 apval = APVAL(&srch_type_var, ew);
1832 srch_type = *apval;
1833 *apval = NULL;
1835 apval = APVAL(&srch_rule_var, ew);
1836 srch_rule = *apval;
1837 *apval = NULL;
1839 apval = APVAL(&time_var, ew);
1840 ttime = *apval;
1841 *apval = NULL;
1843 apval = APVAL(&size_var, ew);
1844 ssize = *apval;
1845 *apval = NULL;
1847 apval = APVAL(&cust_var, ew);
1848 cust = *apval;
1849 *apval = NULL;
1851 apval = APVAL(&mailattr_var, ew);
1852 mailattr = *apval;
1853 *apval = NULL;
1855 apval = APVAL(&snattr_var, ew);
1856 snattr = *apval;
1857 *apval = NULL;
1859 apval = APVAL(&gnattr_var, ew);
1860 gnattr = *apval;
1861 *apval = NULL;
1863 apval = APVAL(&cnattr_var, ew);
1864 cnattr = *apval;
1865 *apval = NULL;
1867 if(server)
1868 removing_leading_and_trailing_white_space(server);
1870 if(base){
1871 removing_leading_and_trailing_white_space(base);
1872 (void)removing_double_quotes(base);
1873 p = add_backslash_escapes(base);
1874 fs_give((void **)&base);
1875 base = p;
1878 if(port){
1879 removing_leading_and_trailing_white_space(port);
1880 if(*port)
1881 portval = atoi(port);
1884 if(binddn){
1885 removing_leading_and_trailing_white_space(binddn);
1886 (void)removing_double_quotes(binddn);
1887 p = add_backslash_escapes(binddn);
1888 fs_give((void **)&binddn);
1889 binddn = p;
1892 if(nick){
1893 removing_leading_and_trailing_white_space(nick);
1894 (void)removing_double_quotes(nick);
1895 p = add_backslash_escapes(nick);
1896 fs_give((void **)&nick);
1897 nick = p;
1900 if(ttime){
1901 removing_leading_and_trailing_white_space(ttime);
1902 if(*ttime)
1903 timeval = atoi(ttime);
1906 if(ssize){
1907 removing_leading_and_trailing_white_space(ssize);
1908 if(*ssize)
1909 sizeval = atoi(ssize);
1912 if(cust){
1913 removing_leading_and_trailing_white_space(cust);
1914 p = add_backslash_escapes(cust);
1915 fs_give((void **)&cust);
1916 cust = p;
1919 if(mailattr){
1920 removing_leading_and_trailing_white_space(mailattr);
1921 p = add_backslash_escapes(mailattr);
1922 fs_give((void **)&mailattr);
1923 mailattr = p;
1926 if(snattr){
1927 removing_leading_and_trailing_white_space(snattr);
1928 p = add_backslash_escapes(snattr);
1929 fs_give((void **)&snattr);
1930 snattr = p;
1933 if(gnattr){
1934 removing_leading_and_trailing_white_space(gnattr);
1935 p = add_backslash_escapes(gnattr);
1936 fs_give((void **)&gnattr);
1937 gnattr = p;
1940 if(cnattr){
1941 removing_leading_and_trailing_white_space(cnattr);
1942 p = add_backslash_escapes(cnattr);
1943 fs_give((void **)&cnattr);
1944 cnattr = p;
1948 * Don't allow user to edit scope but if one is present then we
1949 * leave it (so they could edit it by hand).
1951 if(def && def->scope != -1 && def->scope != DEF_LDAP_SCOPE){
1952 NAMEVAL_S *v;
1954 v = ldap_search_scope(def->scope);
1955 if(v){
1956 snprintf(custom_scope, sizeof(custom_scope), "/scope=%s", v->name);
1957 custom_scope[sizeof(custom_scope)-1] = '\0';
1961 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\"",
1962 server ? server : "",
1963 (portval >= 0 && port && *port) ? ":" : "",
1964 (portval >= 0 && port && *port) ? port : "",
1965 base ? base : "",
1966 binddn ? binddn : "",
1967 bitnset(LDAP_F_IMPL, ldap_option_list) ? 1 : 0,
1968 bitnset(LDAP_F_RHS, ldap_option_list) ? 1 : 0,
1969 bitnset(LDAP_F_REF, ldap_option_list) ? 1 : 0,
1970 bitnset(LDAP_F_NOSUB, ldap_option_list) ? 1 : 0,
1971 bitnset(LDAP_F_TLS, ldap_option_list) ? 1 : 0,
1972 bitnset(LDAP_F_TLSMUST, ldap_option_list) ? 1 : 0,
1973 bitnset(LDAP_F_LDAPS, ldap_option_list) ? 1 : 0,
1974 srch_type ? srch_type : "",
1975 srch_rule ? srch_rule : "",
1976 custom_scope,
1977 (timeval >= 0 && ttime && *ttime) ? ttime : "",
1978 (sizeval >= 0 && ssize && *ssize) ? ssize : "",
1979 cust ? cust : "",
1980 nick ? nick : "",
1981 mailattr ? mailattr : "",
1982 cnattr ? cnattr : "",
1983 snattr ? snattr : "",
1984 gnattr ? gnattr : "");
1985 dir_tmp[sizeof(dir_tmp)-1] = '\0';
1987 *raw_server = cpystr(dir_tmp);
1990 for(j = 0; varlist[j]; j++){
1991 v = varlist[j];
1992 if(v->current_val.p)
1993 fs_give((void **)&v->current_val.p);
1994 if(v->global_val.p)
1995 fs_give((void **)&v->global_val.p);
1996 if(v->main_user_val.p)
1997 fs_give((void **)&v->main_user_val.p);
1998 if(v->post_user_val.p)
1999 fs_give((void **)&v->post_user_val.p);
2000 if(v->name)
2001 fs_give((void **)&v->name);
2004 if(server)
2005 fs_give((void **)&server);
2006 if(base)
2007 fs_give((void **)&base);
2008 if(port)
2009 fs_give((void **)&port);
2010 if(binddn)
2011 fs_give((void **)&binddn);
2012 if(nick)
2013 fs_give((void **)&nick);
2014 if(srch_type)
2015 fs_give((void **)&srch_type);
2016 if(srch_rule)
2017 fs_give((void **)&srch_rule);
2018 if(ttime)
2019 fs_give((void **)&ttime);
2020 if(ssize)
2021 fs_give((void **)&ssize);
2022 if(mailattr)
2023 fs_give((void **)&mailattr);
2024 if(cnattr)
2025 fs_give((void **)&cnattr);
2026 if(snattr)
2027 fs_give((void **)&snattr);
2028 if(gnattr)
2029 fs_give((void **)&gnattr);
2030 if(cust)
2031 fs_give((void **)&cust);
2033 opt_screen = saved_screen;
2034 ps->mangled_screen = 1;
2035 return(rv);
2040 * Just calls text_tool except for intercepting MC_EXIT.
2043 dir_edit_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
2045 if(cmd == MC_EXIT)
2046 return(config_exit_cmd(flags));
2047 else
2048 return(text_tool(ps, cmd, cl, flags));
2053 * Delete LDAP directory entry
2055 void
2056 dir_config_del(struct pine *ps, CONF_S **cl)
2058 char prompt[81];
2059 int rv = 0, i;
2061 if(fixed_var((*cl)->var, NULL, NULL)){
2062 if((*cl)->var->post_user_val.l || (*cl)->var->main_user_val.l){
2063 if(want_to(_("Delete (unused) directory servers "),
2064 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){
2065 rv = 1;
2066 delete_user_vals((*cl)->var);
2069 else
2070 q_status_message(SM_ORDER, 3, 3,
2071 _("Can't delete sys-admin defined value"));
2073 else{
2074 int cnt, ans = 0, no_ex;
2075 char **new_list, **lval, **nelval;
2077 no_ex = (ps_global->ew_for_except_vars == Main);
2079 /* This can't happen, intercepted at caller by first_one case */
2080 nelval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
2081 lval = LVAL((*cl)->var, ew);
2082 if(lval && lval[0] && lval[0][0] == '\0')
2083 ans = 'r';
2085 /* how many servers defined? */
2086 for(cnt = 0; nelval[cnt]; cnt++)
2090 * If using default and there is more than one in list, ask if user
2091 * wants to ignore them all or delete just this one. If just this
2092 * one, copy rest to user_val. If ignore all, copy "" to user_val
2093 * to override.
2095 if(!lval && cnt > 1){
2096 static ESCKEY_S opts[] = {
2097 {'i', 'i', "I", N_("Ignore All")},
2098 {'r', 'r', "R", N_("Remove One")},
2099 {-1, 0, NULL, NULL}};
2100 ans = radio_buttons(
2101 _("Ignore all default directory servers or just remove this one ? "),
2102 -FOOTER_ROWS(ps), opts, 'i', 'x',
2103 h_ab_del_dir_ignore, RB_NORM);
2106 if(ans == 0){
2107 snprintf(prompt, sizeof(prompt), _("Really delete %s \"%s\" from directory servers "),
2108 ((*cl)->value && *(*cl)->value)
2109 ? "server"
2110 : "item",
2111 ((*cl)->value && *(*cl)->value)
2112 ? (*cl)->value
2113 : int2string((*cl)->varmem + 1));
2114 prompt[sizeof(prompt)-1] = '\0';
2118 ps->mangled_footer = 1;
2119 if(ans == 'i'){
2120 rv = ps->mangled_body = 1;
2123 * Ignore all of default by adding an empty string. Make it
2124 * look just like there are no servers defined.
2127 new_list = (char **)fs_get((1 + 1) * sizeof(char *));
2128 new_list[0] = cpystr("");
2129 new_list[1] = NULL;
2130 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
2131 free_list_array(&new_list);
2132 *cl = first_confline(*cl);
2133 free_conflines(cl);
2134 opt_screen->top_line = NULL;
2136 add_ldap_fake_first_server(ps, cl, &ps->vars[V_LDAP_SERVERS],
2137 &dir_conf_km, h_direct_config,
2138 dir_config_tool);
2140 else if(ans == 'r' ||
2141 (ans != 'x' &&
2142 want_to(prompt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y')){
2143 CONF_S *cp;
2144 char **servers;
2145 int move_top = 0, this_one, revert_to_default,
2146 default_there_to_revert_to;
2149 * Remove one from current list.
2152 rv = ps->mangled_body = 1;
2154 this_one = (*cl)->varmem;
2156 /* might have to re-adjust screen to see new current */
2157 move_top = (this_one > 0) &&
2158 (this_one == cnt - 1) &&
2159 (((*cl) == opt_screen->top_line) ||
2160 ((*cl)->prev == opt_screen->top_line) ||
2161 ((*cl)->prev->prev == opt_screen->top_line));
2164 * If this is last one and there is a default available, revert
2165 * to it.
2167 revert_to_default = ((cnt == 1) && lval);
2168 if(cnt > 1){
2169 new_list = (char **)fs_get((cnt + 1) * sizeof(char *));
2170 for(i = 0; i < this_one; i++)
2171 new_list[i] = cpystr(nelval[i]);
2173 for(i = this_one; i < cnt; i++)
2174 new_list[i] = cpystr(nelval[i+1]);
2176 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
2177 free_list_array(&new_list);
2179 else if(revert_to_default){
2180 char ***alval;
2182 alval = ALVAL((*cl)->var, ew);
2183 if(alval && *alval)
2184 free_list_array(alval);
2186 else{
2187 /* cnt is one and we want to hide default */
2188 new_list = (char **)fs_get((1 + 1) * sizeof(char *));
2189 new_list[0] = cpystr("");
2190 new_list[1] = NULL;
2191 set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew);
2192 free_list_array(&new_list);
2195 if(cnt == 1){ /* delete display line for this_one */
2196 if(revert_to_default){
2197 servers = (*cl)->var->global_val.l;
2198 default_there_to_revert_to = (servers != NULL);
2201 *cl = first_confline(*cl);
2202 free_conflines(cl);
2203 opt_screen->top_line = NULL;
2204 if(revert_to_default && default_there_to_revert_to){
2205 CONF_S *first_line = NULL;
2207 q_status_message(SM_ORDER, 0, 3,
2208 _("Reverting to default directory server"));
2209 dir_init_display(ps, cl, servers,
2210 &ps->vars[V_LDAP_SERVERS], &first_line);
2211 *cl = first_line;
2213 else{
2214 add_ldap_fake_first_server(ps, cl,
2215 &ps->vars[V_LDAP_SERVERS],
2216 &dir_conf_km, h_direct_config,
2217 dir_config_tool);
2220 else if(this_one == cnt - 1){ /* deleted last one */
2221 /* back up and delete it */
2222 *cl = (*cl)->prev;
2223 free_conflines(&(*cl)->next);
2224 /* now back up to first line of this server */
2225 *cl = (*cl)->prev->prev;
2226 if(move_top)
2227 opt_screen->top_line = *cl;
2229 else{ /* deleted one out of the middle */
2230 if(*cl == opt_screen->top_line)
2231 opt_screen->top_line = (*cl)->next->next->next;
2233 cp = *cl;
2234 *cl = (*cl)->next; /* move to next line, then */
2235 snip_confline(&cp); /* snip 1st deleted line */
2236 cp = *cl;
2237 *cl = (*cl)->next; /* move to next line, then */
2238 snip_confline(&cp); /* snip 2nd deleted line */
2239 cp = *cl;
2240 *cl = (*cl)->next; /* move to next line, then */
2241 snip_confline(&cp); /* snip 3rd deleted line */
2242 /* adjust varmems */
2243 for(cp = *cl; cp; cp = cp->next)
2244 cp->varmem--;
2247 else
2248 q_status_message(SM_ORDER, 0, 3, _("Server not deleted"));
2251 if(rv == 1){
2252 set_current_val((*cl)->var, TRUE, FALSE);
2253 fix_side_effects(ps, (*cl)->var, 0);
2254 write_pinerc(ps, ew, WRP_NONE);
2260 * Utility routine to help set up display
2262 void
2263 add_ldap_fake_first_server(struct pine *ps, CONF_S **ctmp, struct variable *var,
2264 struct key_menu *km, HelpType help,
2265 int (*tool)(struct pine *, int, CONF_S **, unsigned))
2267 new_confline(ctmp);
2268 (*ctmp)->help_title= _("HELP FOR DIRECTORY SERVER CONFIGURATION");
2269 (*ctmp)->value = cpystr(ADD_FIRST_LDAP_SERVER);
2270 (*ctmp)->var = var;
2271 (*ctmp)->varmem = 0;
2272 (*ctmp)->keymenu = km;
2273 (*ctmp)->help = help;
2274 (*ctmp)->tool = tool;
2275 (*ctmp)->valoffset = 2;
2280 * Add an ldap server to the display list.
2282 * Args before -- Insert it before current, else append it after.
2284 void
2285 add_ldap_server_to_display(struct pine *ps, CONF_S **ctmp, char *serv, char *subtitle,
2286 struct variable *var, int member, struct key_menu *km,
2287 HelpType help,
2288 int (*tool)(struct pine *, int, CONF_S **, unsigned),
2289 int before, CONF_S **first_line)
2291 new_confline(ctmp);
2292 if(first_line)
2293 *first_line = *ctmp;
2295 if(before){
2297 * New_confline appends ctmp after old current instead of inserting
2298 * it, so we have to adjust. We have
2299 * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c ->
2302 CONF_S *a, *b, *c, *p;
2304 p = *ctmp;
2305 b = (*ctmp)->prev;
2306 c = (*ctmp)->next;
2307 a = b ? b->prev : NULL;
2308 if(a)
2309 a->next = p;
2311 if(b){
2312 b->prev = p;
2313 b->next = c;
2316 if(c)
2317 c->prev = b;
2319 p->prev = a;
2320 p->next = b;
2323 (*ctmp)->help_title= _("HELP FOR DIRECTORY SERVER CONFIGURATION");
2324 (*ctmp)->value = serv;
2325 (*ctmp)->var = var;
2326 (*ctmp)->varmem = member;
2327 (*ctmp)->keymenu = km;
2328 (*ctmp)->help = help;
2329 (*ctmp)->tool = tool;
2330 (*ctmp)->flags |= CF_STARTITEM;
2331 (*ctmp)->valoffset = 4;
2333 new_confline(ctmp);
2334 (*ctmp)->value = subtitle;
2335 (*ctmp)->keymenu = km;
2336 (*ctmp)->help = help;
2337 (*ctmp)->tool = tool;
2338 (*ctmp)->flags |= CF_NOSELECT;
2339 (*ctmp)->valoffset = 8;
2341 new_confline(ctmp);
2342 (*ctmp)->keymenu = km;
2343 (*ctmp)->help = help;
2344 (*ctmp)->tool = tool;
2345 (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
2346 (*ctmp)->valoffset = 0;
2351 * ldap option list manipulation tool
2354 * returns: -1 on unrecognized cmd, 0 if no change, 1 if change
2357 ldap_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
2359 int rv = 0;
2361 switch(cmd){
2362 case MC_TOGGLE: /* mark/unmark option */
2363 rv = 1;
2364 toggle_ldap_option_bit(ps, (*cl)->varmem, (*cl)->var, (*cl)->value);
2365 break;
2367 case MC_EXIT: /* exit */
2368 rv = config_exit_cmd(flags);
2369 break;
2371 default :
2372 rv = -1;
2373 break;
2376 return(rv);
2380 void
2381 toggle_ldap_option_bit(struct pine *ps, int index, struct variable *var, char *value)
2383 NAMEVAL_S *f;
2384 int tls_is_on_now;
2385 int tlsmust_is_on_now;
2386 int ldaps_is_on_now;
2387 int tls_is_on_after;
2388 int tlsmust_is_on_after;
2389 int ldaps_is_on_after;
2391 tls_is_on_now = (f = ldap_feature_list(LDAP_F_TLS)) != NULL
2392 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2394 tlsmust_is_on_now = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
2395 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2397 ldaps_is_on_now = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
2398 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2400 f = ldap_feature_list(index);
2402 /* flip the bit */
2403 if(bitnset(f->value, ldap_option_list))
2404 clrbitn(f->value, ldap_option_list);
2405 else
2406 setbitn(f->value, ldap_option_list);
2408 tls_is_on_after = (f = ldap_feature_list(LDAP_F_TLS)) != NULL
2409 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2411 tlsmust_is_on_after = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
2412 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2414 ldaps_is_on_after = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
2415 && bitnset(f->value, ldap_option_list) ? 1 : 0;
2417 f = ldap_feature_list(index);
2419 if(!ldaps_is_on_now && ldaps_is_on_after){
2420 if(tlsmust_is_on_after || tls_is_on_after){
2421 char *name;
2422 if(tlsmust_is_on_after)
2423 name = ldap_feature_list(LDAP_F_TLSMUST)->name;
2424 else
2425 name = ldap_feature_list(LDAP_F_TLS)->name;
2426 clrbitn(f->value, ldap_option_list);
2427 q_status_message1(SM_ORDER, 3, 3,
2428 _("Can not use LDAPS when using TLS. Disable \"%s\" first."), name);
2431 else if(!tls_is_on_now && tls_is_on_after){
2432 if(ldaps_is_on_after){
2433 char *name = ldap_feature_list(LDAP_F_LDAPS)->name;
2434 clrbitn(f->value, ldap_option_list);
2435 q_status_message1(SM_ORDER, 3, 3,
2436 _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name);
2439 else if(!tlsmust_is_on_now && tlsmust_is_on_after){
2440 if(ldaps_is_on_after){
2441 char *name = ldap_feature_list(LDAP_F_LDAPS)->name;
2442 clrbitn(f->value, ldap_option_list);
2443 q_status_message1(SM_ORDER, 3, 3,
2444 _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name);
2448 if(value)
2449 value[1] = bitnset(f->value, ldap_option_list) ? 'X' : ' ';
2453 NAMEVAL_S *
2454 ldap_feature_list(int index)
2456 static NAMEVAL_S ldap_feat_list[] = {
2457 {"use-implicitly-from-composer", NULL, LDAP_F_IMPL},
2458 {"lookup-addrbook-contents", NULL, LDAP_F_RHS},
2459 {"save-search-criteria-not-result", NULL, LDAP_F_REF},
2460 {"disable-ad-hoc-space-substitution", NULL, LDAP_F_NOSUB},
2461 {"attempt-tls-on-connection", NULL, LDAP_F_TLS},
2462 {"require-tls-on-connection", NULL, LDAP_F_TLSMUST},
2463 {"require-ldaps-on-connection", NULL, LDAP_F_LDAPS}
2466 return((index >= 0 &&
2467 index < (sizeof(ldap_feat_list)/sizeof(ldap_feat_list[0])))
2468 ? &ldap_feat_list[index] : NULL);
2473 * simple radio-button style variable handler
2476 ldap_radiobutton_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
2478 int rv = 0;
2479 CONF_S *ctmp;
2480 NAMEVAL_S *rule;
2481 char **apval;
2483 switch(cmd){
2484 case MC_CHOICE : /* set/unset feature */
2486 /* hunt backwards, turning off old values */
2487 for(ctmp = *cl; ctmp && !(ctmp->flags & CF_NOSELECT) && !ctmp->varname;
2488 ctmp = prev_confline(ctmp))
2489 ctmp->value[1] = ' ';
2491 /* hunt forwards, turning off old values */
2492 for(ctmp = *cl; ctmp && !(ctmp->flags & CF_NOSELECT) && !ctmp->varname;
2493 ctmp = next_confline(ctmp))
2494 ctmp->value[1] = ' ';
2496 /* turn on current value */
2497 (*cl)->value[1] = R_SELD;
2499 if((*cl)->var == ldap_srch_rule_ptr)
2500 rule = ldap_search_rules((*cl)->varmem);
2501 else
2502 rule = ldap_search_types((*cl)->varmem);
2504 apval = APVAL((*cl)->var, ew);
2505 if(apval && *apval)
2506 fs_give((void **)apval);
2508 if(apval)
2509 *apval = cpystr(rule->name);
2511 ps->mangled_body = 1; /* BUG: redraw it all for now? */
2512 rv = 1;
2514 break;
2516 case MC_EXIT: /* exit */
2517 rv = config_exit_cmd(flags);
2518 break;
2520 default :
2521 rv = -1;
2522 break;
2525 return(rv);
2528 #endif /* ENABLE_LDAP */