// PasswordEditor.java
// $Id: PasswordEditor.java,v 1.3 1997/01/24 11:58:52 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.contrib;

import w3c.tools.store.*;
import w3c.www.http.HTTP;
import w3c.jigsaw.http.*;
import w3c.jigsaw.resources.*;
import w3c.jigsaw.forms.*;
import w3c.jigsaw.auth.*;
import w3c.jigsaw.html.*;

/**
 * A resource that allows you to change your password.
 * This resource should be suitably protected when installed, of course.
 */

public class PasswordEditor extends PostableResource {
    /**
     * Attribute index - The name of the realm to edit.
     */
    protected static int ATTR_REALM = -1;

    static {
	Class     c = null;
	Attribute a = null;

	try {
	    c = Class.forName("w3c.jigsaw.contrib.PasswordEditor");
	} catch (Exception ex) {
	    ex.printStackTrace();
	    System.exit(1);
	}
	// Register the name of the realm to edit
	a = new StringAttribute("realm"
				, null
				, Attribute.EDITABLE);
	ATTR_REALM = AttributeRegistry.registerAttribute(c, a);
    }

    /**
     * The loaded realm, when loaded.
     */
    AuthRealm realm = null;

    /**
     * Get the name of the realm to edit.
     * @return The name of the realm to edit, as a String.
     */

    public String getRealm() {
	return getString(ATTR_REALM, null);
    }

    protected synchronized boolean changePassword(String username
						  , String oldpassword
						  , String newpassword) {
	// Get a handle on the authentication realm:
	if ( realm == null ) {
	    // Load the realm from the auth realm catalog:
	    RealmsCatalog c = getServer().getRealmsCatalog();
	    String        r = getRealm();
	    if ( r == null ) {
		getServer().errlog(this, "attribute realm no initialized.");
		return false;
	    }
	    // Really, load the store now:
	    realm = c.loadRealm(r);
	}
	// If we did get the realm:
	if ( realm != null ) {
	    // Get the user:
	    AuthUser user = realm.loadUser(username);
	    if ( user == null )
		return false;
	    // Check the old password first:
	    String passwd = user.getPassword();
	    if ((passwd == null) || ! passwd.equals(oldpassword))
		return false;
	    // Set the new password:
	    user.setPassword(newpassword);
	    return true;
	}
	return false;
    }

    protected HtmlGenerator generateForm(String msg) {
	// Create the HTML and set title:
	HtmlGenerator g = new HtmlGenerator("Password editor for "+getRealm());
	g.append("<h1>Password editor for "
		 , getRealm()
		 , "</h1>");
	// If some message is available, dump it:
	if ( msg != null ) 
	    g.append("<hr>", msg, "</hr>");
	// And then display the form:
	g.append("<form method=\"POST\" action=\""
		 , getURLPath()
		 , "\">");
	g.append("<table width=\"100%\">");
	g.append("<tr><th align=right>username");
	g.append("<th align=left><input type=\"text\" name=\"username\">");
	g.append("<tr><th align=right>old password");
	g.append("<th align=left><input type=\"password\" name=\"opasswd\">");
	g.append("<tr><th align=right>new password");
	g.append("<th align=left><input type=\"password\" name=\"npasswd\">");
	g.append("<tr><th align=right>confirm");
	g.append("<th align=left><input type=\"password\" name=\"cpasswd\">");
	g.append("</table>");
	g.append("<input type=\"submit\" value=\"Change\">");
	g.append("</form>");
	return g;
    }

    protected final HtmlGenerator generateForm() {
	return generateForm(null);
    }

    /**
     * Handle a get request on the password editor.
     * Dump a form suitable for editing a user entry.
     * @param request The request to handle.
     * @return An HTTP Reply instance.
     */

    public Reply get(Request request) {
	Reply reply = createDefaultReply(request, HTTP.OK);
	reply.setStream(generateForm());
	return reply;
    }

    /**
     * Handle a post request.
     * Do change the password, when possible.
     * @param request The request to handle.
     * @param data The form decoded data.
     * @return An HTTP Reply instance.
     */

    public Reply handle(Request request, URLDecoder data) {
	String username = data.getValue("username");
	String opasswd  = data.getValue("opasswd");
	String npasswd  = data.getValue("npasswd");
	String cpasswd  = data.getValue("cpasswd");
	HtmlGenerator g = null;
	if ((username == null)
	    || (opasswd == null)
	    || (npasswd == null)
	    || (cpasswd == null)) {
	    // Check that all values are available:
	    if (username == null)
		g = generateForm("Fill in <em>all</em> the fields.");
	    else
		g = generateForm("Hey, "+username+", could you feel in "
				 + "<em>all</em> the fields please.");
	} else 	if ( ! npasswd.equals(cpasswd) ) {
	    // Check that new and confirmed password are the same:
	    g = generateForm("New and confirmed password don't "
			     + " match, try again "
			     + ((username == null) ? "." : (username+".")));
	} else if ( changePassword(username, opasswd, npasswd) ) {
	    // Run the change:
	    g = new HtmlGenerator("Password now changed.");
	    g.append("<h1>Your password has been changed</h1>");
	    g.append("<p>Operation succeeded, have fun !");
	} else {
	    // Changing the password failed, don't provide explanations:
	    g = new HtmlGenerator("Password change failed");
	    g.append("<h1>Changing the password failed</h1>");
	    g.append("You were not allowed to change the password for user \""
		     , username
		     , "\".");
	}
	// We always succeed, that's cool:
	Reply reply = createDefaultReply(request, HTTP.OK);
	reply.setStream(g);
	return reply;
    }

    /**
     * Empty constructor for dynamic instantiation.
     */

    public PasswordEditor() {
    }

}
