/**
 * File:
 *   include/mail/widgets.ycp
 *
 * Package:
 *   Configuration of mail
 *
 * Summary:
 *   Widget definitions.
 *
 * Authors:
 *   Martin Vidner <mvidner@suse.cz>
 *
 * $Id: widgets.ycp 17828 2004-06-14 13:16:34Z mvidner $
 */

{

textdomain "mail";

import "Mail";
import "MailAliases";

import "Hostname";
import "Address";

import "Popup";
import "Label";

/* ---------------------------------------------------------------- */

/**
 * See RFC 2822, 3.4
 * But for now, nonempty, no-spaces.
 * @param address an address to check
 * @return valid?
 */
define boolean check_mail_local_part (string address) ``{
    return address != "" && findfirstof (address, " ") == nil;
}

/* ---------------------------------------------------------------- */

/**
 * A list to check entered user names against.
 * It is initialized on first use.
 */
list<string> local_users = nil;

/**
 * Read user names from passwd.
 * It does not get the NIS entries, that's why one combo is editable.
 * "+" is filtered out.
 * @return user name list
 */
define list<string> GetLocalUsers () ``{
    if (local_users == nil)
    {
	// initialize the list
	import "Users";
	import "UsersCache";

	Users::SetGUI (false);
	Users::Read ();
	local_users = (list<string>) union (
		    UsersCache::GetUsernames ("local"),
		    UsersCache::GetUsernames ("system"));
    }
    return local_users;
}


/* ---------------------------------------------------------------- */

/**
 * Formats a list for a TextEntry, separating the elements by ", "
 * @param alist	a list
 * @return	a string
 */
define string listToString (list<string> alist) ``{
    return mergestring (alist, ", ");
}

/**
 * Splits a TextEntry string into a list of strings
 * separated by spaces, commas or semicolons.
 * Empty strings are removed.
 * @param astring	a string
 * @return		a list of strings
 */
define list<string> stringToList (string astring) ``{
    list<string> alist = splitstring (astring, " ,;");
    return filter (string s, alist, ``(s != ""));
}

/* ---------------------------------------------------------------- */

/**
 * A replacement for the Next button: "Finish", `next
 */
term finish_button = `PushButton (`id (`next),
					 `opt (`default, `key_F10),
					 Label::FinishButton());
/**
 * @struct fetchmail
 *	$[server:, protocol:, remote_user:, local_user:, password:, ...]
 */
map fetchmail_item = $[];

// don't forget to reset it!
boolean fetchmail_item_touched = false;


define string Get_foo () ``{
    return fetchmail_item["protocol"]:"";
}

define void Set_foo (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    fetchmail_item_touched = fetchmail_item_touched ||
	(fetchmail_item["protocol"]:"" != val);
    fetchmail_item = add (fetchmail_item, "protocol", val);
}

define boolean Validate_foo (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    if (!Hostname::CheckDomain (val))
    {
	UI::SetFocus (`id (id));
	// Translators: error popup
	string msg = _("The host name is incorrect");
	Popup::Error (msg);
	return false;
    }
    return true;
}

define string Get_outgoing_mail_server () ``{
     return Mail::outgoing_mail_server;
}

define void Set_outgoing_mail_server (symbol id) ``{
    string oms = (string) UI::QueryWidget (`id (id), `Value);
    Mail::Touch (Mail::outgoing_mail_server != oms);
    Mail::outgoing_mail_server = oms;
}

define boolean Validate_outgoing_mail_server(symbol id) ``{
    // when validating: may be enclosed in brackets (prevents mx lookups)
    string oms = (string) UI::QueryWidget (`id (id), `Value);
    // watch this: "[", no brackets, "]"
    string oms_no_brackets = regexpmatch (oms, "[[][^][]*[]]") ?
	regexpsub (oms, ".(.*).", "\\1") : oms;

    if (oms_no_brackets != "" &&
	! Address::Check (oms_no_brackets)
	||
	oms_no_brackets == "" &&
	Mail::connection_type == `dialup)
    {
	UI::SetFocus (`id (id));
	Popup::Error (Address::Valid4 ());
	return false;
    }
    return true;
}


define string Get_from_header () ``{
     return Mail::from_header;
}

define void Set_from_header (symbol id) ``{
    string fh = (string) UI::QueryWidget (`id (id), `Value);
    Mail::Touch (Mail::from_header != fh);
    Mail::from_header = fh;
}

define boolean Validate_from_header (symbol id) ``{
    string fh = (string) UI::QueryWidget (`id (id), `Value);
    if (fh != "" && ! Hostname::CheckDomain (fh))
    {
	UI::SetFocus (`id (id));
	Popup::Error (Hostname::ValidDomain ());
	return false;
    }
    return true;
}

define string Get_local_domains () ``{
     return listToString (Mail::local_domains);
}

define void Set_local_domains (symbol id) ``{
    list<string> lld = stringToList ((string)UI::QueryWidget(`id (id), `Value));
    Mail::Touch (Mail::local_domains != lld);
    Mail::local_domains = lld;
}

define boolean Validate_local_domains (symbol id) ``{
    list<string> lld = stringToList ((string)UI::QueryWidget(`id (id), `Value));
    // find one that fails
    if (find (string s, lld, {
	// #36871
	// Strip \$ which marks postfix substitutions:
	// Verify that they only occur together
	// and then remove them individually. Elementary, dear Watson.
	if (regexpmatch (s, "\\\\[^$]") ||
	    regexpmatch (s, "\\\\$") ||
	    regexpmatch (s, "[^\\]\\$") ||
	    regexpmatch (s, "^\\$"))
	{
	    return true;
	}
	s = deletechars (s, "\\$");
	return ! Hostname::CheckDomain (s);
    }) != nil)
    {
	UI::SetFocus (`id (id));
	Popup::Error (Hostname::ValidDomain ());
	return false;
    }
    return true;
}

define boolean Get_listen_remote () ``{
    return Mail::listen_remote;
}

define void Set_listen_remote (symbol id) ``{
    boolean lr = (boolean) UI::QueryWidget (`id (id), `Value);
    Mail::Touch (Mail::listen_remote != lr);
    Mail::listen_remote = lr;
}

define boolean Get_use_amavis () ``{
    return Mail::use_amavis;
}

define void Set_use_amavis (symbol id) ``{
    boolean am = (boolean) UI::QueryWidget (`id (id), `Value);
    Mail::Touch (Mail::use_amavis != am);
    Mail::use_amavis = am;
}


define string Get_fm_server () ``{
    return fetchmail_item["server"]:"";
}

define void Set_fm_server (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    fetchmail_item_touched = fetchmail_item_touched ||
	(fetchmail_item["server"]:"" != val);
    fetchmail_item = add (fetchmail_item, "server", val);
}

// also used for smtp_auth server
define boolean Validate_fm_server (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    if (!Hostname::CheckDomain (val))
    {
	UI::SetFocus (`id (id));
	// Translators: error popup
	string msg = _("The host name is incorrect");
	Popup::Error (msg);
	return false;
    }
    return true;
}

define string Get_fm_protocol () ``{
    return fetchmail_item["protocol"]:"AUTO";
}

define void Set_fm_protocol (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    fetchmail_item_touched = fetchmail_item_touched ||
	(fetchmail_item["protocol"]:"" != val);
    fetchmail_item = add (fetchmail_item, "protocol", val);
}

define string Get_fm_remote_user () ``{
    return fetchmail_item["remote_user"]:"";
}

define void Set_fm_remote_user (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    fetchmail_item_touched = fetchmail_item_touched ||
	(fetchmail_item["remote_user"]:"" != val);
    fetchmail_item = add (fetchmail_item, "remote_user", val);
}

// also used for smtp_auth user
define boolean Validate_fm_remote_user (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    if (val == "")
    {
	UI::SetFocus (`id (id));
	// Translators: error popup
	Popup::Error (_("The user name format is incorrect."));
	return false;
    }
    return true;
}

define string Get_fm_password () ``{
    return fetchmail_item["password"]:"";
}

define void Set_fm_password (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    fetchmail_item_touched = fetchmail_item_touched ||
	(fetchmail_item["password"]:"" != val);
    fetchmail_item = add (fetchmail_item, "password", val);
}


define string Get_fm_local_user () ``{
    return fetchmail_item["local_user"]:"";
}

define void Set_fm_local_user (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    fetchmail_item_touched = fetchmail_item_touched ||
	(fetchmail_item["local_user"]:"" != val);
    fetchmail_item = add (fetchmail_item, "local_user", val);
}

define boolean Validate_fm_local_user (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    if (!check_mail_local_part (val))
    {
	// it may be ok if it is directed to an alias
	UI::SetFocus (`id (id));
	// Translators: error popup
	Popup::Error (_("The user name format is incorrect."));
	return false;
    }
    return true;
}

define string Get_root_alias () ``{
    return MailAliases::root_alias;
}

define void Set_root_alias (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    Mail::Touch (MailAliases::root_alias != val);
    MailAliases::root_alias = val;
}

define boolean Validate_root_alias (symbol id) ``{
    string val = (string) UI::QueryWidget (`id (id), `Value);
    // user@machine, \\root - too much variation, don't check yet
    if (false)
    {
	UI::SetFocus (`id (id));
	// Translators: error popup
	Popup::Error (_("The user name format is incorrect."));
	return false;
    }
    return true;
}

define symbol Get_delivery_mode () ``{
    map scr2ui = $[
	`local: `dm_local,
	`procmail: `dm_procmail,
	`cyrus: `dm_cyrus,
	];
    symbol val = scr2ui[Mail::postfix_mda]:`dm_local;
    return val;
}

define void Set_delivery_mode (symbol id) ``{
    symbol val = (symbol) UI::QueryWidget (`id (id), `Value);
    map ui2scr = $[
	`dm_local: `local,
	`dm_procmail: `procmail,
	`dm_cyrus: `cyrus,
	];
    val = ui2scr[val]:`local;
    Mail::Touch (Mail::postfix_mda != val);
    Mail::postfix_mda = val;
}

define boolean Validate_delivery_mode (symbol id) ``{
    symbol val = (symbol) UI::QueryWidget (`id (id), `Value);
    // Procmail is only OK if root has an alias
    // Because postfix runs procmail as nobody instead of root
    // and the mail would end up in the wrong place
    boolean ok = true;

    // the root alias widget should be in the same dialog!
    symbol ra_id = `root_alias;
    if (!UI::WidgetExists (`id (ra_id)))
    {
	y2error ("Widget %1 not found, skipping validation of %2", ra_id, id);
    }
    else
    {
	string ra_val = (string) UI::QueryWidget (`id (ra_id), `Value);
	if (ra_val == "" && val == `dm_procmail)
	{
	    ok = false;
	}
    }

    if (!ok)
    {
	UI::SetFocus (`id (id));
	// Translators: error popup
	// Validation
	Popup::Error (_("Cannot use procmail when root's mail is not forwarded."));
	return false;
    }
    return true;
}

define list Choices_protocol () ``{
    return Mail::protocol_choices;
}

define list Choices_local_user () ``{
    return GetLocalUsers ();
}

define list Choices_delivery_mode () ``{

    return [
	    // combo box choice:
	    // deliver mail normally
	    `item (`id (`dm_local), _("Directly")),
	    // combo box choice:
	    // deliver mail through procmail
	    `item (`id (`dm_procmail), _("Through procmail")),
	    // combo box choice:
	    // deliver mail to cyrus-imapd using LMTP
	    `item (`id (`dm_cyrus), _("To Cyrus IMAP Server")),
	    // TODO: should check whether cyrus-imapd is installed.
	    // And show the choice only if it is.
	    // But SuSEconfig.postfix falls back to local if it's not, so OK
    ];
}

/**
 * @ref widget_def
 */
map Widgets = $[
    `foo: $[
	"widget": `TextEntry (),
	"opt": `opt (`notify), // optional
	"label": "",
	// if there are choices, they are used to construct the widget,
	// otherwise get is used
	"choices": [1, 2, 3],
	// just a template, do not translate
	"help": _("."),
	"get": Get_foo,
	"set": Set_foo,
	"validate": Validate_foo,
	],
    `outgoing_mail_server: $[
	"widget": `TextEntry (),
	// Translators: text entry label
	"label": _("&Outgoing mail server"),
	// help text
	"help": _("
<p>The outgoing mail server is generally intended for dial-up connections.
Enter the Internet service provider's SMTP server, such as
<b>smtp.provider.com</b>.</p>
"),
	"get": Get_outgoing_mail_server,
	"set": Set_outgoing_mail_server,
	"validate": Validate_outgoing_mail_server,
	],
    `from_header: $[
	"widget": `TextEntry (),
	// Translators: text entry label
	"label": _("Do&main for the 'From' header"),
	// help text
	"help": _("
<p>You may want the mail you sent to appear as if it originated from
<b>company.com</b> instead of <b>pc-042.company.com</b>.
Use the text box provided or a more detailed dialog.</p>
"),
	"get": Get_from_header,
	"set": Set_from_header,
	"validate": Validate_from_header,
	],
    `local_domains: $[
	"widget": `TextEntry (),
	// Translators: text entry label
	"label": _("&Domains for locally delivered mail"),
	// help text
	"help": _("
<p>Here, specify the domains for which the mail
will be delivered locally. If you enter nothing,
the local host name is assumed.</p>
"),
	"get": Get_local_domains,
	"set": Set_local_domains,
	"validate": Validate_local_domains,
	],
    `listen_remote: $[
	"widget": `CheckBox (),
	// check box label
	"label": _("Accept remote &SMTP connections"),
	// help text
	"help": _("
<p>Mail can be received directly via the SMTP protocol
or it can be downloaded from
a POP or an IMAP server using <b>fetchmail</b>.</p>"),
	"get": Get_listen_remote,
	"set": Set_listen_remote,
	],
    `use_amavis: $[
	"widget": `CheckBox (),
	// checkbox label
	"label": _("&Enable virus scanning (AMaViS)"),
	// help text
	"help": _("
<p>Enabling virus scanning checks incoming and outgoing mail
with AMaViS.</p>
")
	// help text
+ _("
<p>If AMaViS is not installed and you want to use it, it will be installed
automatically.</p>
"),
	"get": Get_use_amavis,
	"set": Set_use_amavis,
	],
    `fm_server: $[
	"widget": `TextEntry (),
	// Translators: text entry label
	"label": _("&Server"),
	"help": "",
	"get": Get_fm_server,
	"set": Set_fm_server,
	"validate": Validate_fm_server,
	],
    `fm_protocol: $[
	"widget": `ComboBox (),
	"opt": `opt (`hstretch),
	// Translators: combo box label
	"label": _("&Protocol"),
	"choices": Choices_protocol,
	"help": "",
	"get": Get_fm_protocol,
	"set": Set_fm_protocol,
	],
    `fm_remote_user: $[
	"widget": `TextEntry (),
	// Translators: text entry label
	"label": _("&Remote user name"),
	"help": "",
	"get": Get_fm_remote_user,
	"set": Set_fm_remote_user,
	"validate": Validate_fm_remote_user,
	],
    `fm_password: $[
	"widget": `Password (),
	// Translators: text entry label
	"label": _("P&assword"),
	"help": "",
	"get": Get_fm_password,
	"set": Set_fm_password,
	],
    `fm_local_user: $[
	"widget": `ComboBox (),
	// editable because entering a mail alias makes sense too
	// and we miss the nis users
	"opt": `opt (`hstretch, `editable),
	// Translators: combo box label
	"label": _("&Local user"),
	"choices": Choices_local_user,
	"help": "",
	"get": Get_fm_local_user,
	"set": Set_fm_local_user,
	"validate": Validate_fm_local_user,
	],
    `root_alias: $[
	"widget": `TextEntry (),
	// Translators: text entry label
	"label": _("&Forward root's mail to"),
	// help text
	"help": _("<p>It is recommended to have a regular user account
for the system administrator and redirect root's mail to this account.</p>"),
	"get": Get_root_alias,
	"set": Set_root_alias,
	"validate": Validate_root_alias,
	],
    `delivery_mode: $[
	"widget": `ComboBox (),
	"opt": `opt (`hstretch),
	// Translators: combo box label
	// /etc/sysconfig/postfix: POSTFIX_MDA
	"label": _("&Delivery Mode"),
	"choices": Choices_delivery_mode,
	// help text
	"help": _("<p>The <b>delivery mode</b> is usually <b>procmail</b>, unless you do not forward root's mail or want to access the mail via IMAP.</p>"),
	"get": Get_delivery_mode,
	"set": Set_delivery_mode,
	"validate": Validate_delivery_mode,
	],
    ];


}
