All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cocoon.components.modules.input.DigestMetaModule Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.cocoon.components.modules.input;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.thread.ThreadSafe;

import org.apache.cocoon.util.HashMap;

import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Iterator;
import java.util.Map;
import java.io.UnsupportedEncodingException;

/** Meta module that obtains values from other module and returns
 * message digest of value. Very useful for storing and checking
 * passwords. Input module configured through nested element
 * "input-module", message digest algorithm, security provider, salt,
 * and URL encoded output configurable through elements "algorithm",
 * "provider", "salt", "encode". Defaults are "sha", null, "salt", and
 * "false". Available value for encode are "none" (returns byte[]),
 * "string" (return hash as string), "url" (returns url encoded
 * string), "hex" (returns string of hex values).
 *
 * @version $Id: DigestMetaModule.java 587751 2007-10-24 02:41:36Z vgritsenko $
 */
public class DigestMetaModule extends AbstractMetaModule implements ThreadSafe {

    private String defaultAlgorithm = "SHA";
    private String defaultProvider;
    private String defaultSalt = "salt";
    private String defaultEncode = "false";

    /** output encoding none */
    static final int ENCODING_NONE = 0;
    /** output encoding url encoding */
    static final int ENCODING_STR = 1;
    /** output encoding hex */
    static final int ENCODING_URL = 2;
    /** output encoding hex */
    static final int ENCODING_HEX = 3;

    private static final HashMap encodingNames;
    /** setup mapping tables */
    static {
        HashMap names = new HashMap();
        names.put("false", new Integer(ENCODING_NONE));
        names.put("no", new Integer(ENCODING_NONE));
        names.put("none", new Integer(ENCODING_NONE));
        names.put("string", new Integer(ENCODING_STR));
        names.put("yes", new Integer(ENCODING_URL));
        names.put("true", new Integer(ENCODING_URL));
        names.put("hex", new Integer(ENCODING_HEX));
        encodingNames = names;
        names = null;
    }

    /**
     * @see org.apache.cocoon.components.modules.input.AbstractInputModule#configure(org.apache.avalon.framework.configuration.Configuration)
     */
    public void configure(Configuration config) throws ConfigurationException {
        this.inputConf = config.getChild("input-module");
        this.defaultInput = this.inputConf.getAttribute("name", this.defaultInput);

        this.defaultAlgorithm = this.inputConf.getAttribute("algorithm",this.defaultAlgorithm);
        this.defaultProvider = this.inputConf.getAttribute("provider",this.defaultProvider);
        this.defaultSalt = this.inputConf.getAttribute("salt",this.defaultSalt);
        this.defaultEncode = this.inputConf.getAttribute("encode","false");

        // preferred
        this.defaultAlgorithm = config.getChild("algorithm").getValue(this.defaultAlgorithm);
        this.defaultProvider = config.getChild("provider").getValue(this.defaultProvider);
        this.defaultSalt = config.getChild("salt").getValue(this.defaultSalt);
        this.defaultEncode = config.getChild("encode").getValue(this.defaultEncode);

        if (encodingNames.get(this.defaultEncode) == null) {
            if (getLogger().isErrorEnabled())
                getLogger().error("Requested encoding is unknown: "+this.defaultEncode);
            this.defaultEncode="false";
        }
    }

    /**
     * @see org.apache.cocoon.components.modules.input.AbstractInputModule#getAttribute(java.lang.String, org.apache.avalon.framework.configuration.Configuration, java.util.Map)
     */
    public Object getAttribute( String name, Configuration modeConf, Map objectModel ) 
    throws ConfigurationException {
        if (!this.initialized) {
            this.lazy_initialize();
        }
        if (this.defaultInput == null) {
            if (getLogger().isWarnEnabled()) 
                getLogger().warn("No input module given. FAILING");
            return null;
        }

        // obtain correct configuration objects
        // default vs dynamic
        Configuration inputConfig = null;
        String inputName=null;
        String algorithm = this.defaultAlgorithm;
        String provider  = this.defaultProvider;
        String salt  = this.defaultSalt;
        int encode = ((Integer) encodingNames.get(this.defaultEncode)).intValue();
        if (modeConf!=null) {
            inputName   = modeConf.getChild("input-module").getAttribute("name",null);
            if (inputName != null) {
                inputConfig = modeConf.getChild("input-module");
            }
            // read necessary parameters
            algorithm = modeConf.getAttribute("algorithm", algorithm);
            provider  = modeConf.getAttribute("provider", provider);
            salt  = modeConf.getAttribute("salt", salt);
            encode = ((Integer) encodingNames.get(modeConf.getAttribute("encode", this.defaultEncode))).intValue();

            // preferred
            algorithm = modeConf.getChild("algorithm").getValue(algorithm);
            provider  = modeConf.getChild("provider").getValue(provider);
            salt  = modeConf.getChild("salt").getValue(salt);
            encode = ((Integer) encodingNames.get(modeConf.getChild("encode").getValue(this.defaultEncode))).intValue();
        }


        Object value = getValue(name, objectModel,
                                this.input, this.defaultInput, this.inputConf,
                                null, inputName, inputConfig);
        
        if (value != null)
            try {
                MessageDigest md = (provider==null ? MessageDigest.getInstance(algorithm) : 
                                    MessageDigest.getInstance(algorithm,provider));
                
                md.update((salt+(value instanceof String? (String)value : value.toString())).getBytes());
                return encodeByteArray(md.digest(),encode);

            } catch (NoSuchAlgorithmException nsae) {
                if (getLogger().isWarnEnabled()) 
                    getLogger().warn("A problem occurred acquiring digest algorithm '" + algorithm 
                                     + (provider==null?"":"' from '"+provider) +"': " + nsae.getMessage());
            } catch (NoSuchProviderException nspe) {
                if (getLogger().isWarnEnabled()) 
                    getLogger().warn("A problem occurred acquiring digest algorithm '" + algorithm 
                                     + (provider==null?"":"' from '"+provider) +"': " + nspe.getMessage());
            }

        return null;        
    }

