001    /**
002     * Implements the CFML Function hash
003     */
004    package railo.runtime.functions.string;
005    
006    import java.security.MessageDigest;
007    
008    import railo.commons.lang.Md5;
009    import railo.commons.lang.StringUtil;
010    import railo.runtime.PageContext;
011    import railo.runtime.config.Config;
012    import railo.runtime.exp.PageException;
013    import railo.runtime.ext.function.Function;
014    import railo.runtime.op.Caster;
015    
016    public final class Hash implements Function {
017            
018            // function for old code in ra files calling this function
019            public static String call(PageContext pc, String input) throws PageException {
020                    return invoke( pc.getConfig(), input, null, null, 1 );
021            }
022        public synchronized static String call(PageContext pc , String input, String algorithm) throws PageException {
023                    return invoke( pc.getConfig(), input, algorithm, null, 1 );
024            }
025        public synchronized static String call(PageContext pc , String input, String algorithm, String encoding) throws PageException {
026                    return invoke( pc.getConfig(), input, algorithm, encoding, 1 );
027            }
028            //////
029            
030            
031            public static String call(PageContext pc, Object input) throws PageException {
032                    return invoke( pc.getConfig(), input, null, null, 1 );
033            }
034            
035        public synchronized static String call(PageContext pc , Object input, String algorithm) throws PageException {
036                    return invoke( pc.getConfig(), input, algorithm, null, 1 );
037            }
038    
039        public synchronized static String call(PageContext pc , Object input, String algorithm, String encoding) throws PageException {
040                    return invoke( pc.getConfig(), input, algorithm, encoding, 1 );
041            }
042        
043        public synchronized static String call(PageContext pc , Object input, String algorithm, String encoding, double numIterations) throws PageException {
044                    return invoke( pc.getConfig(), input, algorithm, encoding, (int)numIterations );
045            }
046    
047        /*/ this method signature was called from ConfigWebAdmin.createUUID(), comment this comment to enable
048        public synchronized static String invoke(Config config, Object input, String algorithm, String encoding) throws PageException {
049            
050            return invoke(config, input, algorithm, encoding, 1);
051        }   //*/
052        
053        public synchronized static String invoke(Config config, Object input, String algorithm, String encoding, int numIterations) throws PageException {
054                    
055            if(StringUtil.isEmpty(algorithm))algorithm="md5";
056                    else algorithm=algorithm.trim().toLowerCase();
057                    if(StringUtil.isEmpty(encoding))encoding=config.getWebCharset();
058                    
059                    boolean isDefaultAlgo = numIterations == 1 && ("md5".equals(algorithm) || "cfmx_compat".equals(algorithm));
060                    byte[] arrBytes = null;
061                    
062                    try {                   
063                            if(input instanceof byte[]) {
064                                    arrBytes = (byte[])input;
065                                    if(isDefaultAlgo) return Md5.getDigestAsString( arrBytes ).toUpperCase();
066                            } 
067                            else {
068                                    String string = Caster.toString(input);
069                                    if (isDefaultAlgo) return Md5.getDigestAsString( string ).toUpperCase();
070                                    arrBytes = string.getBytes( encoding );
071                            }
072                            
073                            MessageDigest md=MessageDigest.getInstance(algorithm);
074                        md.reset();
075                        
076                            for(int i=0; i<numIterations; i++)
077                                    md.update(arrBytes);
078                        
079                            return Md5.stringify( md.digest() ).toUpperCase();
080                    } 
081                    catch (Throwable t) {
082                            throw Caster.toPageException(t);
083                    }
084            }
085    
086    }