/**
 *
 * File:
 *   securenets.ycp
 *
 * Module:
 *   Network/YPServer
 *
 * Summary:
 *   YPServer module.
 *
 * Authors:
 *   Dan Vesely <dan@suse.cz>
 *   Martin Vidner <mvidner@suse.cz>
 *
 * $Id: securenets.ycp 20204 2004-11-05 09:19:26Z jsuchome $
 *
 * YPServer module part.
 *
 */


{

    textdomain "nis_server";

    import "NisServer";
    import "Wizard";
    import "Label";
    import "Popup";
    import "IP";

    /**
     * Creates items for table from var_yp_securenets.scr any agent
     * @param nets list of output from securenets agent
     *		<br>$["netmask": "255.0.0.0", "network": "10.0.0.0"]
     * @return a list of items formated for a UI table
     */
    define list<term> ItemizeSecurenets (list<map> nets) {
	list<map> not_comment = filter (map e, nets, ``(
	    haskey (e, "netmask") || haskey (e, "network")));
	list<term> result = [];
	integer i = 0;
	foreach (map element, not_comment, {
	    result = add (result,
		`item (`id (i), element["netmask"]:"", element["network"]:""));
	    i = i + 1;
	});
	return result;
    }

    /**
     * Merge edited entries with the original entries with comments
     * @param orig list of original entries (with comments)
     * @param edit list with edited entries (as placed in the table)
     * @return list with merged entries
     */
    define list<map> MergeNetsEntries (list<map> orig, list<term> edit) ``{

	list<map> edit_maps = maplist (term e, edit, ``(
				      $["netmask" : e[1]:"",
					"network" : e[2]:""]
	));


	list<map> result = filter (map e, orig, ``(haskey (e, "hash") ||
					   haskey (e, "comment") ||
					   contains (edit_maps, e)));
	edit_maps = filter (map e, edit_maps, ``(!contains (result, e)));
	result = result + edit_maps;

	return result;
    }

    /**
     * Popup dialog for editing netmask/network
     * @param id id of item
     * @param netmask netmask
     * @param network network
     * @return a new item or nil on cancel
     */
    define term NetsEditPopup (integer id, string netmask, string network) ``{

	term buttons  = `HBox ();
	buttons = add (buttons, `PushButton (`id (`ok), `opt (`default, `key_F10), Label::OKButton()));
	buttons = add (buttons, `PushButton (`id (`cancel), `opt (`key_F9), Label::CancelButton()));

	term contents = `VBox ();
	contents = add (contents, `VSpacing (0.3));
			       // To translators: popup dialog heading
	contents = add (contents, `Heading (_("Edit netmask and network")));
	contents = add (contents, `VSpacing (0.5));
				// To translators: textentry label
	contents = add (contents, `TextEntry (`id(`netmask), _("Net&mask"), netmask));
	contents = add (contents, `VSpacing (0.3));
				// To translators: textentry label
	contents = add (contents, `TextEntry (`id(`network), _("Net&work"), network));
	contents = add (contents, `VSpacing (0.5));
	contents = add (contents, buttons);
	contents = add (contents, `VSpacing (0.3));
	contents = `HBox (`HSpacing (), contents, `HSpacing ());

	UI::OpenDialog (contents);
	UI::SetFocus (`id (`netmask));

	symbol ui = nil;
	string error_msg = "";

	repeat {
	    error_msg = "";
	    ui = (symbol) UI::UserInput ();

	    if (ui == `ok)
	    {
		netmask = (string) UI::QueryWidget (`id (`netmask), `Value);
		network = (string) UI::QueryWidget (`id (`network), `Value);
		// explicitly allow 0.0.0.0
		if (netmask != "0.0.0.0" && !IP::Check4(netmask))
		{
		    // To translators: error message
		    error_msg = error_msg + _("Wrong netmask!\n");
		}
				// To translators: error message
		error_msg = error_msg + (IP::Check4(network) ? "" : _("Wrong network!\n"));

		if (size (error_msg) > 0)
		{
		    Popup::Error (error_msg);
		}
	    }

	} until ((error_msg == "" && ui == `ok) || ui == `cancel);

	UI::CloseDialog ();

	return ui == `ok ? `item (`id (id), netmask, network) : nil;
    }

    /**
     * Securenets dialog
     * @return `back, `next or `abort
     */
    define symbol QueryHosts () ``{

	// help text 1/4
	string helptext = _("<p>Please enter which hosts are allowed to query the NIS server.</p>");
	// help text 2/4
	helptext = helptext + _("<p>A host address will be allowed if <b>network</b> is equal
to the  bitwise <i>AND</i> of the host's address and the <b>netmask</b>.</p>");
	// help text 3/4
	helptext = helptext + _("<p>The entry with <b>netmask</b> <tt>255.0.0.0</tt> and <b>network</b>
<tt>127.0.0.0</tt> must exist to allow connections from the local host.</p>
");
	// help text 4/4
	helptext = helptext + _("<p>Entering <b>netmask</b> <tt>0.0.0.0</tt> and
<b>network</b> <tt>0.0.0.0</tt> gives access to all hosts.</p>");

	list<term> allow_query = ItemizeSecurenets (NisServer::securenets);
	integer n_items = size (allow_query);

	term buttons = `HBox ();
				// To translators: pushbutton label
	buttons = add (buttons, `PushButton (`id (`add), `opt (`key_F3), _("A&dd")));
				// To translators: pushbutton label
	buttons = add (buttons, `PushButton (`id (`edit), `opt (`key_F4), _("&Edit")));
				// To translators: pushbutton label
	buttons = add (buttons, `PushButton (`id (`delete), `opt (`key_F5), _("De&lete")));

	term contents = `VBox ();
	contents = add (contents, `Table (`id (`table), `opt (`notify, `immediate),
					  `header (
					      // To translators: table headers
					      _("Netmask"),
					      // To translators: table headers
					      _("Network")),
					  allow_query));
	contents = add (contents, buttons);


				// To translators: dialog label
	Wizard::SetContents (_("NIS Server Query Hosts Setup"), contents, helptext, true, true);
	Wizard::SetNextButton(`next, Label::FinishButton() );

	symbol ui = nil;

	repeat
	{
	    boolean anyitems = UI::QueryWidget (`id (`table), `CurrentItem) != nil;
	    UI::ChangeWidget (`id (`edit), `Enabled, anyitems);
	    UI::ChangeWidget (`id (`delete), `Enabled, anyitems);

	    // Kludge, because a `Table still does not have a shortcut. #16116
	    UI::SetFocus (`id (`table));

	    ui = (symbol) UI::UserInput ();
	    if (ui == `cancel)
	    {
		ui = `abort;
	    }

	    if (ui == `delete)
	    {
		integer id = (integer) UI::QueryWidget (`id (`table), `CurrentItem);
		allow_query = filter(term e, allow_query, ``(id != e[0, 0]:-1));
		UI::ChangeWidget(`id(`table), `Items, allow_query);
	    }

	    else if (ui == `edit)
	    {
		integer id = (integer) UI::QueryWidget (`id (`table), `CurrentItem);
		term item  = find (term e, allow_query, ``(id == e[0, 0]:-1));
		item = NetsEditPopup (id, item[1]:"", item[2]:"");
		if (item != nil)
		{
		    allow_query = maplist (term e, allow_query, ``{
			return (e[0, 0]:-1 == id) ? item : e;
		    });
		    UI::ChangeWidget (`id (`table), `Items, allow_query);
		}
	    }

	    else if (ui == `add)
	    {
		term new_item = NetsEditPopup (n_items, "", "");
		if (new_item != nil)
		{
		    n_items = n_items + 1;
		    allow_query = add (allow_query, new_item);
		    UI::ChangeWidget (`id (`table), `Items, allow_query);
		}
	    }

	    if (ui == `abort && !Popup::ReallyAbort (true)) ui = `again;
	}
	until (contains ([`back, `next, `abort], ui));

	if (ui == `back) Wizard::RestoreNextButton();

	// and finally merge
	NisServer::securenets = MergeNetsEntries (NisServer::securenets, allow_query);

	return ui;
    }

}
