001    package railo.commons.net;
002    
003    import java.io.UnsupportedEncodingException;
004    
005    import railo.commons.io.SystemUtil;
006    import railo.runtime.net.http.ReqRspUtil;
007    
008    public class URLDecoder {
009    
010            private URLDecoder(){}
011    
012            /**
013             * @param string
014             * @return
015             */
016            public static String decode(String str, boolean force) {
017                    try {
018                            return decode(str,SystemUtil.getCharset(), force);
019                    } 
020                    catch (UnsupportedEncodingException e) {
021                            return str;
022                    }
023            }
024    
025        public static String decode(String s, String enc, boolean force) throws UnsupportedEncodingException {
026            if(!force && !ReqRspUtil.needDecoding(s)) return s;
027            //if(true) return java.net.URLDecoder.decode(s, enc);
028            
029            boolean needToChange = false;
030            StringBuilder sb = new StringBuilder();
031            int numChars = s.length();
032            int i = 0;
033    
034            
035    
036            while (i < numChars) {
037                char c = s.charAt(i);
038                switch (c) {
039                case '+':
040                    sb.append(' ');
041                    i++;
042                    needToChange = true;
043                    break;
044                case '%':
045                    
046                    try {
047                        byte[] bytes = new byte[(numChars-i)/3];
048                        int pos = 0;
049                        
050                        while ( ((i+2) < numChars) && 
051                                (c=='%')) {
052                            bytes[pos++] = (byte)Integer.parseInt(s.substring(i+1,i+3),16);
053                            i+= 3;
054                            if (i < numChars)
055                                c = s.charAt(i);
056                        }
057    
058                        if ((i < numChars) && (c=='%')){
059                            needToChange = true;
060                                    sb.append(c); 
061                                    i++;
062                                    continue;
063                            //throw new IOException("Incomplete trailing escape (%) pattern");
064                        }
065                        sb.append(new String(bytes, 0, pos, enc));
066                    } catch (NumberFormatException e) {
067                            needToChange = true;
068                            sb.append(c); 
069                            i++;
070                        //throw new IOException("Illegal hex characters in escape (%) pattern - " + e.getMessage());
071                    }
072                    needToChange = true;
073                    break;
074                default: 
075                    sb.append(c); 
076                    i++;
077                    break; 
078                }
079            }
080    
081            return (needToChange? sb.toString() : s);
082        }
083    }
084    
085