alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/security/Encoder.java,v 1.17 2005/02/21 18:51:07 minhnn Exp $
 * $Author: minhnn $
 * $Revision: 1.17 $
 * $Date: 2005/02/21 18:51:07 $
 *
 * ====================================================================
 *
 * Copyright (C) 2002-2005 by MyVietnam.net
 *
 * This program 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 any later version.
 *
 * All copyright notices regarding MyVietnam and MyVietnam CoreLib
 * MUST remain intact in the scripts and source code.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Correspondence and Marketing Questions can be sent to:
 * info@MyVietnam.net
 *
 * @author: Minh Nguyen  minhnn@MyVietnam.net
 * @author: Mai  Nguyen  mai.nh@MyVietnam.net
 */
package net.myvietnam.mvncore.security;

import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;

import net.myvietnam.mvncore.misc.Base64;
import net.myvietnam.mvncore.util.MailUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Encoder {

    private static Log log = LogFactory.getLog(Encoder.class);

    // Please note that 2 below methods are used in #getMD5_Base64 only
    // use them in other methods will make it not thread-safe
    private static MessageDigest digest = null;
    private static boolean isInited = false;

    private static Method encodeMethod1_4 = null;
    private static Method decodeMethod1_4 = null;

    // URLEncoder.encode(String) has been deprecated in J2SE 1.4.
    // Take advantage of the new method URLEncoder.encode(String, enc)
    // if J2SE 1.4 is used.
    static {
        try {
            Class urlEncoderClass = Class.forName("java.net.URLEncoder");
            encodeMethod1_4 = urlEncoderClass.getMethod("encode",
                    new Class[] {String.class, String.class});
        } catch (Exception ex) {} // encodeMethod1_4 will be null if exception

        try {
            Class urlDecoderClass = Class.forName("java.net.URLDecoder");
            decodeMethod1_4 = urlDecoderClass.getMethod("decode",
                    new Class[] {String.class, String.class});
        } catch (Exception ex) {} // decodeMethod1_4 will be null if exception
    }

    private Encoder() {
    }

    /**
     * This method return a String that has been encrypted as MD5 and then escaped using Base64.<p>
     * This method should be used to encrypt all password for maximum security.
     * @param input String the string that need encrypted
     * @return String the string after encrypted
     */
    public static synchronized String getMD5_Base64(String input) {
        // please note that we dont use digest, because if we
        // cannot get digest, then the second time we have to call it
        // again, which will fail again
        if (isInited == false) {
            isInited = true;
            try {
                digest = MessageDigest.getInstance("MD5");
            } catch (Exception ex) {
                log.fatal("Cannot get MessageDigest. Application may fail to run correctly.", ex);
            }
        }
        if (digest == null) return input;

        // now everything is ok, go ahead
        try {
            digest.update(input.getBytes("UTF-8"));
        } catch (java.io.UnsupportedEncodingException ex) {
            log.error("Assertion: This should never occur.");
        }
        byte[] rawData = digest.digest();
        byte[] encoded = Base64.encode(rawData);
        String retValue = new String(encoded);
        return retValue;
    }

    /**
     * This method just call URLEncoder.encode() so we can get rid of
     * the deprecation warning from using URLEncoder.encode() directly.
     * @param input String
     * @return String
     */
    public static String encodeURL(String input) {
        if (encodeMethod1_4 != null) {
            Object[] methodArgsName = new Object[2];
            methodArgsName[0] = input;
            methodArgsName[1] = "UTF-8";

            try {
                return (String)encodeMethod1_4.invoke(null, methodArgsName);
            } catch (Exception ex) {
                throw new RuntimeException("System error invoking URLEncoder.encode() by reflection.");
            }
        } else {
            // must use J2SE 1.3 version

            // The following line will cause a warning if compile with jdk1.4
            // However, we cannot use the new method String encode(String s, String enc)
            // in jdk1.4, because it wont be compiled with jdk1.3
            // Currently, there is no way to get rid of this wanring
            return URLEncoder.encode(input);
        }
    }

    /**
     * This method just call URLDecoder.decode() so we can get rid of
     * the deprecation warning from using URLDecoder.encode() directly.
     * @param input String
     * @return String
     */
    public static String decodeURL(String input) {
        if (decodeMethod1_4 != null) {
            Object[] methodArgsName = new Object[2];
            methodArgsName[0] = input;
            methodArgsName[1] = "UTF-8";

            try {
                return (String)decodeMethod1_4.invoke(null, methodArgsName);
            } catch (Exception ex) {
                throw new RuntimeException("System error invoking URLDecoder.decode() by reflection.");
            }
        } else {
            // must use J2SE 1.3 version

            // The following line will cause a warning if compile with jdk1.4
            // However, we cannot use the new method String decode(String s, String enc)
            // in jdk1.4, because it wont be compiled with jdk1.3
            // Currently, there is no way to get rid of this wanring
            return URLDecoder.decode(input);
        }
    }

    /**
     * Filter a url to make it safe, this method is used in class URLFilter
     * @param url String a url to be filtered
     * @return String a url that has been filtered
     */
    public static String filterUrl(String url) {
        String lowerUrl = url.toLowerCase();
        if ( (lowerUrl.indexOf("javascript:") >= 0) ||
             lowerUrl.indexOf("file:") >= 0) {
            return "";
        }

        String protocol = "http://";//default protocol
        String name = null;
        if (url.startsWith("http://")) {
            protocol = "http://";
            name = url.substring(protocol.length());// must duplicate it because of the default protocol
        } else if (url.startsWith("https://")) {
            protocol = "https://";
            name = url.substring(protocol.length());// must duplicate it because of the default protocol
        } else if (url.startsWith("ftp://")) {
            protocol = "ftp://";
            name = url.substring(protocol.length());// must duplicate it because of the default protocol
        } else if (url.startsWith("mailto:")) {
            protocol = "mailto:";
            name = url.substring(protocol.length());// must duplicate it because of the default protocol
        } else {
            name = url;
        }
        String ret;
        if (protocol.equals("mailto:")) {
            try {
                MailUtil.checkGoodEmail(name);
                ret = protocol + name;
            } catch (Exception ex) {
                ret = "";
            }
        } else {
            ret = protocol + encodePath(name);
        }
        return ret;
    }

    /**
     *
     * @param path the path, something like this localhost:8080/image/index.html
     * @return the path after being encoded
     */
    private static String encodePath(String path) {
        path = removeInvalidUserInURL(path);
        return path;
        /*
        String ret = "";
        int indexFirstSlash = path.indexOf('/');
        if ( indexFirstSlash != -1 ) {
            String hostport = path.substring(0, indexFirstSlash);
            int indexFirstColon = hostport.indexOf(':');
            if (indexFirstColon != -1) {
                String host = hostport.substring(0, indexFirstColon);
                String port = hostport.substring(indexFirstColon + 1);
                hostport = Encoder.encodeURL(host) + ":" + Encoder.encodeURL(port);
            } else {
                hostport = Encoder.encodeURL(hostport);
            }
            String filename = path.substring(indexFirstSlash + 1);
            filename = Encoder.encodeURL(filename);
            ret = hostport + "/" + filename;
        } else {
            ret = Encoder.encodeURL(path);
        }
        return ret;
        */
    }

    /**
     * This method is used to fix IE spoof url bug:
     * http://originalsite.com % 0 0 @ www.badsite.com
     * <p>(remove the space above, I added spaces because
     * McAfee conplain that it is a trojan)
     * @param path String
     * @return String
     */
    private static String removeInvalidUserInURL(String path) {
        // atIndex is the RIGHT most of @
        int atIndex = path.lastIndexOf('@');
        if (atIndex != -1) {
            // has the user info part
            // percentIndex is the LEFT most of %
            int pecentIndex = path.indexOf('%');
            if ((pecentIndex != -1) && (pecentIndex < atIndex)) {
                // user info part has % in it, very likely a spoof url
                return path.substring(atIndex + 1);// get the char right after @
            }
        }
        return path;
    }
    /*
    public static void main(String[] args) {
        //test data should be
        //a1            iou3zTQ6oq2Zt9diAwhXog==
        //Hello World   sQqNsWTgdUEFt6mb5y4/5Q==

        //String testString = "a1";
        //String encrypted = getMD5_Base64(testString);
        //System.out.println("encrypted = " + encrypted);
        //System.out.println("length = " + encrypted.length());


       //String encodeString = "Di\u1ec5n \u0111\u00e0n";//Die^~n d-a`n
       //JDK 1.3 result : Di%3Fn+%3F%E0n
       //JDK 1.4 result : Di%E1%BB%85n+%C4%91%C3%A0n
       //System.out.println("encodeURL input '" + encodeString + "' output '" + encodeURL(encodeString) + "'");

       //String decodeString = "Di%E1%BB%85n+%C4%91%C3%A0n";//encoded of "Die^~n d-a`n"
       //System.out.println("decodeURL input '" + decodeString + "' output '" + decodeURL(decodeString) + "'");
    }*/
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.