/**
 * File:
 *   routines.ycp
 *
 * Module:
 *   Configuration of nfs
 *
 * Summary:
 *   Network NFS routines
 *
 * Authors:
 *   Jan Holesovsky <kendy@suse.cz>
 *   Dan Vesely <dan@suse.cz>
 *
 * $Id: routines.ycp 20765 2005-01-14 09:18:07Z jsuchome $
 *
 * Network NFS routines
 *
 */

{
    textdomain "nfs";

    import "Package";
    import "Report";

    /**
     * @param spec	"server:/path/specification"
     * @return		`couple("server", "/path/specification")
     */
    define term SpecToServPath(string spec) ``{
	integer colonpos = findfirstof(spec, ":");
	string serv = "";
	if (colonpos != nil) {
	    serv = substring(spec, 0, colonpos);
	    spec = substring(spec, colonpos+1);
	}
	return `couple(serv, spec);
    }


    /**
     * Creates a list of ui table items for nfs fstab entries
     * @param fstab	list of nfs fstab entries
     * @return		itemized table entries
     * @example UI::ChangeWidget(`id(`fstable), `Items, FstabTableItems(nfs_entries));
     */
    define list<term> FstabTableItems(list<map> fstab) ``{
	integer count = 0;
	return maplist(map entry, fstab, ``{
	    term sp = SpecToServPath(entry["spec"]:"");
	    term it = `item(`id(count),
			    sp[0]:"" + " ",
			    sp[1]:"" + " ",
			    entry["file"]:"" + " ",
			    entry["mntops"]:"" + " ");

	    count = count+1;
	    return it;
	});
    }

    /**
     * Check for the validity of a hostname: nonempty, shorter than 50 chars,
     * [-A-Za-z._]. If invalid, a message is displayed.
     * @param name	a hostname
     * @return		whether valid
     */
    define boolean CheckHostName(string name) ``{
	if (size(name) > 0 &&
	    size(name) < 50 &&
	    name == filterchars(name,
				"-_.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) {
	    return true;
	} else
	    // error popup message
	    Report::Error (sformat(_("You entered a wrong host name. It must be
shorter than 50 characters and you can use
just 0..9, A..Z, a..z, dots, - and _.")));
	return false;
    };

    /**
     * Check if a mountpoint is in the fstab. If yes, display a message.
     * @param fstab	in .etc.fstab format (must contain the key "file")
     * @param mpoint	mount point
     * @return		is it there?
     */
    define boolean IsMpInFstab(list<map> fstab, string mpoint) ``{
	list tmp = filter(map fse, fstab, ``{
	    return (fse["file"]:"" == mpoint);
	});

	if (size(tmp) == 0)
	    return false;
	else
	    // error popup message
	    Report::Error (sformat(_("The fstab already contains an entry
with mount-point '%1'."), mpoint));
	return true;
    };

    /**
     * Check for the validity of a path/mountpoint:
     * nonempty, fewer than 70 chars, starts with a slash.
     * If invalid, a message is displayed.
     * @param name	path
     * @return		whether valid
     */
    define boolean CheckPath(string name) ``{
	if (size(name) > 0 &&
	    size(name) < 70 &&
	    substring(name, 0, 1) == "/")
	{
	    return true;
	}

	// error popup message (spaces are now allowed)
	Report::Error (sformat(_("You entered a wrong path.
It must be shorter than 70 characters
and it must begin with a slash (/).")));
	return false;
    };

    /**
     * Checks the nfs options for /etc/fstab:
     * nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5))
     * @param options	options
     * @return		a translated string with error message, emtpy string if ok
     */
    define string check_options (string options) ``{

	// To translators: error popup
	if (size (options) == 0)   return _("Empty options string not allowed!");
	if (options == "defaults") return "";


	list<string> option_list = splitstring (options, ",");
	// these can be negated by "no"
	list<string> non_value   = ["bg", "fg", "soft", "hard", "intr", "posix", "cto", "ac",
			    "lock", "tcp", "udp",
			    // these are common for all fs types
			    "atime", "auto", "dev", "exec", "suid", "user"];
	// these cannot be negated
	list non_value1 = ["defaults", "async", "sync", "ro", "rw"];
	list with_value  = ["rsize", "wsize", "timeo", "retrans", "acregmin", "acregmax",
			    "acdirmin", "acdirmin", "acdirmax", "actimeo", "retry", "namlen",
			    "port", "mountport", "mountport", "mounthost", "mountprog",
			    "mountvers", "nfsprog", "nfsvers"];
	integer i = 0;
	string current_option = "";

	// first fiter out non value options and its nooptions forms (see nfs(5))
	option_list = filter (string e, option_list, ``(!contains (non_value, e)));
	non_value   = maplist (string e, non_value, ``(sformat ("no%1", e)));
	option_list = filter (string e, option_list, ``(!contains (non_value, e)));
	option_list = filter (string e, option_list, ``(!contains (non_value1, e)));

	while (i < size (option_list))
	{
	    string opt = option_list[i]:"";
	    list<string> value = splitstring (opt, "=");
	    string v0 = value[0]:"";
	    string v1 = value[1]:"";
	    // To translators: error popup
	    if (!contains (with_value, v0)) return sformat (_("Wrong option: %1"), v0);
	    // To translators: error popup
	    if (size (value) != 2) return sformat (_("Wrong option format: %1"), opt);
	    // To translators: error popup
	    if (v1 == "") return sformat (_("Empty value for option: %1"), v0);
	    i = i + 1;
	}

	return "";
    }

    /**
     * Strips a superfluous slash off the end of a pathname.
     * @param	p	pathname
     * @return		stripped pathname
     */
    define string StripExtraSlash (string p) ``{
	if (regexpmatch (p, "^.+/$"))
	{
	    return regexpsub (p, "^(.+)/$", "\\1");
	}
	else
	{
	    return p;
	}
    }

    /**
     * Check whether pormap is installed, ask user to install it if it is missing
     * @return boolean true if portmap is installed
     */
    define boolean IsPortmapInstalled() ``{
	return Package::Install ("portmap");
    }
}
