#if !defined(lint) && !defined(DOS) static char rcsid[] = "$Id: ldapconf.c 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $"; #endif /* * ======================================================================== * Copyright 2013-2021 Eduardo Chappa * Copyright 2006-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * ======================================================================== */ #include "headers.h" #include "ldapconf.h" #include "keymenu.h" #include "radio.h" #include "status.h" #include "confscroll.h" #include "adrbkcmd.h" #include "titlebar.h" #include "takeaddr.h" #include "../pith/ldap.h" #include "../pith/state.h" #include "../pith/bitmap.h" #include "../pith/mailcmd.h" #include "../pith/list.h" /* * Internal prototypes */ #ifdef ENABLE_LDAP int addr_select_tool(struct pine *, int, CONF_S **, unsigned); void dir_init_display(struct pine *, CONF_S **, char **, struct variable *, CONF_S **); int dir_config_tool(struct pine *, int, CONF_S **, unsigned); void dir_config_add(struct pine *, CONF_S **); void dir_config_shuffle(struct pine *, CONF_S **); void dir_config_edit(struct pine *, CONF_S **); int dir_edit_screen(struct pine *, LDAP_SERV_S *, char *, char **); int dir_edit_tool(struct pine *, int, CONF_S **, unsigned); void dir_config_del(struct pine *, CONF_S **); void add_ldap_fake_first_server(struct pine *, CONF_S **, struct variable *, struct key_menu *, HelpType, int (*)(struct pine *, int, CONF_S **, unsigned)); void add_ldap_server_to_display(struct pine *, CONF_S **, char *, char *, struct variable *, int, struct key_menu *, HelpType, int (*)(struct pine *, int, CONF_S **, unsigned), int, CONF_S **); int ldap_checkbox_tool(struct pine *, int, CONF_S **, unsigned); void toggle_ldap_option_bit(struct pine *, int, struct variable *, char *); NAMEVAL_S *ldap_feature_list(int); static char *srch_res_help_title = N_("HELP FOR SEARCH RESULTS INDEX"); static char *set_choose = "--- ----------------------"; #define ADD_FIRST_LDAP_SERVER _("Use Add to add a directory server") #define ADDR_SELECT_EXIT_VAL 5 #define ADDR_SELECT_GOBACK_VAL 6 #define ADDR_SELECT_FORCED_EXIT_VAL 7 static int some_selectable; static char *dserv = N_("Directory Server on "); /* * Let user choose an ldap entry (or return an entry if user doesn't need * to be consulted). * * Returns 0 if ok, * -1 if Exit was chosen * -2 if none were selectable * -3 if no entries existed at all * -4 go back to Abook List was chosen * -5 caller shouldn't free ac->res_head * * When 0 is returned the winner is pointed to by result. * Result is an allocated LDAP_SEARCH_WINNER_S which has pointers * to the ld and entry that were chosen. Those are pointers into * the initial data, not copies. The two-pointer structure is * allocated here and freed by the caller. */ int ldap_addr_select(struct pine *ps, ADDR_CHOOSE_S *ac, LDAP_CHOOSE_S **result, LDAPLookupStyle style, WP_ERR_S *wp_err, char *srchstr) { LDAPMessage *e; LDAP_SERV_RES_S *res_list; CONF_S *ctmpa = NULL, *first_line = NULL, *alt_first_line = NULL; int i, retval = 0, got_n_mail = 0, got_n_entries = 0; int need_mail; OPT_SCREEN_S screen; struct key_menu *km; char ee[200]; HelpType help; void (*prev_redrawer) (void); dprint((4, "ldap_addr_select()\n")); need_mail = (style == AlwaysDisplay || style == DisplayForURL) ? 0 : 1; if(style == AlwaysDisplay){ km = &addr_s_km_with_view; help = h_address_display; } else if(style == AlwaysDisplayAndMailRequired){ km = &addr_s_km_with_goback; help = h_address_select; } else if(style == DisplayForURL){ km = &addr_s_km_for_url; help = h_address_display; } else{ km = &addr_s_km; help = h_address_select; } if(result) *result = NULL; some_selectable = 0; for(res_list = ac->res_head; res_list; res_list = res_list->next){ for(e = ldap_first_entry(res_list->ld, res_list->res); e != NULL; e = ldap_next_entry(res_list->ld, e)){ char *dn, *a; struct berval **cn, **org, **unit, **title, **mail, **sn; BerElement *ber; int indent, have_mail; dn = NULL; cn = org = title = unit = mail = sn = NULL; for(a = ldap_first_attribute(res_list->ld, e, &ber); a != NULL; a = ldap_next_attribute(res_list->ld, e, ber)){ dprint((9, " %s", a ? a : "?")); if(strcmp(a, res_list->info_used->cnattr) == 0){ if(!cn) cn = ldap_get_values_len(res_list->ld, e, a); if(cn && !ALPINE_LDAP_can_use(cn)){ ldap_value_free_len(cn); cn = NULL; } } else if(strcmp(a, res_list->info_used->mailattr) == 0){ if(!mail) mail = ldap_get_values_len(res_list->ld, e, a); } else if(strcmp(a, "o") == 0){ if(!org) org = ldap_get_values_len(res_list->ld, e, a); } else if(strcmp(a, "ou") == 0){ if(!unit) unit = ldap_get_values_len(res_list->ld, e, a); } else if(strcmp(a, "title") == 0){ if(!title) title = ldap_get_values_len(res_list->ld, e, a); } our_ldap_memfree(a); } dprint((9, "\n")); if(!cn){ for(a = ldap_first_attribute(res_list->ld, e, &ber); a != NULL; a = ldap_next_attribute(res_list->ld, e, ber)){ if(strcmp(a, res_list->info_used->snattr) == 0){ if(!sn) sn = ldap_get_values_len(res_list->ld, e, a); if(sn && !ALPINE_LDAP_can_use(sn)){ ldap_value_free_len(sn); sn = NULL; } } our_ldap_memfree(a); } } if(ALPINE_LDAP_can_use(mail)) have_mail = 1; else have_mail = 0; got_n_mail += have_mail; got_n_entries++; indent = 2; /* * First line is either cn, sn, or dn. */ if(cn){ new_confline(&ctmpa); if(!alt_first_line) alt_first_line = ctmpa; ctmpa->flags |= CF_STARTITEM; if(need_mail && !have_mail) ctmpa->flags |= CF_PRIVATE; ctmpa->value = cpystr(cn[0]->bv_val); ldap_value_free_len(cn); ctmpa->valoffset = indent; ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; if(!first_line && (have_mail || !need_mail)) first_line = ctmpa; } /* only happens if no cn */ if(sn){ new_confline(&ctmpa); if(!alt_first_line) alt_first_line = ctmpa; ctmpa->flags |= CF_STARTITEM; if(need_mail && !have_mail) ctmpa->flags |= CF_PRIVATE; ctmpa->value = cpystr(sn[0]->bv_val); ldap_value_free_len(sn); ctmpa->valoffset = indent; ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; if(!first_line && (have_mail || !need_mail)) first_line = ctmpa; } if(!sn && !cn){ new_confline(&ctmpa); if(!alt_first_line) alt_first_line = ctmpa; ctmpa->flags |= CF_STARTITEM; if(need_mail && !have_mail) ctmpa->flags |= CF_PRIVATE; dn = ldap_get_dn(res_list->ld, e); if(dn && !dn[0]){ our_ldap_dn_memfree(dn); dn = NULL; } ctmpa->value = cpystr(dn ? dn : "?"); if(dn) our_ldap_dn_memfree(dn); ctmpa->valoffset = indent; ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; if(!first_line && (have_mail || !need_mail)) first_line = ctmpa; } if(title){ for(i = 0; ALPINE_LDAP_usable(title, i); i++){ new_confline(&ctmpa); ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = indent + 2; ctmpa->value = cpystr(title[i]->bv_val); ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; } ldap_value_free_len(title); } if(unit){ for(i = 0; ALPINE_LDAP_usable(unit, i); i++){ new_confline(&ctmpa); ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = indent + 2; ctmpa->value = cpystr(unit[i]->bv_val); ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; } ldap_value_free_len(unit); } if(org){ for(i = 0; ALPINE_LDAP_usable(org, i); i++){ new_confline(&ctmpa); ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = indent + 2; ctmpa->value = cpystr(org[i]->bv_val); ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; } ldap_value_free_len(org); } if(have_mail){ /* Don't show long list of email addresses. */ if(!ALPINE_LDAP_can_use_num(mail, 0) || !ALPINE_LDAP_can_use_num(mail, 1) || !ALPINE_LDAP_can_use_num(mail, 2) || !ALPINE_LDAP_can_use_num(mail, 3)){ for(i = 0; ALPINE_LDAP_usable(mail, i); i++){ new_confline(&ctmpa); ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = indent + 2; ctmpa->value = cpystr(mail[i]->bv_val); ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; } } else{ char tmp[200]; for(i = 4; ALPINE_LDAP_usable(mail, i); i++) ; new_confline(&ctmpa); ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = indent + 2; snprintf(tmp, sizeof(tmp), _("(%d email addresses)"), i); tmp[sizeof(tmp)-1] = '\0'; ctmpa->value = cpystr(tmp); ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; } } else{ new_confline(&ctmpa); ctmpa->flags |= CF_NOSELECT; ctmpa->valoffset = indent + 2; ctmpa->value = cpystr(_("")); ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->d.a.ld = res_list->ld; ctmpa->d.a.entry = e; ctmpa->d.a.info_used = res_list->info_used; ctmpa->d.a.serv = res_list->serv; ctmpa->d.a.ac = ac; } if(mail) ldap_value_free_len(mail); new_confline(&ctmpa); /* blank line */ ctmpa->keymenu = km; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->flags |= CF_NOSELECT | CF_B_LINE; } } if(first_line) some_selectable++; else if(alt_first_line) first_line = alt_first_line; else{ new_confline(&ctmpa); /* blank line */ ctmpa->keymenu = need_mail ? &addr_s_km_exit : &addr_s_km_goback; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->flags |= CF_NOSELECT | CF_B_LINE; new_confline(&ctmpa); first_line = ctmpa; strncpy(ee, "[ ", sizeof(ee)); ee[sizeof(ee)-1] = '\0'; if(wp_err && wp_err->ldap_errno) /* TRANSLATORS: No matches returned for an LDAP search */ snprintf(ee+2, sizeof(ee)-2, _("%s, No Matches Returned"), ldap_err2string(wp_err->ldap_errno)); else strncpy(ee+2, _("No Matches"), sizeof(ee)-2); ee[sizeof(ee)-1] = '\0'; /* TRANSLATORS: a request for user to choose Exit after they read text */ strncat(ee, _(" -- Choose Exit ]"), sizeof(ee)-strlen(ee)-1); ee[sizeof(ee)-1] = '\0'; ctmpa->value = cpystr(ee); ctmpa->valoffset = 10; ctmpa->keymenu = need_mail ? &addr_s_km_exit : &addr_s_km_goback; ctmpa->help = help; ctmpa->help_title = _(srch_res_help_title); ctmpa->tool = addr_select_tool; ctmpa->flags |= CF_NOSELECT; } if(style == AlwaysDisplay || style == DisplayForURL || style == AlwaysDisplayAndMailRequired || (style == DisplayIfOne && got_n_mail >= 1) || (style == DisplayIfTwo && got_n_mail >= 1 && got_n_entries >= 2)){ if(wp_err && wp_err->mangled) *wp_err->mangled = 1; prev_redrawer = ps_global->redrawer; push_titlebar_state(); memset(&screen, 0, sizeof(screen)); /* TRANSLATORS: Print something1 using something2. "this" is something1 */ switch(conf_scroll_screen(ps,&screen,first_line,ac->title,_("this"),0, NULL)){ case ADDR_SELECT_EXIT_VAL: retval = -1; break; case ADDR_SELECT_GOBACK_VAL: retval = -4; break; case ADDR_SELECT_FORCED_EXIT_VAL: if(alt_first_line) /* some entries, but none suitable */ retval = -2; else retval = -3; break; default: retval = 0; break; } ClearScreen(); pop_titlebar_state(); redraw_titlebar(); if((ps_global->redrawer = prev_redrawer) != NULL) (*ps_global->redrawer)(); if(result && retval == 0 && ac->selected_ld && ac->selected_entry){ (*result) = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S)); (*result)->ld = ac->selected_ld; (*result)->selected_entry = ac->selected_entry; (*result)->info_used = ac->info_used; (*result)->serv = ac->selected_serv; } } else if(style == DisplayIfOne && got_n_mail < 1){ if(alt_first_line) /* some entries, but none suitable */ retval = -2; else retval = -3; first_line = first_confline(ctmpa); free_conflines(&first_line); } else if(style == DisplayIfTwo && (got_n_mail < 1 || got_n_entries < 2)){ if(got_n_mail < 1){ if(alt_first_line) /* some entries, but none suitable */ retval = -2; else retval = -3; } else{ retval = 0; if(result){ (*result) = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S)); (*result)->ld = first_line->d.a.ld; (*result)->selected_entry = first_line->d.a.entry; (*result)->info_used = first_line->d.a.info_used; (*result)->serv = first_line->d.a.serv; } } first_line = first_confline(ctmpa); free_conflines(&first_line); } return(retval); } int addr_select_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int retval = 0; switch(cmd){ case MC_CHOICE : if(flags & CF_PRIVATE){ q_status_message(SM_ORDER | SM_DING, 0, 3, _("No email address available for this entry; choose another or ExitSelect")); } else if(some_selectable){ (*cl)->d.a.ac->selected_ld = (*cl)->d.a.ld; (*cl)->d.a.ac->selected_entry = (*cl)->d.a.entry; (*cl)->d.a.ac->info_used = (*cl)->d.a.info_used; (*cl)->d.a.ac->selected_serv = (*cl)->d.a.serv; retval = simple_exit_cmd(flags); } else retval = ADDR_SELECT_FORCED_EXIT_VAL; break; case MC_VIEW_TEXT : case MC_SAVE : case MC_FWDTEXT : case MC_COMPOSE : case MC_ROLE : {LDAP_CHOOSE_S *e; if((*cl)->d.a.ld && (*cl)->d.a.entry){ e = (LDAP_CHOOSE_S *)fs_get(sizeof(LDAP_CHOOSE_S)); e->ld = (*cl)->d.a.ld; e->selected_entry = (*cl)->d.a.entry; e->info_used = (*cl)->d.a.info_used; e->serv = (*cl)->d.a.serv; if(cmd == MC_VIEW_TEXT) view_ldap_entry(ps, e); else if(cmd == MC_SAVE) save_ldap_entry(ps, e, 0); else if(cmd == MC_COMPOSE) compose_to_ldap_entry(ps, e, 0); else if(cmd == MC_ROLE) compose_to_ldap_entry(ps, e, 1); else forward_ldap_entry(ps, e); fs_give((void **)&e); } } break; case MC_ADDRBOOK : retval = ADDR_SELECT_GOBACK_VAL; break; case MC_EXIT : retval = ADDR_SELECT_EXIT_VAL; break; default: retval = -1; break; } if(retval > 0) ps->mangled_body = 1; return(retval); } void dir_init_display(struct pine *ps, CONF_S **ctmp, char **servers, struct variable *var, CONF_S **first_line) { int i; char *serv; char *subtitle; size_t sizeofsub; LDAP_SERV_S *info; if(first_line) *first_line = NULL; if(servers && servers[0] && servers[0][0]){ for(i = 0; servers[i]; i++){ info = break_up_ldap_server(servers[i]); serv = (info && info->nick && *info->nick) ? cpystr(info->nick) : (info && info->serv && *info->serv) ? cpystr(info->serv) : cpystr(_("Bad Server Config, Delete this")); sizeofsub = (((info && info->serv && *info->serv) ? strlen(info->serv) : 3) + strlen(_(dserv)) + 15) * sizeof(char); subtitle = (char *)fs_get(sizeofsub); if(info && info->port >= 0) snprintf(subtitle, sizeofsub, "%s%s:%d", _(dserv), (info && info->serv && *info->serv) ? info->serv : "", info->port); else snprintf(subtitle, sizeofsub, "%s%s", _(dserv), (info && info->serv && *info->serv) ? info->serv : ""); subtitle[sizeofsub-1] = '\0'; add_ldap_server_to_display(ps, ctmp, serv, subtitle, var, i, &dir_conf_km, h_direct_config, dir_config_tool, 0, (first_line && *first_line == NULL) ? first_line : NULL); free_ldap_server_info(&info); } } else{ add_ldap_fake_first_server(ps, ctmp, var, &dir_conf_km, h_direct_config, dir_config_tool); if(first_line) *first_line = *ctmp; } } void directory_config(struct pine *ps, int edit_exceptions) { CONF_S *ctmp = NULL, *first_line = NULL; OPT_SCREEN_S screen; int no_ex, readonly_warning = 0; if(edit_exceptions){ q_status_message(SM_ORDER, 3, 7, _("Exception Setup not implemented for directory")); return; } ew = edit_exceptions ? ps_global->ew_for_except_vars : Main; no_ex = (ps_global->ew_for_except_vars == Main); if(ps->restricted) readonly_warning = 1; else{ PINERC_S *prc = NULL; switch(ew){ case Main: prc = ps->prc; break; case Post: prc = ps->post_prc; break; default: break; } readonly_warning = prc ? prc->readonly : 1; if(prc && prc->quit_to_edit){ quit_to_edit_msg(prc); return; } } if(ps->fix_fixed_warning) offer_to_fix_pinerc(ps); dir_init_display(ps, &ctmp, no_ex ? ps->VAR_LDAP_SERVERS : LVAL(&ps->vars[V_LDAP_SERVERS], ew), &ps->vars[V_LDAP_SERVERS], &first_line); memset(&screen, 0, sizeof(screen)); screen.deferred_ro_warning = readonly_warning; /* TRANSLATORS: Print something1 using something2. "servers" is something1 */ (void)conf_scroll_screen(ps, &screen, first_line, _("SETUP DIRECTORY SERVERS"), _("servers"), 0, NULL); ps->mangled_screen = 1; } int dir_config_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int first_one, rv = 0; first_one = (*cl)->value && (strcmp((*cl)->value, ADD_FIRST_LDAP_SERVER) == 0); switch(cmd){ case MC_DELETE : if(first_one) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Nothing to Delete, use Add")); else dir_config_del(ps, cl); break; case MC_ADD : if(!fixed_var((*cl)->var, NULL, "directory list")) dir_config_add(ps, cl); break; case MC_EDIT : if(!fixed_var((*cl)->var, NULL, "directory list")){ if(first_one) dir_config_add(ps, cl); else dir_config_edit(ps, cl); } break; case MC_SHUFFLE : if(!fixed_var((*cl)->var, NULL, "directory list")){ if(first_one) q_status_message(SM_ORDER|SM_DING, 0, 3, _("Nothing to Shuffle, use Add")); else dir_config_shuffle(ps, cl); } break; case MC_EXIT : rv = 2; break; default: rv = -1; break; } return(rv); } /* * Add LDAP directory entry */ void dir_config_add(struct pine *ps, CONF_S **cl) { char *raw_server = NULL; LDAP_SERV_S *info = NULL; char **lval; int no_ex; no_ex = (ps_global->ew_for_except_vars == Main); if(dir_edit_screen(ps, NULL, "ADD A", &raw_server) == 1){ info = break_up_ldap_server(raw_server); if(info && info->serv && *info->serv){ char *subtitle; size_t sizeofsub; int i, cnt = 0; char **new_list; CONF_S *cp; lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew); if(lval) while(lval[cnt]) cnt++; /* catch the special "" case */ if(cnt == 0 || (cnt == 1 && lval[0][0] == '\0')){ new_list = (char **)fs_get((1 + 1) * sizeof(char *)); new_list[0] = raw_server; new_list[1] = NULL; } else{ /* add one for new value */ cnt++; new_list = (char **)fs_get((cnt + 1) * sizeof(char *)); for(i = 0; i < (*cl)->varmem; i++) new_list[i] = cpystr(lval[i]); new_list[(*cl)->varmem] = raw_server; for(i = (*cl)->varmem; i < cnt; i++) new_list[i+1] = cpystr(lval[i]); } raw_server = NULL; set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew); free_list_array(&new_list); set_current_val((*cl)->var, TRUE, FALSE); sizeofsub = (((info && info->serv && *info->serv) ? strlen(info->serv) : 3) + strlen(_(dserv)) + 15) * sizeof(char); subtitle = (char *)fs_get(sizeofsub); if(info && info->port >= 0) snprintf(subtitle, sizeofsub, "%s%s:%d", _(dserv), (info && info->serv && *info->serv) ? info->serv : "", info->port); else snprintf(subtitle, sizeofsub, "%s%s", _(dserv), (info && info->serv && *info->serv) ? info->serv : ""); subtitle[sizeofsub-1] = '\0'; if(cnt < 2){ /* first one */ struct variable *var; struct key_menu *keymenu; HelpType help; int (*tool)(struct pine *, int, CONF_S **, unsigned); var = (*cl)->var; keymenu = (*cl)->keymenu; help = (*cl)->help; tool = (*cl)->tool; *cl = first_confline(*cl); free_conflines(cl); add_ldap_server_to_display(ps, cl, (info && info->nick && *info->nick) ? cpystr(info->nick) : cpystr(info->serv), subtitle, var, 0, keymenu, help, tool, 0, NULL); opt_screen->top_line = NULL; } else{ /* * Insert new server. */ add_ldap_server_to_display(ps, cl, (info && info->nick && *info->nick) ? cpystr(info->nick) : cpystr(info->serv), subtitle, (*cl)->var, (*cl)->varmem, (*cl)->keymenu, (*cl)->help, (*cl)->tool, 1, NULL); /* adjust the rest of the varmems */ for(cp = (*cl)->next; cp; cp = cp->next) cp->varmem++; } /* because add_ldap advanced cl to its third line */ (*cl) = (*cl)->prev->prev; fix_side_effects(ps, (*cl)->var, 0); write_pinerc(ps, ew, WRP_NONE); } else q_status_message(SM_ORDER, 0, 3, _("Add cancelled, no server name")); } free_ldap_server_info(&info); if(raw_server) fs_give((void **)&raw_server); } /* * Shuffle order of LDAP directory entries */ void dir_config_shuffle(struct pine *ps, CONF_S **cl) { int cnt, rv, current_num, new_num, i, j, deefault; char **new_list, **lval; char tmp[200]; HelpType help; ESCKEY_S opts[3]; CONF_S *a, *b; int no_ex; no_ex = (ps_global->ew_for_except_vars == Main); /* how many are in our current list? */ lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew); for(cnt = 0; lval && lval[cnt]; cnt++) ; if(cnt < 2){ q_status_message(SM_ORDER, 0, 3, _("Shuffle only makes sense when there is more than one server in list")); return; } current_num = (*cl)->varmem; /* variable number of highlighted directory */ /* Move it up or down? */ i = 0; opts[i].ch = 'u'; opts[i].rval = 'u'; opts[i].name = "U"; opts[i++].label = _("Up"); opts[i].ch = 'd'; opts[i].rval = 'd'; opts[i].name = "D"; opts[i++].label = _("Down"); opts[i].ch = -1; deefault = 'u'; if(current_num == 0){ /* no up */ opts[0].ch = -2; deefault = 'd'; } else if(current_num == cnt - 1) /* no down */ opts[1].ch = -2; snprintf(tmp, sizeof(tmp), "Shuffle \"%s\" %s%s%s ? ", (*cl)->value, (opts[0].ch != -2) ? _("UP") : "", (opts[0].ch != -2 && opts[1].ch != -2) ? " or " : "", (opts[1].ch != -2) ? _("DOWN") : ""); tmp[sizeof(tmp)-1] = '\0'; help = (opts[0].ch == -2) ? h_dir_shuf_down : (opts[1].ch == -2) ? h_dir_shuf_up : h_dir_shuf; rv = radio_buttons(tmp, -FOOTER_ROWS(ps), opts, deefault, 'x', help, RB_NORM); switch(rv){ case 'x': cmd_cancelled("Shuffle"); return; case 'u': new_num = current_num - 1; a = (*cl)->prev->prev->prev; b = *cl; break; case 'd': new_num = current_num + 1; a = *cl; b = (*cl)->next->next->next; break; } /* allocate space for new list */ new_list = (char **)fs_get((cnt + 1) * sizeof(char *)); /* fill in new_list */ for(i = 0; i < cnt; i++){ if(i == current_num) j = new_num; else if (i == new_num) j = current_num; else j = i; /* notice this works even if we were using default */ new_list[i] = cpystr(lval[j]); } new_list[i] = NULL; j = set_variable_list((*cl)->var - ps->vars, new_list, TRUE, ew); free_list_array(&new_list); if(j){ q_status_message(SM_ORDER, 0, 3, _("Shuffle cancelled: couldn't save configuration file")); set_current_val((*cl)->var, TRUE, FALSE); return; } set_current_val((*cl)->var, TRUE, FALSE); if(a == opt_screen->top_line) opt_screen->top_line = b; j = a->varmem; a->varmem = b->varmem; b->varmem = j; /* * Swap display lines. To start with, a is lower in list, b is higher. * The fact that there are 3 lines per entry is totally entangled in * the code. */ a->next->next->next = b->next->next->next; if(b->next->next->next) b->next->next->next->prev = a->next->next; b->prev = a->prev; if(a->prev) a->prev->next = b; b->next->next->next = a; a->prev = b->next->next; ps->mangled_body = 1; write_pinerc(ps, ew, WRP_NONE); } /* * Edit LDAP directory entry */ void dir_config_edit(struct pine *ps, CONF_S **cl) { char *raw_server = NULL, **lval; LDAP_SERV_S *info; int no_ex; no_ex = (ps_global->ew_for_except_vars == Main); lval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew); info = break_up_ldap_server((lval && lval[(*cl)->varmem]) ? lval[(*cl)->varmem] : NULL); if(dir_edit_screen(ps, info, "CHANGE THIS", &raw_server) == 1){ free_ldap_server_info(&info); info = break_up_ldap_server(raw_server); if(lval && lval[(*cl)->varmem] && strcmp(lval[(*cl)->varmem], raw_server) == 0) q_status_message(SM_ORDER, 0, 3, _("No change, cancelled")); else if(!(info && info->serv && *info->serv)) q_status_message(SM_ORDER, 0, 3, _("Change cancelled, use Delete if you want to remove this server")); else{ char *subtitle; int i, cnt; char **new_list; size_t sizeofsub; for(cnt = 0; lval && lval[cnt]; cnt++) ; new_list = (char **)fs_get((cnt + 1) * sizeof(char *)); for(i = 0; i < (*cl)->varmem; i++) new_list[i] = cpystr(lval[i]); new_list[(*cl)->varmem] = raw_server; raw_server = NULL; for(i = (*cl)->varmem + 1; i < cnt; i++) new_list[i] = cpystr(lval[i]); new_list[cnt] = NULL; set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew); free_list_array(&new_list); set_current_val((*cl)->var, TRUE, FALSE); if((*cl)->value) fs_give((void **)&(*cl)->value); (*cl)->value = cpystr((info->nick && *info->nick) ? info->nick : info->serv); if((*cl)->next->value) fs_give((void **)&(*cl)->next->value); sizeofsub = (((info && info->serv && *info->serv) ? strlen(info->serv) : 3) + strlen(_(dserv)) + 15) * sizeof(char); subtitle = (char *)fs_get(sizeofsub); if(info && info->port >= 0) snprintf(subtitle, sizeofsub, "%s%s:%d", _(dserv), (info && info->serv && *info->serv) ? info->serv : "", info->port); else snprintf(subtitle, sizeofsub, "%s%s", _(dserv), (info && info->serv && *info->serv) ? info->serv : ""); subtitle[sizeofsub] = '\0'; (*cl)->next->value = subtitle; fix_side_effects(ps, (*cl)->var, 0); write_pinerc(ps, ew, WRP_NONE); } } free_ldap_server_info(&info); if(raw_server) fs_give((void **)&raw_server); } #define LDAP_F_IMPL 0 #define LDAP_F_RHS 1 #define LDAP_F_REF 2 #define LDAP_F_NOSUB 3 #define LDAP_F_TLS 4 #define LDAP_F_TLSMUST 5 #define LDAP_F_LDAPS 6 bitmap_t ldap_option_list; struct variable *ldap_srch_rule_ptr; /* * Gives user screen to edit config values for ldap server. * * Args ps -- pine struct * def -- default values to start with * title -- part of title at top of screen * raw_server -- This is the returned item, allocated here and freed by caller. * * Returns: 0 if no change * 1 if user requested a change * (change is stored in raw_server and hasn't been acted upon yet) * 10 user says abort */ int dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_server) { OPT_SCREEN_S screen, *saved_screen; CONF_S *ctmp = NULL, *ctmpb, *first_line = NULL; char tmp[MAXPATH+1], custom_scope[MAXPATH], **apval; int rv, i, j, lv, indent, rindent; NAMEVAL_S *f; struct variable server_var, base_var, binddn_var, port_var, nick_var, srch_type_var, srch_rule_var, time_var, size_var, mailattr_var, cnattr_var, snattr_var, gnattr_var, cust_var, opt_var, *v, *varlist[21]; char *server = NULL, *base = NULL, *port = NULL, *nick = NULL, *srch_type = NULL, *srch_rule = NULL, *ttime = NULL, *c_s_f = "custom-search-filter", *binddn = NULL, *ssize = NULL, *mailattr = NULL, *cnattr = NULL, *snattr = NULL, *gnattr = NULL, *cust = NULL; /* * We edit by making a nested call to conf_scroll_screen. * We use some fake struct variables to get back the results in, and * so we can use the existing tools from the config screen. */ custom_scope[0] = '\0'; varlist[j = 0] = &server_var; varlist[++j] = &base_var; varlist[++j] = &port_var; varlist[++j] = &binddn_var; varlist[++j] = &nick_var; varlist[++j] = &srch_type_var; varlist[++j] = &srch_rule_var; varlist[++j] = &time_var; varlist[++j] = &size_var; varlist[++j] = &mailattr_var; varlist[++j] = &cnattr_var; varlist[++j] = &snattr_var; varlist[++j] = &gnattr_var; varlist[++j] = &cust_var; varlist[++j] = &opt_var; varlist[++j] = NULL; for(j = 0; varlist[j]; j++) memset(varlist[j], 0, sizeof(struct variable)); server_var.name = cpystr("ldap-server"); server_var.is_used = 1; server_var.is_user = 1; apval = APVAL(&server_var, ew); *apval = (def && def->serv && def->serv[0]) ? cpystr(def->serv) : NULL; set_current_val(&server_var, FALSE, FALSE); base_var.name = cpystr("search-base"); base_var.is_used = 1; base_var.is_user = 1; apval = APVAL(&base_var, ew); *apval = (def && def->base && def->base[0]) ? cpystr(def->base) : NULL; set_current_val(&base_var, FALSE, FALSE); port_var.name = cpystr("port"); port_var.is_used = 1; port_var.is_user = 1; if(def && def->port >= 0){ apval = APVAL(&port_var, ew); *apval = cpystr(int2string(def->port)); } port_var.global_val.p = cpystr(int2string(LDAP_PORT)); set_current_val(&port_var, FALSE, FALSE); binddn_var.name = cpystr("bind-dn"); binddn_var.is_used = 1; binddn_var.is_user = 1; apval = APVAL(&binddn_var, ew); *apval = (def && def->binddn && def->binddn[0]) ? cpystr(def->binddn) : NULL; set_current_val(&binddn_var, FALSE, FALSE); nick_var.name = cpystr("nickname"); nick_var.is_used = 1; nick_var.is_user = 1; apval = APVAL(&nick_var, ew); *apval = (def && def->nick && def->nick[0]) ? cpystr(def->nick) : NULL; set_current_val(&nick_var, FALSE, FALSE); srch_type_var.name = cpystr("search-type"); srch_type_var.is_used = 1; srch_type_var.is_user = 1; apval = APVAL(&srch_type_var, ew); *apval = (f=ldap_search_types(def ? def->type : -1)) ? cpystr(f->name) : NULL; srch_type_var.global_val.p = (f=ldap_search_types(DEF_LDAP_TYPE)) ? cpystr(f->name) : NULL; set_current_val(&srch_type_var, FALSE, FALSE); ldap_srch_rule_ptr = &srch_rule_var; /* so radiobuttons can tell */ srch_rule_var.name = cpystr("search-rule"); srch_rule_var.is_used = 1; srch_rule_var.is_user = 1; apval = APVAL(&srch_rule_var, ew); *apval = (f=ldap_search_rules(def ? def->srch : -1)) ? cpystr(f->name) : NULL; srch_rule_var.global_val.p = (f=ldap_search_rules(DEF_LDAP_SRCH)) ? cpystr(f->name) : NULL; set_current_val(&srch_rule_var, FALSE, FALSE); time_var.name = cpystr("timelimit"); time_var.is_used = 1; time_var.is_user = 1; if(def && def->time >= 0){ apval = APVAL(&time_var, ew); *apval = cpystr(int2string(def->time)); } time_var.global_val.p = cpystr(int2string(DEF_LDAP_TIME)); set_current_val(&time_var, FALSE, FALSE); size_var.name = cpystr("sizelimit"); size_var.is_used = 1; size_var.is_user = 1; if(def && def->size >= 0){ apval = APVAL(&size_var, ew); *apval = cpystr(int2string(def->size)); } size_var.global_val.p = cpystr(int2string(DEF_LDAP_SIZE)); set_current_val(&size_var, FALSE, FALSE); mailattr_var.name = cpystr("email-attribute"); mailattr_var.is_used = 1; mailattr_var.is_user = 1; apval = APVAL(&mailattr_var, ew); *apval = (def && def->mailattr && def->mailattr[0]) ? cpystr(def->mailattr) : NULL; mailattr_var.global_val.p = cpystr(DEF_LDAP_MAILATTR); set_current_val(&mailattr_var, FALSE, FALSE); cnattr_var.name = cpystr("name-attribute"); cnattr_var.is_used = 1; cnattr_var.is_user = 1; apval = APVAL(&cnattr_var, ew); *apval = (def && def->cnattr && def->cnattr[0]) ? cpystr(def->cnattr) : NULL; cnattr_var.global_val.p = cpystr(DEF_LDAP_CNATTR); set_current_val(&cnattr_var, FALSE, FALSE); snattr_var.name = cpystr("surname-attribute"); snattr_var.is_used = 1; snattr_var.is_user = 1; apval = APVAL(&snattr_var, ew); *apval = (def && def->snattr && def->snattr[0]) ? cpystr(def->snattr) : NULL; snattr_var.global_val.p = cpystr(DEF_LDAP_SNATTR); set_current_val(&snattr_var, FALSE, FALSE); gnattr_var.name = cpystr("givenname-attribute"); gnattr_var.is_used = 1; gnattr_var.is_user = 1; apval = APVAL(&gnattr_var, ew); *apval = (def && def->gnattr && def->gnattr[0]) ? cpystr(def->gnattr) : NULL; gnattr_var.global_val.p = cpystr(DEF_LDAP_GNATTR); set_current_val(&gnattr_var, FALSE, FALSE); cust_var.name = cpystr(c_s_f); cust_var.is_used = 1; cust_var.is_user = 1; apval = APVAL(&cust_var, ew); *apval = (def && def->cust && def->cust[0]) ? cpystr(def->cust) : NULL; set_current_val(&cust_var, FALSE, FALSE); /* TRANSLATORS: Features is a section title in the LDAP configuration screen. Following this are a list of features or options that can be turned on or off. */ opt_var.name = cpystr(_("Features")); opt_var.is_used = 1; opt_var.is_user = 1; opt_var.is_list = 1; clrbitmap(ldap_option_list); if(def && def->impl) setbitn(LDAP_F_IMPL, ldap_option_list); if(def && def->rhs) setbitn(LDAP_F_RHS, ldap_option_list); if(def && def->ref) setbitn(LDAP_F_REF, ldap_option_list); if(def && def->nosub) setbitn(LDAP_F_NOSUB, ldap_option_list); if(def && def->tls) setbitn(LDAP_F_TLS, ldap_option_list); if(def && def->tlsmust) setbitn(LDAP_F_TLSMUST, ldap_option_list); if(def && def->ldaps) setbitn(LDAP_F_LDAPS, ldap_option_list); /* save the old opt_screen before calling scroll screen again */ saved_screen = opt_screen; indent = utf8_width(c_s_f) + 3; rindent = 12; /* Server */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR LDAP SERVER"); ctmp->var = &server_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_server; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,server_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); first_line = ctmp; /* Search Base */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SERVER SEARCH BASE"); ctmp->var = &base_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_base; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,base_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Port */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR PORT NUMBER"); ctmp->var = &port_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_port; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,port_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); ctmp->flags |= CF_NUMBER; /* Bind DN (DN to bind to if needed) */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SERVER BIND DN"); ctmp->var = &binddn_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_binddn; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,binddn_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Nickname */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SERVER NICKNAME"); ctmp->var = &nick_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_nick; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,nick_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Options */ new_confline(&ctmp); ctmp->var = &opt_var; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", opt_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = ldap_checkbox_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Feature Name"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_checkbox_keymenu; ctmp->help = NO_HELP; ctmp->tool = ldap_checkbox_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); /* find longest value's name */ for(lv = 0, i = 0; (f = ldap_feature_list(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); /* enabling ldaps disables tls */ if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL && bitnset(f->value, ldap_option_list)){ int clear = 0; if((f = ldap_feature_list(LDAP_F_TLS)) != NULL && bitnset(f->value, ldap_option_list)){ clear++; clrbitn(f->value, ldap_option_list); } if((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL && bitnset(f->value, ldap_option_list)){ clear++; clrbitn(f->value, ldap_option_list); } if(clear > 0) q_status_message(SM_ORDER, 3, 3, _("Can not use TLS when connecting using LDAPS")); } /* enabling tls disables ldaps */ if(((f = ldap_feature_list(LDAP_F_TLS)) != NULL && bitnset(f->value, ldap_option_list)) || ((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL && bitnset(f->value, ldap_option_list))){ if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL && bitnset(f->value, ldap_option_list)){ clrbitn(f->value, ldap_option_list); q_status_message(SM_ORDER, 3, 3, _("Can not use LDAPS when connecting using TLS")); } } for(i = 0; (f = ldap_feature_list(i)); i++){ new_confline(&ctmp); ctmp->var = &opt_var; ctmp->help_title= _("HELP FOR LDAP FEATURES"); ctmp->varnamep = ctmpb; ctmp->keymenu = &config_checkbox_keymenu; switch(i){ case LDAP_F_IMPL: ctmp->help = h_config_ldap_opts_impl; break; case LDAP_F_RHS: ctmp->help = h_config_ldap_opts_rhs; break; case LDAP_F_REF: ctmp->help = h_config_ldap_opts_ref; break; case LDAP_F_NOSUB: ctmp->help = h_config_ldap_opts_nosub; break; case LDAP_F_TLS: ctmp->help = h_config_ldap_opts_tls; break; case LDAP_F_TLSMUST: ctmp->help = h_config_ldap_opts_tlsmust; break; case LDAP_F_LDAPS: ctmp->help = h_config_ldap_opts_ldaps; break; } ctmp->tool = ldap_checkbox_tool; ctmp->valoffset = rindent; ctmp->varmem = i; utf8_snprintf(tmp, sizeof(tmp), "[%c] %-*.*w", bitnset(f->value, ldap_option_list) ? 'X' : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Search Type */ new_confline(&ctmp); ctmp->var = &srch_type_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", srch_type_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Rule Values"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = ldap_radiobutton_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); /* find longest value's name */ for(lv = 0, i = 0; (f = ldap_search_types(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); for(i = 0; (f = ldap_search_types(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SEARCH TYPE"); ctmp->var = &srch_type_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_ldap_searchtypes; ctmp->varmem = i; ctmp->tool = ldap_radiobutton_tool; ctmp->varnamep = ctmpb; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!def || def->type == -1) && f->value == DEF_LDAP_TYPE) || (def && f->value == def->type)) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; ctmp->varname = cpystr(""); /* Search Rule */ new_confline(&ctmp); ctmp->var = &srch_rule_var; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; snprintf(tmp, sizeof(tmp), "%s =", srch_rule_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmpb = ctmp; ctmp->flags |= (CF_NOSELECT | CF_STARTITEM); /* Search Rule */ new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = NULL; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr("Set Rule Values"); new_confline(&ctmp); ctmp->var = NULL; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = NO_HELP; ctmp->tool = ldap_radiobutton_tool; ctmp->varnamep = ctmpb; ctmp->flags |= CF_NOSELECT; ctmp->value = cpystr(set_choose); /* find longest value's name */ for(lv = 0, i = 0; (f = ldap_search_rules(i)); i++) if(lv < (j = utf8_width(f->name))) lv = j; lv = MIN(lv, 100); for(i = 0; (f = ldap_search_rules(i)); i++){ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SEARCH RULE"); ctmp->var = &srch_rule_var; ctmp->valoffset = rindent; ctmp->keymenu = &config_radiobutton_keymenu; ctmp->help = h_config_ldap_searchrules; ctmp->varmem = i; ctmp->tool = ldap_radiobutton_tool; ctmp->varnamep = ctmpb; utf8_snprintf(tmp, sizeof(tmp), "(%c) %-*.*w", (((!def || def->srch == -1) && f->value == DEF_LDAP_SRCH) || (def && f->value == def->srch)) ? R_SELD : ' ', lv, lv, f->name); tmp[sizeof(tmp)-1] = '\0'; ctmp->value = cpystr(tmp); } /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; ctmp->varname = cpystr(""); /* Email attribute name */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR EMAIL ATTRIBUTE NAME"); ctmp->var = &mailattr_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_email_attr; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,mailattr_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Name attribute name */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR NAME ATTRIBUTE NAME"); ctmp->var = &cnattr_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_cn_attr; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,cnattr_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Surname attribute name */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SURNAME ATTRIBUTE NAME"); ctmp->var = &snattr_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_sn_attr; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,snattr_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Givenname attribute name */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR GIVEN NAME ATTRIBUTE NAME"); ctmp->var = &gnattr_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_gn_attr; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,gnattr_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; ctmp->varname = cpystr(""); /* Time limit */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR SERVER TIMELIMIT"); ctmp->var = &time_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_time; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,time_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); ctmp->flags |= CF_NUMBER; /* Size limit */ new_confline(&ctmp); ctmp->var = &size_var; ctmp->help_title= _("HELP FOR SERVER SIZELIMIT"); ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_size; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,size_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); ctmp->flags |= CF_NUMBER; /* Blank line */ new_confline(&ctmp); ctmp->flags |= CF_NOSELECT | CF_B_LINE; /* Custom Search Filter */ new_confline(&ctmp); ctmp->help_title= _("HELP FOR CUSTOM SEARCH FILTER"); ctmp->var = &cust_var; ctmp->valoffset = indent; ctmp->keymenu = &config_text_keymenu; ctmp->help = h_config_ldap_cust; ctmp->tool = dir_edit_tool; utf8_snprintf(tmp, sizeof(tmp), "%-*.*w =", indent-3,indent-3,cust_var.name); tmp[sizeof(tmp)-1] = '\0'; ctmp->varname = cpystr(tmp); ctmp->varnamep = ctmp; ctmp->value = pretty_value(ps, ctmp); snprintf(tmp, sizeof(tmp), "%s DIRECTORY SERVER", title); tmp[sizeof(tmp)-1] = '\0'; memset(&screen, 0, sizeof(screen)); screen.ro_warning = saved_screen ? saved_screen->deferred_ro_warning : 0; /* TRANSLATORS: Print something1 using something2. servers is something1 */ rv = conf_scroll_screen(ps, &screen, first_line, tmp, _("servers"), 0, NULL); /* * Now look at the fake variables and extract the information we * want from them. */ if(rv == 1 && raw_server){ char dir_tmp[2200], *p; int portval = -1, timeval = -1, sizeval = -1; apval = APVAL(&server_var, ew); server = *apval; *apval = NULL; apval = APVAL(&base_var, ew); base = *apval; *apval = NULL; apval = APVAL(&port_var, ew); port = *apval; *apval = NULL; apval = APVAL(&binddn_var, ew); binddn = *apval; *apval = NULL; apval = APVAL(&nick_var, ew); nick = *apval; *apval = NULL; apval = APVAL(&srch_type_var, ew); srch_type = *apval; *apval = NULL; apval = APVAL(&srch_rule_var, ew); srch_rule = *apval; *apval = NULL; apval = APVAL(&time_var, ew); ttime = *apval; *apval = NULL; apval = APVAL(&size_var, ew); ssize = *apval; *apval = NULL; apval = APVAL(&cust_var, ew); cust = *apval; *apval = NULL; apval = APVAL(&mailattr_var, ew); mailattr = *apval; *apval = NULL; apval = APVAL(&snattr_var, ew); snattr = *apval; *apval = NULL; apval = APVAL(&gnattr_var, ew); gnattr = *apval; *apval = NULL; apval = APVAL(&cnattr_var, ew); cnattr = *apval; *apval = NULL; if(server) removing_leading_and_trailing_white_space(server); if(base){ removing_leading_and_trailing_white_space(base); (void)removing_double_quotes(base); p = add_backslash_escapes(base); fs_give((void **)&base); base = p; } if(port){ removing_leading_and_trailing_white_space(port); if(*port) portval = atoi(port); } if(binddn){ removing_leading_and_trailing_white_space(binddn); (void)removing_double_quotes(binddn); p = add_backslash_escapes(binddn); fs_give((void **)&binddn); binddn = p; } if(nick){ removing_leading_and_trailing_white_space(nick); (void)removing_double_quotes(nick); p = add_backslash_escapes(nick); fs_give((void **)&nick); nick = p; } if(ttime){ removing_leading_and_trailing_white_space(ttime); if(*ttime) timeval = atoi(ttime); } if(ssize){ removing_leading_and_trailing_white_space(ssize); if(*ssize) sizeval = atoi(ssize); } if(cust){ removing_leading_and_trailing_white_space(cust); p = add_backslash_escapes(cust); fs_give((void **)&cust); cust = p; } if(mailattr){ removing_leading_and_trailing_white_space(mailattr); p = add_backslash_escapes(mailattr); fs_give((void **)&mailattr); mailattr = p; } if(snattr){ removing_leading_and_trailing_white_space(snattr); p = add_backslash_escapes(snattr); fs_give((void **)&snattr); snattr = p; } if(gnattr){ removing_leading_and_trailing_white_space(gnattr); p = add_backslash_escapes(gnattr); fs_give((void **)&gnattr); gnattr = p; } if(cnattr){ removing_leading_and_trailing_white_space(cnattr); p = add_backslash_escapes(cnattr); fs_give((void **)&cnattr); cnattr = p; } /* * Don't allow user to edit scope but if one is present then we * leave it (so they could edit it by hand). */ if(def && def->scope != -1 && def->scope != DEF_LDAP_SCOPE){ NAMEVAL_S *v; v = ldap_search_scope(def->scope); if(v){ snprintf(custom_scope, sizeof(custom_scope), "/scope=%s", v->name); custom_scope[sizeof(custom_scope)-1] = '\0'; } } 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\"", server ? server : "", (portval >= 0 && port && *port) ? ":" : "", (portval >= 0 && port && *port) ? port : "", base ? base : "", binddn ? binddn : "", bitnset(LDAP_F_IMPL, ldap_option_list) ? 1 : 0, bitnset(LDAP_F_RHS, ldap_option_list) ? 1 : 0, bitnset(LDAP_F_REF, ldap_option_list) ? 1 : 0, bitnset(LDAP_F_NOSUB, ldap_option_list) ? 1 : 0, bitnset(LDAP_F_TLS, ldap_option_list) ? 1 : 0, bitnset(LDAP_F_TLSMUST, ldap_option_list) ? 1 : 0, bitnset(LDAP_F_LDAPS, ldap_option_list) ? 1 : 0, srch_type ? srch_type : "", srch_rule ? srch_rule : "", custom_scope, (timeval >= 0 && ttime && *ttime) ? ttime : "", (sizeval >= 0 && ssize && *ssize) ? ssize : "", cust ? cust : "", nick ? nick : "", mailattr ? mailattr : "", cnattr ? cnattr : "", snattr ? snattr : "", gnattr ? gnattr : ""); dir_tmp[sizeof(dir_tmp)-1] = '\0'; *raw_server = cpystr(dir_tmp); } for(j = 0; varlist[j]; j++){ v = varlist[j]; if(v->current_val.p) fs_give((void **)&v->current_val.p); if(v->global_val.p) fs_give((void **)&v->global_val.p); if(v->main_user_val.p) fs_give((void **)&v->main_user_val.p); if(v->post_user_val.p) fs_give((void **)&v->post_user_val.p); if(v->name) fs_give((void **)&v->name); } if(server) fs_give((void **)&server); if(base) fs_give((void **)&base); if(port) fs_give((void **)&port); if(binddn) fs_give((void **)&binddn); if(nick) fs_give((void **)&nick); if(srch_type) fs_give((void **)&srch_type); if(srch_rule) fs_give((void **)&srch_rule); if(ttime) fs_give((void **)&ttime); if(ssize) fs_give((void **)&ssize); if(mailattr) fs_give((void **)&mailattr); if(cnattr) fs_give((void **)&cnattr); if(snattr) fs_give((void **)&snattr); if(gnattr) fs_give((void **)&gnattr); if(cust) fs_give((void **)&cust); opt_screen = saved_screen; ps->mangled_screen = 1; return(rv); } /* * Just calls text_tool except for intercepting MC_EXIT. */ int dir_edit_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { if(cmd == MC_EXIT) return(config_exit_cmd(flags)); else return(text_tool(ps, cmd, cl, flags)); } /* * Delete LDAP directory entry */ void dir_config_del(struct pine *ps, CONF_S **cl) { char prompt[81]; int rv = 0, i; if(fixed_var((*cl)->var, NULL, NULL)){ if((*cl)->var->post_user_val.l || (*cl)->var->main_user_val.l){ if(want_to(_("Delete (unused) directory servers "), 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){ rv = 1; delete_user_vals((*cl)->var); } } else q_status_message(SM_ORDER, 3, 3, _("Can't delete sys-admin defined value")); } else{ int cnt, ans = 0, no_ex; char **new_list, **lval, **nelval; no_ex = (ps_global->ew_for_except_vars == Main); /* This can't happen, intercepted at caller by first_one case */ nelval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew); lval = LVAL((*cl)->var, ew); if(lval && lval[0] && lval[0][0] == '\0') ans = 'r'; /* how many servers defined? */ for(cnt = 0; nelval[cnt]; cnt++) ; /* * If using default and there is more than one in list, ask if user * wants to ignore them all or delete just this one. If just this * one, copy rest to user_val. If ignore all, copy "" to user_val * to override. */ if(!lval && cnt > 1){ static ESCKEY_S opts[] = { {'i', 'i', "I", N_("Ignore All")}, {'r', 'r', "R", N_("Remove One")}, {-1, 0, NULL, NULL}}; ans = radio_buttons( _("Ignore all default directory servers or just remove this one ? "), -FOOTER_ROWS(ps), opts, 'i', 'x', h_ab_del_dir_ignore, RB_NORM); } if(ans == 0){ snprintf(prompt, sizeof(prompt), _("Really delete %s \"%s\" from directory servers "), ((*cl)->value && *(*cl)->value) ? "server" : "item", ((*cl)->value && *(*cl)->value) ? (*cl)->value : int2string((*cl)->varmem + 1)); prompt[sizeof(prompt)-1] = '\0'; } ps->mangled_footer = 1; if(ans == 'i'){ rv = ps->mangled_body = 1; /* * Ignore all of default by adding an empty string. Make it * look just like there are no servers defined. */ new_list = (char **)fs_get((1 + 1) * sizeof(char *)); new_list[0] = cpystr(""); new_list[1] = NULL; set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew); free_list_array(&new_list); *cl = first_confline(*cl); free_conflines(cl); opt_screen->top_line = NULL; add_ldap_fake_first_server(ps, cl, &ps->vars[V_LDAP_SERVERS], &dir_conf_km, h_direct_config, dir_config_tool); } else if(ans == 'r' || (ans != 'x' && want_to(prompt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y')){ CONF_S *cp; char **servers; int move_top = 0, this_one, revert_to_default, default_there_to_revert_to; /* * Remove one from current list. */ rv = ps->mangled_body = 1; this_one = (*cl)->varmem; /* might have to re-adjust screen to see new current */ move_top = (this_one > 0) && (this_one == cnt - 1) && (((*cl) == opt_screen->top_line) || ((*cl)->prev == opt_screen->top_line) || ((*cl)->prev->prev == opt_screen->top_line)); /* * If this is last one and there is a default available, revert * to it. */ revert_to_default = ((cnt == 1) && lval); if(cnt > 1){ new_list = (char **)fs_get((cnt + 1) * sizeof(char *)); for(i = 0; i < this_one; i++) new_list[i] = cpystr(nelval[i]); for(i = this_one; i < cnt; i++) new_list[i] = cpystr(nelval[i+1]); set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew); free_list_array(&new_list); } else if(revert_to_default){ char ***alval; alval = ALVAL((*cl)->var, ew); if(alval && *alval) free_list_array(alval); } else{ /* cnt is one and we want to hide default */ new_list = (char **)fs_get((1 + 1) * sizeof(char *)); new_list[0] = cpystr(""); new_list[1] = NULL; set_variable_list(V_LDAP_SERVERS, new_list, FALSE, ew); free_list_array(&new_list); } if(cnt == 1){ /* delete display line for this_one */ if(revert_to_default){ servers = (*cl)->var->global_val.l; default_there_to_revert_to = (servers != NULL); } *cl = first_confline(*cl); free_conflines(cl); opt_screen->top_line = NULL; if(revert_to_default && default_there_to_revert_to){ CONF_S *first_line = NULL; q_status_message(SM_ORDER, 0, 3, _("Reverting to default directory server")); dir_init_display(ps, cl, servers, &ps->vars[V_LDAP_SERVERS], &first_line); *cl = first_line; } else{ add_ldap_fake_first_server(ps, cl, &ps->vars[V_LDAP_SERVERS], &dir_conf_km, h_direct_config, dir_config_tool); } } else if(this_one == cnt - 1){ /* deleted last one */ /* back up and delete it */ *cl = (*cl)->prev; free_conflines(&(*cl)->next); /* now back up to first line of this server */ *cl = (*cl)->prev->prev; if(move_top) opt_screen->top_line = *cl; } else{ /* deleted one out of the middle */ if(*cl == opt_screen->top_line) opt_screen->top_line = (*cl)->next->next->next; cp = *cl; *cl = (*cl)->next; /* move to next line, then */ snip_confline(&cp); /* snip 1st deleted line */ cp = *cl; *cl = (*cl)->next; /* move to next line, then */ snip_confline(&cp); /* snip 2nd deleted line */ cp = *cl; *cl = (*cl)->next; /* move to next line, then */ snip_confline(&cp); /* snip 3rd deleted line */ /* adjust varmems */ for(cp = *cl; cp; cp = cp->next) cp->varmem--; } } else q_status_message(SM_ORDER, 0, 3, _("Server not deleted")); } if(rv == 1){ set_current_val((*cl)->var, TRUE, FALSE); fix_side_effects(ps, (*cl)->var, 0); write_pinerc(ps, ew, WRP_NONE); } } /* * Utility routine to help set up display */ void add_ldap_fake_first_server(struct pine *ps, CONF_S **ctmp, struct variable *var, struct key_menu *km, HelpType help, int (*tool)(struct pine *, int, CONF_S **, unsigned)) { new_confline(ctmp); (*ctmp)->help_title= _("HELP FOR DIRECTORY SERVER CONFIGURATION"); (*ctmp)->value = cpystr(ADD_FIRST_LDAP_SERVER); (*ctmp)->var = var; (*ctmp)->varmem = 0; (*ctmp)->keymenu = km; (*ctmp)->help = help; (*ctmp)->tool = tool; (*ctmp)->valoffset = 2; } /* * Add an ldap server to the display list. * * Args before -- Insert it before current, else append it after. */ void add_ldap_server_to_display(struct pine *ps, CONF_S **ctmp, char *serv, char *subtitle, struct variable *var, int member, struct key_menu *km, HelpType help, int (*tool)(struct pine *, int, CONF_S **, unsigned), int before, CONF_S **first_line) { new_confline(ctmp); if(first_line) *first_line = *ctmp; if(before){ /* * New_confline appends ctmp after old current instead of inserting * it, so we have to adjust. We have * <- a <-> b <-> p <-> c -> and want <- a <-> p <-> b <-> c -> */ CONF_S *a, *b, *c, *p; p = *ctmp; b = (*ctmp)->prev; c = (*ctmp)->next; a = b ? b->prev : NULL; if(a) a->next = p; if(b){ b->prev = p; b->next = c; } if(c) c->prev = b; p->prev = a; p->next = b; } (*ctmp)->help_title= _("HELP FOR DIRECTORY SERVER CONFIGURATION"); (*ctmp)->value = serv; (*ctmp)->var = var; (*ctmp)->varmem = member; (*ctmp)->keymenu = km; (*ctmp)->help = help; (*ctmp)->tool = tool; (*ctmp)->flags |= CF_STARTITEM; (*ctmp)->valoffset = 4; new_confline(ctmp); (*ctmp)->value = subtitle; (*ctmp)->keymenu = km; (*ctmp)->help = help; (*ctmp)->tool = tool; (*ctmp)->flags |= CF_NOSELECT; (*ctmp)->valoffset = 8; new_confline(ctmp); (*ctmp)->keymenu = km; (*ctmp)->help = help; (*ctmp)->tool = tool; (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE; (*ctmp)->valoffset = 0; } /* * ldap option list manipulation tool * * * returns: -1 on unrecognized cmd, 0 if no change, 1 if change */ int ldap_checkbox_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0; switch(cmd){ case MC_TOGGLE: /* mark/unmark option */ rv = 1; toggle_ldap_option_bit(ps, (*cl)->varmem, (*cl)->var, (*cl)->value); break; case MC_EXIT: /* exit */ rv = config_exit_cmd(flags); break; default : rv = -1; break; } return(rv); } void toggle_ldap_option_bit(struct pine *ps, int index, struct variable *var, char *value) { NAMEVAL_S *f; int tls_is_on_now; int tlsmust_is_on_now; int ldaps_is_on_now; int tls_is_on_after; int tlsmust_is_on_after; int ldaps_is_on_after; tls_is_on_now = (f = ldap_feature_list(LDAP_F_TLS)) != NULL && bitnset(f->value, ldap_option_list) ? 1 : 0; tlsmust_is_on_now = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL && bitnset(f->value, ldap_option_list) ? 1 : 0; ldaps_is_on_now = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL && bitnset(f->value, ldap_option_list) ? 1 : 0; f = ldap_feature_list(index); /* flip the bit */ if(bitnset(f->value, ldap_option_list)) clrbitn(f->value, ldap_option_list); else setbitn(f->value, ldap_option_list); tls_is_on_after = (f = ldap_feature_list(LDAP_F_TLS)) != NULL && bitnset(f->value, ldap_option_list) ? 1 : 0; tlsmust_is_on_after = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL && bitnset(f->value, ldap_option_list) ? 1 : 0; ldaps_is_on_after = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL && bitnset(f->value, ldap_option_list) ? 1 : 0; f = ldap_feature_list(index); if(!ldaps_is_on_now && ldaps_is_on_after){ if(tlsmust_is_on_after || tls_is_on_after){ char *name; if(tlsmust_is_on_after) name = ldap_feature_list(LDAP_F_TLSMUST)->name; else name = ldap_feature_list(LDAP_F_TLS)->name; clrbitn(f->value, ldap_option_list); q_status_message1(SM_ORDER, 3, 3, _("Can not use LDAPS when using TLS. Disable \"%s\" first."), name); } } else if(!tls_is_on_now && tls_is_on_after){ if(ldaps_is_on_after){ char *name = ldap_feature_list(LDAP_F_LDAPS)->name; clrbitn(f->value, ldap_option_list); q_status_message1(SM_ORDER, 3, 3, _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name); } } else if(!tlsmust_is_on_now && tlsmust_is_on_after){ if(ldaps_is_on_after){ char *name = ldap_feature_list(LDAP_F_LDAPS)->name; clrbitn(f->value, ldap_option_list); q_status_message1(SM_ORDER, 3, 3, _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name); } } if(value) value[1] = bitnset(f->value, ldap_option_list) ? 'X' : ' '; } NAMEVAL_S * ldap_feature_list(int index) { static NAMEVAL_S ldap_feat_list[] = { {"use-implicitly-from-composer", NULL, LDAP_F_IMPL}, {"lookup-addrbook-contents", NULL, LDAP_F_RHS}, {"save-search-criteria-not-result", NULL, LDAP_F_REF}, {"disable-ad-hoc-space-substitution", NULL, LDAP_F_NOSUB}, {"attempt-tls-on-connection", NULL, LDAP_F_TLS}, {"require-tls-on-connection", NULL, LDAP_F_TLSMUST}, {"require-ldaps-on-connection", NULL, LDAP_F_LDAPS} }; return((index >= 0 && index < (sizeof(ldap_feat_list)/sizeof(ldap_feat_list[0]))) ? &ldap_feat_list[index] : NULL); } /* * simple radio-button style variable handler */ int ldap_radiobutton_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) { int rv = 0; CONF_S *ctmp; NAMEVAL_S *rule; char **apval; switch(cmd){ case MC_CHOICE : /* set/unset feature */ /* hunt backwards, turning off old values */ for(ctmp = *cl; ctmp && !(ctmp->flags & CF_NOSELECT) && !ctmp->varname; ctmp = prev_confline(ctmp)) ctmp->value[1] = ' '; /* hunt forwards, turning off old values */ for(ctmp = *cl; ctmp && !(ctmp->flags & CF_NOSELECT) && !ctmp->varname; ctmp = next_confline(ctmp)) ctmp->value[1] = ' '; /* turn on current value */ (*cl)->value[1] = R_SELD; if((*cl)->var == ldap_srch_rule_ptr) rule = ldap_search_rules((*cl)->varmem); else rule = ldap_search_types((*cl)->varmem); apval = APVAL((*cl)->var, ew); if(apval && *apval) fs_give((void **)apval); if(apval) *apval = cpystr(rule->name); ps->mangled_body = 1; /* BUG: redraw it all for now? */ rv = 1; break; case MC_EXIT: /* exit */ rv = config_exit_cmd(flags); break; default : rv = -1; break; } return(rv); } #endif /* ENABLE_LDAP */