//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.util.security;

import java.io.IOException;
import java.util.Arrays;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/* ------------------------------------------------------------ */
/**
 * Password utility class.
 * 
 * This utility class gets a password or pass phrase either by:
 * 
 * <PRE>
 *  + Password is set as a system property.
 *  + The password is prompted for and read from standard input
 *  + A program is run to get the password.
 * </pre>
 * 
 * Passwords that begin with OBF: are de obfuscated. Passwords can be obfuscated
 * by run org.eclipse.util.Password as a main class. Obfuscated password are
 * required if a system needs to recover the full password (eg. so that it may
 * be passed to another system). They are not secure, but prevent casual
 * observation.
 * <p>
 * Passwords that begin with CRYPT: are oneway encrypted with UnixCrypt. The
 * real password cannot be retrieved, but comparisons can be made to other
 * passwords. A Crypt can be generated by running org.eclipse.util.UnixCrypt as
 * a main class, passing password and then the username. Checksum passwords are
 * a secure(ish) way to store passwords that only need to be checked rather than
 * recovered. Note that it is not strong security - specially if simple
 * passwords are used.
 * 
 * 
 */
public class Password extends Credential
{
    private static final Logger LOG = Log.getLogger(Password.class);

    private static final long serialVersionUID = 5062906681431569445L;

    public static final String __OBFUSCATE = "OBF:";

    private String _pw;

    /* ------------------------------------------------------------ */
    /**
     * Constructor.
     * 
     * @param password The String password.
     */
    public Password(String password)
    {
        _pw = password;

        // expand password
        while (_pw != null && _pw.startsWith(__OBFUSCATE))
            _pw = deobfuscate(_pw);
    }

    /* ------------------------------------------------------------ */
    @Override
    public String toString()
    {
        return _pw;
    }

    /* ------------------------------------------------------------ */
    public String toStarString()
    {
        return "*****************************************************".substring(0, _pw.length());
    }

    /* ------------------------------------------------------------ */
    @Override
    public boolean check(Object credentials)
    {
        if (this == credentials) return true;

        if (credentials instanceof Password) return credentials.equals(_pw);

        if (credentials instanceof String) return credentials.equals(_pw);

        if (credentials instanceof char[]) return Arrays.equals(_pw.toCharArray(), (char[]) credentials);

        if (credentials instanceof Credential) return ((Credential) credentials).check(_pw);

        return false;
    }

    /* ------------------------------------------------------------ */
    @Override
    public boolean equals(Object o)
    {
        if (this == o) 
            return true;

        if (null == o) 
            return false;

        if (o instanceof Password)
        {
            Password p = (Password) o;
            //noinspection StringEquality
            return p._pw == _pw || (null != _pw && _pw.equals(p._pw));
        }

        if (o instanceof String) 
            return o.equals(_pw);

        return false;
    }

    /* ------------------------------------------------------------ */
    @Override
    public int hashCode()
    {
        return null == _pw ? super.hashCode() : _pw.hashCode();
    }

    /* ------------------------------------------------------------ */
    public static String obfuscate(String s)
    {
        StringBuilder buf = new StringBuilder();
        byte[] b = s.getBytes();

        buf.append(__OBFUSCATE);
        for (int i = 0; i < b.length; i++)
        {
            byte b1 = b[i];
            byte b2 = b[s.length() - (i + 1)];
            int i1 = 127 + b1 + b2;
            int i2 = 127 + b1 - b2;
            int i0 = i1 * 256 + i2;
            String x = Integer.toString(i0, 36);

            switch (x.length())
            {
                case 1:
                    buf.append('0');
                    buf.append('0');
                    buf.append('0');
                    buf.append(x);
                    break;
                case 2:
                    buf.append('0');
                    buf.append('0');
                    buf.append(x);
                    break;
                case 3:
                    buf.append('0');
                    buf.append(x);
                    break;
                default:
                    buf.append(x);
                    break;
            }
        }
        return buf.toString();

    }

    /* ------------------------------------------------------------ */
    public static String deobfuscate(String s)
    {
        if (s.startsWith(__OBFUSCATE)) s = s.substring(4);

        byte[] b = new byte[s.length() / 2];
        int l = 0;
        for (int i = 0; i < s.length(); i += 4)
        {
            String x = s.substring(i, i + 4);
            int i0 = Integer.parseInt(x, 36);
            int i1 = (i0 / 256);
            int i2 = (i0 % 256);
            b[l++] = (byte) ((i1 + i2 - 254) / 2);
        }

        return new String(b, 0, l);
    }

    /* ------------------------------------------------------------ */
    /**
     * Get a password. A password is obtained by trying
     * <UL>
     * <LI>Calling <Code>System.getProperty(realm,dft)</Code>
     * <LI>Prompting for a password
     * <LI>Using promptDft if nothing was entered.
     * </UL>
     * 
     * @param realm The realm name for the password, used as a SystemProperty
     *                name.
     * @param dft The default password.
     * @param promptDft The default to use if prompting for the password.
     * @return Password
     */
    public static Password getPassword(String realm, String dft, String promptDft)
    {
        String passwd = System.getProperty(realm, dft);
        if (passwd == null || passwd.length() == 0)
        {
            try
            {
                System.out.print(realm + ((promptDft != null && promptDft.length() > 0) ? " [dft]" : "") + " : ");
                System.out.flush();
                byte[] buf = new byte[512];
                int len = System.in.read(buf);
                if (len > 0) passwd = new String(buf, 0, len).trim();
            }
            catch (IOException e)
            {
                LOG.warn(Log.EXCEPTION, e);
            }
            if (passwd == null || passwd.length() == 0) passwd = promptDft;
        }
        return new Password(passwd);
    }

    /* ------------------------------------------------------------ */
    /**
     * @param arg
     */
    public static void main(String[] arg)
    {
        if (arg.length != 1 && arg.length != 2)
        {
            System.err.println("Usage - java org.eclipse.jetty.security.Password [<user>] <password>");
            System.err.println("If the password is ?, the user will be prompted for the password");
            System.exit(1);
        }
        String p = arg[arg.length == 1 ? 0 : 1];
        Password pw = new Password(p);
        System.err.println(pw.toString());
        System.err.println(obfuscate(pw.toString()));
        System.err.println(Credential.MD5.digest(p));
        if (arg.length == 2) System.err.println(Credential.Crypt.crypt(arg[0], pw.toString()));
    }
}