    /**
     * @see org.apache.cocoon.components.modules.input.AbstractInputModule#getAttributeNames(org.apache.avalon.framework.configuration.Configuration, java.util.Map)
     */
    public Iterator getAttributeNames( Configuration modeConf, Map objectModel )
    throws ConfigurationException {
        if (!this.initialized) {
             this.lazy_initialize();
        }
        if (this.defaultInput == null) {
            if (getLogger().isWarnEnabled()) 
                getLogger().warn("No input module given. FAILING");
            return null;
        }

        // obtain correct configuration objects
        // default vs dynamic
        Configuration inputConfig = null;
        String inputName=null;
        if (modeConf!=null) {
            inputName   = modeConf.getChild("input-module").getAttribute("name",null);
            if (inputName != null) {
                inputConfig = modeConf.getChild("input-module");
            }
        }

        Iterator names = getNames(objectModel, 
                                  this.input, this.defaultInput, this.inputConf, 
                                  null, inputName, inputConfig);
        
        return names;
    }

    /**
     * @see org.apache.cocoon.components.modules.input.AbstractInputModule#getAttributeValues(java.lang.String, org.apache.avalon.framework.configuration.Configuration, java.util.Map)
     */
    public Object[] getAttributeValues( String name, Configuration modeConf, Map objectModel )
    throws ConfigurationException {
        if (!this.initialized) {
            this.lazy_initialize();
        }
        if (this.defaultInput == null) {
            if (getLogger().isWarnEnabled()) 
                getLogger().warn("No input module given. FAILING");
            return null;
        }

        // obtain correct configuration objects
        // default vs dynamic
        Configuration inputConfig = null;
        String inputName=null;
        String algorithm = this.defaultAlgorithm;
        String provider  = this.defaultProvider;
        String salt  = this.defaultSalt;
        int encode = ((Integer) encodingNames.get(this.defaultEncode)).intValue();
        if (modeConf!=null) {
            inputName   = modeConf.getChild("input-module").getAttribute("name",null);
            if (inputName != null) {
                inputConfig = modeConf.getChild("input-module");
            }
            // read necessary parameters
            algorithm = modeConf.getAttribute("algorithm", algorithm);
            provider  = modeConf.getAttribute("provider" , provider );
            salt  = modeConf.getAttribute("salt" , salt );
            encode = ((Integer) encodingNames.get(modeConf.getAttribute("encode" , this.defaultEncode))).intValue();

            // preferred
            algorithm = modeConf.getChild("algorithm").getValue(algorithm);
            provider  = modeConf.getChild("provider").getValue(provider);
            salt  = modeConf.getChild("salt").getValue(salt);
            encode = ((Integer) encodingNames.get(modeConf.getChild("encode").getValue(this.defaultEncode))).intValue();
        }

        Object[] values = getValues(name, objectModel, 
                                    this.input, this.defaultInput, this.inputConf, 
                                    null, inputName, inputConfig);
        Object[] result = null;

        if (values != null) {
            try {
                MessageDigest md = (provider==null ? MessageDigest.getInstance(algorithm) : 
                                    MessageDigest.getInstance(algorithm,provider));
                
                result = new Object[values.length];
                for (int i=0; ibyte[]
     * @param encode an int, one of {@link #ENCODING_NONE},{@link #ENCODING_URL},{@link #ENCODING_HEX}
     * @return an Object
     */
    Object encodeByteArray(byte[] b, int encode) {
        Object result = null;
        switch(encode) {
        case ENCODING_HEX:
            result = byte2Hex(b);
            break;
        case ENCODING_STR:
            try {
                result = new String(b, "UTF-8");
            } catch (UnsupportedEncodingException uee) {
                if (getLogger().isErrorEnabled())
                    getLogger().error("UTF-8 not supported -- cannot convert message digest to String.");
            }
            break;
        case ENCODING_URL:
            try {
                String str = new String(b, "UTF-8");
                result = URLEncoder.encode(str, "utf-8");
            } catch (UnsupportedEncodingException uee) {
                if (getLogger().isErrorEnabled())
                    getLogger().error("UTF-8 not supported -- cannot convert message digest to String.");
            }
            break;
        case ENCODING_NONE:
            // nothing to do
            break;
        default:
            // should not happen
        }
        return result;
    }

    /**
     * Create a hex representation of a byte array.
     *
     * @param b a byte[] value
     * @return a String value
     */
    static String byte2Hex ( byte[] b ) {
        StringBuffer sb = new StringBuffer( b.length * 2 );
        for ( int i=0 ; i < b.length ; i++ ) {
            sb.append( hexChar [ ( b[i] & 0xf0 ) >>> 4 ] ) ;
            sb.append( hexChar [ ( b[i] & 0x0f )       ] ) ;
        }
        return sb.toString() ;
    }


    /** 
     * hex digits lookup table
     */
    static char[] hexChar = {
        '0' , '1' , '2' , '3' ,
        '4' , '5' , '6' , '7' ,
        '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' 
    };

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy