Package de.esoco.microsafe.ui

Source Code of de.esoco.microsafe.ui.MicroSafeNodeController$PasswordSetter

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// MicroSafe source file
// Copyright (c) 2006 Elmar Sonnenschein / esoco GmbH
// Last Change: 17.10.2006 by eso
//
// MicroSafe is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// MicroSafe is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// MicroSafe; if not, write to the Free Software Foundation, Inc., 59 Temple
// Place, Suite 330, Boston, MA   02111-1307   USA or use the contact information
// from the GNU website http://www.gnu.org
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
package de.esoco.microsafe.ui;

import de.esoco.j2me.model.HierarchyNode;
import de.esoco.j2me.resource.ResourceBundle;
import de.esoco.j2me.ui.BasicNodeController;
import de.esoco.j2me.ui.Dialog;
import de.esoco.j2me.ui.ExecutableCommand;
import de.esoco.j2me.ui.MessageScreen;
import de.esoco.j2me.ui.NodeCommand;
import de.esoco.j2me.ui.NodeController;
import de.esoco.j2me.util.Executable;
import de.esoco.j2me.util.TextUtil;
import de.esoco.j2me.util.UserNotificationException;

import de.esoco.microsafe.crypto.CryptoHandler;
import de.esoco.microsafe.crypto.InvalidKeyException;
import de.esoco.microsafe.model.EncryptableNode;
import de.esoco.microsafe.model.MicroSafeModel;
import de.esoco.microsafe.model.MicroSafeNode;

import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.TextField;


/********************************************************************
* BasicNodeController subclass with enhancements to handle encryption specific
* tasks.
*
* @author eso
*/
public class MicroSafeNodeController extends BasicNodeController
{
  //~ Instance fields --------------------------------------------------------

  MicroSafeModel rModel;

  private ExecutableCommand aChangePasswordCommand;
  private NodeCommand      aCryptoCommand;

  //~ Constructors -----------------------------------------------------------

  /***************************************
   * Creates a new instance for a certain model.
   *
   * @param rModel The data model that this controller operates on
   */
  public MicroSafeNodeController(MicroSafeModel rModel)
  {
    this.rModel = rModel;
    initCommands();
  }

  //~ Methods ----------------------------------------------------------------

  /***************************************
   * If the queried node is encrypted and no password has been set before,
   * this method will first query the password from the user and, if the
   * password is correct, grant access to it. If the password is already set
   * the call will be forwarded to <code>super.checkNodeAccess()</code> (which
   * will simply invoke <code>rInvokeIfGranted.execute()</code>).
   *
   * @param rNode            The node to check
   * @param rInvokeIfGranted The Executable instance to invoke if access is
   *                         allowed
   *
   * @see   de.esoco.j2me.ui.BasicNodeController#checkNodeAccess(HierarchyNode,
   *        Executable)
   */
  public void checkNodeAccess(final HierarchyNode rNode,
                final Executable    rInvokeIfGranted)
  {
    if ((rNode instanceof MicroSafeNode) &&
      ((MicroSafeNode) rNode).isEncrypted() &&
      (((MicroSafeNode) rNode).getCryptoHandler() == null))
    {
      queryPassword("MsPassword", false, (MicroSafeNode) rNode, false,
              rInvokeIfGranted);
    }
    else
    {
      super.checkNodeAccess(rNode, rInvokeIfGranted);
    }
  }

  /***************************************
   * To return the image for a certain Node.
   *
   * @param  sNodeType The node type code (always available)
   * @param  rNode     The node for which the image shall be returned (may be
   *                   NULL during node creation)
   *
   * @return The Image for the node or NULL if no Image shall be displayed
   *
   * @see    NodeController#getNodeImage(String, HierarchyNode)
   */
  public Image getNodeImage(String sNodeType, HierarchyNode rNode)
  {
    if ((rNode instanceof EncryptableNode) &&
      ((EncryptableNode) rNode).isEncrypted())
    {
      sNodeType += "E";
    }

    return super.getNodeImage(sNodeType, rNode);
  }

  /***************************************
   * To return an array with commands that can be invoked on editable nodes.
   *
   * @param  rNode The node for which the command list shall be returned
   *
   * @return An array of (Runnable)Command instances
   */
  public Command[] getNodeListEditCommands(HierarchyNode rNode)
  {
    if (rNode.getParent() == null)
    {
      return new Command[] { aCryptoCommand, aChangePasswordCommand };
    }
    else
    {
      return new Command[] { aCryptoCommand };
    }
  }

