/**
 * File:	clients/inst_root.ycp
 * Package:	Configuration of users and groups
 * Summary:
 * Displays two input fields to get the root password from the user.
 * Plausibility checks executed:
 *
 *   - password must be given
 *   - first and second entry must match
 *   - length of password >= 5, and <= maximum for current encryption
 *   - only certain characters allowed
 *
 * After all the password is crypted and written into the user_settings.
 *
 * Authors:     Klaus Kämpf <kkaempf@suse.de>
 *
 * $Id: inst_root.ycp 21038 2005-01-28 13:37:38Z jsuchome $
 */
{
textdomain "users";

import "Label";
import "Linuxrc";
import "Mode";
import "Popup";
import "Report";
import "Security"; // Perl module (Users.pm) donesn't call constructor...
import "Stage";
import "Users";
import "UsersCache";
import "Wizard";
import "GetInstArgs";

include "users/widgets.ycp";   // for EncryptionPopup()

    string valid_password_chars = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*() ,;:._+/|?{}=[]";

    if (Stage::cont () && ! Linuxrc::usessh ())
    {
        // what is this for??
        SCR::Execute(.target.remove, "/var/lib/YaST2/runme_at_boot");
    }

    boolean this_is_for_real = ! Mode::test ();

    Users::ReadSystemDefaults ();
    string encryptionMethod = Users::EncryptionMethod ();

    // Title for root-password dialogue
    string title = _("Password for \"root\", the system administrator");

    term contents = `VBox(
        `VStretch(),
        `HSquash(
            `VBox(
               // advise user to remember his new password
               `Label(_("Do not forget what you enter here.")),
               `VSpacing(1),

               `Left(`Password(`id(`pw1),
                    // Label: get password for user root
                    // Please use newline if label is longer than 40 characters
                    _("&Enter a password for the root user:"), "")),
               `VSpacing(1),

               `Left(`Password(`id(`pw2),
                    // Label: get same password again for verification
                    // Please use newline if label is longer than 40 characters
                    _("Reenter the password for &verification:"), ""))
               )
             ),
        `VSpacing(3),
        // push button
        `PushButton(`id(`expert), `opt(`key_F7), _("E&xpert Options...") ),
        `VStretch()
    );

    // help text ( explain what the user "root" is and does ) 1/5
    string helptext = _("<p>
Unlike normal users of the system, who, for instance, write texts, create
graphics, or browse the Internet, the user \"root\" exists on
every system and is called into action whenever
administrative tasks need to be performed. Log in as root
when you need to be the system administrator and only then.
</p>
");

    // help text, continued 2/5
    helptext = helptext + _("<p>
Because the root user is equipped with extensive permissions, the password
for \"root\" should be chosen carefully. A combination of letters and numbers
is recommended. To ensure that the password was entered correctly,
reenter it in a second field.
</p>
");

    // help text, continued 3/5
    helptext = helptext + _("<p>
All the rules for user passwords apply to the \"root\" password:
Distinguish between uppercase and lowercase. A password should have at
least 5 characters and, as a rule, not contain any special characters
(e.g., accented letters or umlauts).
</p>
");

    // help text, continued 4/5
    helptext = helptext + _("<p>
Valid password characters are letters, digits, blanks, and
<tt>#*,.;:._-+!</tt><tt>$%&/|?{[()]}=</tt>.
</p>");

    // help text, continued 5/5
    helptext = helptext + _("<p>
Do not forget this \"root\" password!
</p>");

    Wizard::SetDesktopIcon("users");
    Wizard::SetContents (title, contents, helptext,
        GetInstArgs::enable_back(),
	GetInstArgs::enable_next());


    symbol ret = nil;

    repeat
    {
	if ( ret != `expert && ret != `abort)
	{
	    UI::SetFocus ( `id(`pw1) );
	}
	ret = (symbol) Wizard::UserInput();

	if (ret == `abort || ret == `cancel)
	{
	    if ( Popup::ConfirmAbort (`incomplete) )
		return `abort;
	    else
	    {
		ret = `notnext;
		continue;
	    }
	}

	if (ret == `expert)
	{
	    encryptionMethod = EncryptionPopup ();
	    Users::SetEncryptionMethod (encryptionMethod);

	    if ((string) UI::QueryWidget(`id(`pw1), `Value) == "")
		UI::SetFocus (`id(`pw1));
	    else
		Wizard::SetFocusToNextButton();
	}
	if (ret == `next)
	{
	    string pw1 = (string) UI::QueryWidget(`id(`pw1), `Value);
	    string pw2 = (string) UI::QueryWidget(`id(`pw2), `Value);

	    if (this_is_for_real && pw1 != pw2)
	    {
		// report misspellings of the password
		Popup::Message (_("The first and the second version
of the password don't match!
Please try again."));
		ret = `notnext;
		continue;
	    }

	    if (this_is_for_real)
	    {
		UsersCache::SetUserType ("system");
		Users::SetEncryptionMethod (encryptionMethod);
		if (pw1 == "")
		{
		    // report if user forgot to enter a password
		    Popup::Message(_("You didn't enter a password.
Please try again."));
		    ret = `notnext;
		    continue;
		}

		if (findfirstnotof (pw1, valid_password_chars) != nil)
		{
		    // popup text: invalid characters in root password
		    Popup::Message(_("The password may only contain the following characters:\n 0..9, a..z, A..Z, and any of \"#* ,.;:._-+!$%&/|\?{[()]}\".\nPlease try again."));
		    // Invalidate old password
		    UI::ChangeWidget(`id(`pw1), `Value, "");
		    UI::ChangeWidget(`id(`pw2), `Value, "");
		    ret = `notnext;
		    continue;
		}

		// map returned from CheckPasswordUI functions
		map error_map			= $[];
		// map with id's of confirmed questions
		map<string,integer> ui_map	= $[];
		boolean failed			= false;
		do
		{
		    error_map = Users::CheckPasswordUI ("root", pw1, ui_map);
		    if (error_map != $[])
		    {
			if (!Popup::YesNo (error_map ["question"]:""))
			{
			    failed = true;
			}
			else
			{
			    ui_map[ error_map["question_id"]:"" ] = 1;
			}
		    }
		} while (error_map != $[] && !failed);

		if (failed)
		{
		    ret = `notnext;
		    continue;
		}

		Users::WriteSecurity ();
		y2milestone( "encrypting with %1", encryptionMethod );

		Users::SetRootPassword (pw1);

		if (!Users::WriteRootPassword() && Popup::YesNo (
		    // Error msg (yes/no)
		    _("The root password could not be set.
You might not be able to log in.
Retry?
")))
		{
		    Users::SetRootPassword ("");
		    UI::ChangeWidget(`id(`pw1), `Value, "");
		    UI::ChangeWidget(`id(`pw2), `Value, "");
		    ret = `notnext;
		    continue;
		}
	    }
	}
    } until (ret == `next || ret == `back || ret == `abort);

    return ret;
}
