ACC SHELL

Path : /usr/share/YaST2/include/samba-client/
File Upload :
Current File : //usr/share/YaST2/include/samba-client/routines.ycp

/**
 * File:	include/samba-client/routines.ycp
 * Package:	Configuration of samba-client
 * Summary:	Miscelanous functions for configuration of samba-client.
 * Authors:	Stanislav Visnovsky <visnov@suse.cz>
 *
 * $Id: routines.ycp 60041 2009-12-10 12:59:56Z jsuchome $
 */

{

textdomain "samba-client";

import "FileUtils";
import "Mode";
import "Label";
import "Stage";
import "Popup";
import "Service";
import "String";

import "Samba";
import "SambaConfig";
import "SambaNetJoin";
import "SambaNmbLookup";
import "SambaAD";


/**
 * Allow user to type in a user/password pair in a popup.
 *
 * @param message	a text to be displayed above the password text entry
 * @param defaultuser	a pre-filled user name
 * @return map<string, string>		$["user": string, "password": string] with information
 *			provided by the user or nil on cancel
 */
map<string, string> passwordUserPopup (string message, string defaultuser, string domain, symbol what)
{
    term machine_term	= `Empty ();
    string default_id	= "default_entry";
    // default value of Machine Account
    term default_entry= `item (`id (default_id), _("(default)"));
    if (SambaAD::ADS () != "" && what != `leave)
    {
	list machines	= [ default_entry ];
	machine_term	= `HBox (
	    `ReplacePoint (`id (`rpcombo),
		`Left (`ComboBox (`id (`machines), `opt (`hstretch),
		    // combo box label
		    _("&Machine Account OU"), machines)
		)
	    ),
	    `VBox (
		`Label (""),
		`PushButton (`id (`acquire), _("O&btain list"))
	    )
	);
    }
    UI::OpenDialog (`opt (`decorated), `HBox (`HSpacing (0.7), `VBox (
	`HSpacing (25),
	`VSpacing (0.2),
	`Left (`Label (message)),
	// text entry label
	`InputField (`id (`user), `opt (`hstretch), _("&Username"),defaultuser),
	`Password (`id(`passwd), `opt (`hstretch), Label::Password()),
	machine_term,
	`VSpacing (0.2),
	`HBox (
	    `PushButton(`id(`ok), `opt(`default), Label::OKButton()),
	    `PushButton(`id(`cancel), Label::CancelButton())
	),
	`VSpacing (0.2)
    ), `HSpacing (0.7)));

    if (SambaAD::ADS () != ""  && what != `leave)
    {
	UI::ChangeWidget (`id (`machines), `Enabled, false);
    }
    UI::SetFocus (`id (`passwd));
    any ret	= nil;
    string user	= "";
    string pass	= "";
    while (true)
    {
	ret	= UI::UserInput();
	user	= (string)UI::QueryWidget(`id(`user), `Value);
	pass	= (string)UI::QueryWidget(`id(`passwd), `Value);

	if (ret == `ok || ret == `cancel)
	    break;
	if (ret == `acquire)
	{
	    if (user == "" || pass == "")
	    {
		// error popup
		Popup::Error (_("User name and password are required
for listing the machine accounts."));
		continue;
	    }
	    list<string> machines = SambaAD::GetMachines (domain, user, pass);
	    if (machines != nil)
	    {
		list items	= maplist (string m, sort (machines), ``(
		    `item (`id (m), m)));
		items		= prepend (items, default_entry);
		UI::ReplaceWidget (`id (`rpcombo), `Left (
		    `ComboBox (`id (`machines), `opt (`hstretch),
		    _("&Machine Account"), items)
		));
		UI::ChangeWidget (`id (`machines), `Enabled, true);
	    }
	}
    }

    map<string, string> result = (ret == `ok) ? $[
	"user"		: user,
	"password"	: pass
    ] : nil;
    if (SambaAD::ADS () != "" && ret == `ok)
    {
	string machine	= (string)UI::QueryWidget (`id (`machines), `Value);
	if (machine != default_id)
	    result["machine"]	= machine;
    }
    UI::CloseDialog();

    return result;
}

/**
 * If modified, ask for confirmation
 * @return true if abort is confirmed
 */
define boolean ReallyAbort() ``{
    return (Stage::cont() && !contains (WFM::Args (), "from_users")) ?
	Popup::ConfirmAbort (`incomplete) :
	(!Samba::GetModified() || Popup::ReallyAbort(true));
}

/**
 * Check, if the workgroup is a domain or a workgroup. Uses caching to avoid long checks of a workgroup members.
 *
 * @param workgroup	the workgroup to be checked
 * @return symbol	type of the workgroup: `joined_domain, `not_joined_domain, `workgroup or `domain if 
 * 			it is a domain, but the status is not known
 */
define symbol CheckWorkgroup( string workgroup ) ``{

    // for autoyast, skip testing
    if( Mode::config() ) return `workgroup;

    symbol ret = nil;

    // translators: text for busy pop-up
    Popup::ShowFeedback ("", _("Verifying workgroup membership..."));

    if (SambaNmbLookup::IsDomain(workgroup) || SambaAD::ADS () != "") {

	// handle domain joining
	boolean res = SambaNetJoin::Test(workgroup);
	// we the host is already in domain, continue
	if( res == true ) ret = `joined_domain;
	else if( res != nil ) ret = `not_joined_domain;
	else ret = `domain;
    } else {
	ret = `workgroup;
    }
    Popup::ClearFeedback ();
    y2debug( "Check workgroup result: %1", ret );
    return ret;
}

/**
 * Leave an AD domain
 */
define symbol LeaveDomain (string workgroup)
{
    // popup to fill in the domain leaving info; %1 is the domain name
    map<string, string> passwd = passwordUserPopup (sformat(_("Enter the username and the password for leaving the domain %1."), workgroup),
	"Administrator", workgroup, `leave);

    // cancelled the domain leaving
    if( passwd == nil ) return `fail;
    // try to join the domain
    string error = SambaNetJoin::Leave (
	workgroup, passwd["user"]:nil, passwd["password"]:""
    );

    if (error != nil) {
	Popup::Error(error);
	return `fail;
    }
    return `ok;
}

define symbol JoinDomain(string workgroup)
{
    // popup to fill in the domain joining info; %1 is the domain name
    map<string, string> passwd = passwordUserPopup(sformat(_("Enter the username and the password for joining the domain %1."), workgroup)
	+ "\n\n"
	+ _("To join the domain anonymously, leave the text entries empty.") + "\n", "Administrator", workgroup, `join);

    // cancelled the domain joining
    if( passwd == nil ) return `fail;
    // try to join the domain
    string error = SambaNetJoin::Join (
	workgroup, "member",
	passwd["user"]:nil, passwd["password"]:"", passwd["machine"]:nil);

    if (error != nil) {
	Popup::Error(error);
	return `fail;
    }
    // Translators: Information popup, %1 is the name of the domain
    Popup::Message(sformat(_("Domain %1 joined successfully."), Samba::GetWorkgroup()));
    return `ok;
}


/**
 * Allow to join a domain. Uses result of @ref CheckWorkgroup to inform the user about the status.
 *
 * @param workgroup	the workgroup to be joined
 * @param status	domain status returned by CheckWorkgroup
 * @return symbol		`ok on successful join (workgroup is always successful),
 *			`fail on error or user cancel
 *			`nojoin if user don't want to join
 */
define symbol AskJoinDomain( string workgroup, symbol status ) ``{

    // for autoyast, skip testing
    if( Mode::config() ) return `ok;
    
    if( status == `workgroup || status == `joined_domain ) return `ok;
    
    boolean res = false;
    
    // allow to join the domain
    if( status == `domain ) {	
    	    // we don't know the domain status
	    
	    // translators: popup question, the domain status cannot be found out, ask user what to do
	    // %1 is the domain name
	    res = Popup::YesNo(sformat(_("Cannot automatically determine if this host\nis a member of the domain %1."), workgroup)
		+ "\n\n" + sformat(_("Join the domain %1?"), workgroup) + "\n");
    } else if( status == `not_joined_domain ) {
	// translators: popup question, The workgroup is a domain in fact and the machine is not a member, ask user what to do.
	// %1 is the domain name
	res = Popup::YesNo(sformat(_("This host is not a member\nof the domain %1."), workgroup)
	    + "\n\n" + sformat(_("Join the domain %1?"), workgroup) + "\n");
    }

    if (!res) {
	return `nojoin;
    }
    return JoinDomain(workgroup);
}


/**
 * Check if user shares already exist
 * @param path to directory with shares
 */
define boolean SharesExist (string share_dir) {

    if (!FileUtils::Exists (share_dir))
	return false;
    map out = (map) SCR::Execute (.target.bash_output, sformat ("/usr/bin/find %1 -type f | wc -l", share_dir));
    integer count = tointeger (String::FirstChunk (out["stdout"]:"0", "\n"));
    return (count != nil && count > 0);
}

/**
 * ask user if existing shares should be removed
 * @return true for removing
 */
define boolean AskForSharesRemoval () {

    return !Popup::AnyQuestion (Popup::NoHeadline(),
	    // popup question
	    _("User shares already exist.  Keep or delete these shares?"),
	    // button label
	    _("&Keep"),
	    // button label
	    _("&Delete"),
	    `focus_yes
    );
    // FIXME details
}

/**
 * check if services should be stopped: only if there are more sections in
 * smb.conf and if user confirms (bug #143908)
 * @return true if smb+nmb should be stopped
 */
define boolean AskToStopServices () {

    if (Service::Status("nmb") != 0 && Service::Status("smb") != 0)
	return false;

    if (size (SambaConfig::GetShares()) < 1)
	return true;

    // yes/no popup
    return Popup::YesNo (_("Other Windows sharing services are available. Stop them as well?"));
}

/**
 * return the term with hosts resolution support check box (fate#300971)
 * @param hosts_resolution current value of hosts resolution in nsswitch.conf
 */
term HostsResolutionTerm (boolean hosts_resolution) {

    // check box label
    return `Left (`CheckBox (`id (`hosts_resolution),
	_("&Use WINS for Hostname Resolution"), hosts_resolution));
}