  /***************************************
   * Internal method as a shortcut to ResourceBundle.getInstance.getString().
   *
   * @see de.esoco.j2me.util.ResourceBundle#getString(String)
   */
  public String getString(String sKey)
  {
    return ResourceBundle.getCurrent().getString(sKey);
  }

  /***************************************
   * To change the encryption of a particular node. If the node is encrypted
   * already the encryption will be removed (if the user confirms it). Else
   * the encryption of the node and all it's children will be activated. If no
   * password has been set before it will be queried first.
   *
   * @param  rNode The node for which the encryption shall be changed
   *
   * @throws UserNotificationException If an error occurs
   */
  void changeNodeEncryption(final MicroSafeNode rNode)
    throws UserNotificationException
  {
    CryptoHandler rCrypto  = rNode.getCryptoHandler();
    final boolean bEncrypt = !rNode.isEncrypted();

    if (rCrypto == null)
    {
      boolean bNewEncryption = !rModel.usesEncryption();
      String  sMsgKey       = bNewEncryption ? "MsNewPasswd"
                          : "MsPassword";

      Executable aEncryptSet = new Executable()
      {
        public void execute(Object rArg)
          throws UserNotificationException
        {
          setNodeEncryption(rNode, bEncrypt);
        }
      };

      queryPassword(sMsgKey, bNewEncryption, rNode, false, aEncryptSet);
    }
    else
    {
      setNodeEncryption(rNode, bEncrypt);
    }
  }

  /***************************************
   * To change the encryption of a particular node. If the node is encrypted
   * already the encryption will be removed (if the user confirms it). Else
   * the encryption of the node and all it's children will be activated. If no
   * password has been set before it will be queried first.
   *
   * @throws UserNotificationException If an error occurs
   */
  void changePassword() throws UserNotificationException
  {
    CryptoHandler rCrypto = rModel.getCryptoHandler();

    if (rModel.usesEncryption() && rCrypto == null)
    {
      Executable aNewPwQuery = new Executable()
      {
        public void execute(Object rArg)
        {
          queryPassword("MsNewPasswd", true, rModel, true, null);
        }
      };

      queryPassword("MsOldPasswd", false, rModel, false, aNewPwQuery);
    }
    else
    {
      queryPassword("MsNewPasswd", true, rModel, true, null);
    }
  }

  /***************************************
   * Queries a password from the user and invokes a PasswordSetter on the
   * given node if the password input is confirmed.
   *
   * @param sMsgKey         The resource key of the message to display
   * @param bVerify         TRUE if the password input shall be verified; the
   *                        input dialog result will be NULL if the
   *                        verification fails
   * @param rNode           The node on which the password shall be set
   * @param bPasswordChange TRUE if the password is changed by this call. This
   *                        means that empty passwords shall be set as NULL
   *                        (to remove the password) and the view must be
   *                        reset afterwards.
   * @param rInvokeIfOk     Will be invoked if the user confirms the input
   */
  void queryPassword(String     sMsgKey,
             boolean     bVerify,
             MicroSafeNode rNode,
             boolean     bPasswordChange,
             Executable    rInvokeIfOk)
  {
    PasswordSetter aSetter = new PasswordSetter(rNode, bPasswordChange,
                          rInvokeIfOk);

    MessageScreen.showInput(getString("MtPassword"), getString(sMsgKey), null,
               CryptoHandler.getMaxKeyLength(),
               TextField.PASSWORD, bVerify, aSetter);
  }

  /***************************************
   * Internal method to set the encryption password on the model to enable
   * access to an encrypted node.
   *
   * @param  rNode     The node that shall be accessed
   * @param  sPassword The password input by the user
   *
   * @throws UserNotificationException If the password is wrong or another
   *                                   encryption error occurs
   */
  void setEncryptionPassword(MicroSafeNode rNode, String sPassword)
    throws UserNotificationException
  {
    try
    {
      rModel.setEncryptionKey((sPassword == null) ? null
                            : sPassword.getBytes());
    }
    catch (Exception e)
    {
      String msg;

      if (e instanceof InvalidKeyException)
      {
        msg = getString("MsPassWrong");
      }
      else
      {
        msg = TextUtil.formatMessage(getString("MsPassErr"),
                       new Object[] { e.getMessage() });
      }

      throw new UserNotificationException(getString("MtPassErr"), msg, e);
    }
  }