/**
 * Return help text for hosts resolution term
 */
string HostsResolutionHelp () {

    // help text for "Use WINS for Hostname Resolution" check box label
    return _("<p>If you want to use Microsoft Windows Internet Name Service (WINS) for name resolution, check <b>Use WINS for Hostname Resolution</b>.</p>");
}

/**
 * return the term with DHCP support check box
 * @param dhcp_support current value of DHCP support in smb.conf
 */
define term DHCPSupportTerm (boolean dhcp_support) {

    // check box label
    return `Left (`CheckBox (`id (`dhcp), _("Retrieve WINS server via &DHCP"), dhcp_support));
}

/**
 * return the help text for DHCP support
 */
define string DHCPSupportHelp () {

    // help text ("Retrieve WINS server via DHCP" is a checkbox label)
    return _("<p>Check <b>Retrieve WINS server via DHCP</b> to use a WINS server provided by DHCP.</p>");
}

/**
 * return the term with shares settings
 * @param settings map with parameters to show in term
 */
define term SharesTerm (map settings) {

    boolean allow	= settings["allow_share"]:false;
    string group	= settings["group"]:settings["shares_group"]:"";
    integer max		= settings["max_shares"]:100;
    boolean guest	= settings["guest_access"]:false;

    // frame label
    string label	= true ? _("Sharing by Users") :
	// frame label
	_("Sharing");
    return `VBox (
	`VSpacing (0.4),
	// frame label
	`Frame (label, `VBox (
	    `VSpacing (0.4),
	    `Left (`CheckBox(`id(`share_ch), `opt(`notify),
		// checkbox label
		_("&Allow Users to Share Their Directories"), allow)
	    ),
	    haskey (settings, "guest_access") ?
		`Left (`CheckBox(`id(`guest_ch), `opt(`notify),
		    // checkbox label
		    _("Allow &Guest Access"), guest))
		: `VSpacing (0),
	    `HBox (`HSpacing (2), `VBox (
		// texty entry label
		`InputField (`id(`group), `opt(`hstretch),_("&Permitted Group"),
		    group),
		// infield label
		`IntField (`id(`max_shares),_("&Maximum Number of Shares"),
		    1, 99999, max)
	    )),
	    `VSpacing (0.2)
	))
    );
}

/**
 * return the term with shares settings
 * @param allow if shares are allowed
 * @param group name of group owning the shares dir
 * @param max maximum number of allowed shares
 */
define term GetSharesTerm (boolean allow, string group, integer max) {
y2warning ("GetSharesTerm is obsolete, use SharesTerm instead");
    return SharesTerm ($[
	    "allow_share"	: allow,
	    "shares_group"	: group,
	    "max_shares"	: max
    ]);
}

/**
 * return the help text for shares
 */
define string SharesHelp () {

    return

    // membership dialog help (common part 3/4), %1 is separator (e.g. '\')
    sformat (_("<p><b>Allow Users to Share Their Directories</b> enables members of the group in <b>Permitted Group</b> to share directories they own with other users. For example, <tt>users</tt> for a local scope or <tt>DOMAIN%1Users</tt> for a domain scope.  The user also must make sure that the file system permissions allow access.</p>"), Samba::shares_separator) +

    // membership dialog help (common part 3/4)
    _("<p>With <b>Maximum Number of Shares</b>, limit the total amount of shares that may be created.</p>") +

    // membership dialog help common part
    _("<p>To permit access to user shares without authentication, enable <b>Allow Guest Access</b>.</p>");
}

/**
 * return the help text for PAM Mount table
 */
string PAMMountHelp () {

    // help text for PAM Mount table
    return _("<p>In the table <b>Mount Server Directories</b>, you can specify server directories (such as home directory) which should be localy mounted when the user is logged in. If mounting should be user-specific, specify <b>User Name</b> for selected rule. Otherwise, the directory is mounted for each user. For more information, see pam_mount.conf manual page.</p>") +

    // help text for PAM Mount table: example
    _("<p>For example, you may use <tt>/home/%(DOMAIN_USER)</tt> value for <b>Remote Path</b>, <tt>~/</tt> value for <b>Local Mount Point</b> to mount the home directory, together with a value <tt>user=%(DOMAIN_USER)</tt> as a part of <b>Options</b>.</p>");
}

/* EOF */
}

ACC SHELL 2018