  /***************************************
   * Set the encryption flag of a particular node (and by that of all it's
   * children too) and handle all possible errors by wrapping them into a
   * UserNotificationException.
   *
   * @param  rNode      The node to set the encryption flag on
   * @param  bEncrypted The new value of the encryption flag
   *
   * @throws UserNotificationException If changing the flag fails
   */
  void setNodeEncryption(MicroSafeNode rNode, boolean bEncrypted)
    throws UserNotificationException
  {
    try
    {
      rNode.setEncryption(bEncrypted);
      getView().updateNodeItem(rNode, null, null);
    }
    catch (Exception e)
    {
      String msg = TextUtil.formatMessage(getString("MsCryptErr"),
                        new Object[] { e.getMessage() });

      throw new UserNotificationException(getString("JL_MtError"), msg,
                        e);
    }
  }

  /***************************************
   * Initializes the command instances that are specific to MicroSafe nodes.
   */
  private void initCommands()
  {
    aCryptoCommand = new NodeCommand(getString("Crypto"), Command.ITEM, 10,
                     true, this)
      {
        public void processNode(HierarchyNode rNode)
          throws UserNotificationException
        {
          changeNodeEncryption((MicroSafeNode) rNode);
        }
      };

    aChangePasswordCommand = new ExecutableCommand(getString("ChgPasswd"),
                             Command.ITEM, 100)
      {
        public void execute(Object rArg)
          throws UserNotificationException
        {
          changePassword();
        }
      };
  }

  //~ Inner Classes ----------------------------------------------------------

  /********************************************************************
   * Helper class that implements a dialog listener which queries a password
   * from an input dialog and applies it to a certain MicroSafeNode instance.
   */
  private class PasswordSetter implements Executable
  {
    //~ Instance fields ----------------------------------------------------

    boolean bPasswordChange;

    Executable    rExec;
    MicroSafeNode rNode;

    //~ Constructors -------------------------------------------------------

    /***************************************
     * Creates a new PasswordSetter object.
     *
     * @param rNode           The node to set the password on
     * @param bPasswordChange TRUE, if the model's password will be changed
     *                        with this invocation
     * @param rExec           An optional Executable to invoke finally or
     *                        NULL
     */
    PasswordSetter(MicroSafeNode rNode,
             boolean     bPasswordChange,
             Executable    rExec)
    {
      this.rNode       = rNode;
      this.rExec       = rExec;
      this.bPasswordChange = bPasswordChange;
    }

    //~ Methods ------------------------------------------------------------

    /***************************************
     * dialogFinished implementation that sets the password and optionally
     * invokes an Executable afterwards. If the input dialog was setup for
     * password verification (i.e. with two input fields) and the
     * verification failed (result will be NULL), a corresponding error
     * message will be displayed.
     *
     * @param  rInputDialog The dialog instance that contains the password
     *
     * @throws UserNotificationException If an exception occurs
     */
    public void execute(Object rInputDialog)
      throws UserNotificationException
    {
      String sPassword = (String) ((Dialog) rInputDialog).getResult();

      if (sPassword == null)
      {
        // Password NULL means that the input verification failed
        ResourceBundle rRsrc  = ResourceBundle.getCurrent();
        String       sTitle = rRsrc.getString("MtPassErr");
        String       sText  = rRsrc.getString("MsPassComp");

        MessageScreen.showAlert(sTitle, sText, AlertType.ERROR);

        return;
      }

      if (bPasswordChange && (sPassword.length() == 0))
      {
        sPassword = null;
      }

      setEncryptionPassword(rNode, sPassword);

      // refresh display and invalidate application clipboard when
      // password changes because because all nodes will be decrypted
      // (icon change) and encryption of nodes in the clipboard becomes
      // invalid
      if (bPasswordChange)
      {
        getView().reset();
      }

      if (rExec != null)
      {
        rExec.execute(null);
      }
    }
  }
}
TOP

Related Classes of de.esoco.microsafe.ui.MicroSafeNodeController$PasswordSetter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.