/* * Copyright (C) 2000 - 2008 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD 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 OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbluedragon.org/ */ package com.nary.net.http; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.util.BitSet; /** * Class that provides methods for URLEncoding. Req'd for jdks below 1.4 * where java.net.URLEncoder doesn't provide an encode method that * takes a charset parameter */ public class urlEncoder { // permitted chars in the url private static final BitSet SAFECHARS = new BitSet(256); static { for (int i = 'a'; i <= 'z'; i++) { SAFECHARS.set(i); } for (int i = 'A'; i <= 'Z'; i++) { SAFECHARS.set(i); } for (int i = '0'; i <= '9'; i++) { SAFECHARS.set(i); } } // encodes with UTF-8 charset, which is the W3C recommendation (see // javadoc comments for java.net.URLEncoder @SuppressWarnings("deprecation") public static String encode( String s ) { try { return encode( s, "UTF-8" ); } catch ( UnsupportedEncodingException e ) { // this should not be possible?! return java.net.URLEncoder.encode( s ); } } public static String encode( String s, String _enc ) throws UnsupportedEncodingException{ if ( !needsEncoded( s ) ) return s; boolean wroteUnencodedChar = false; int strLen = s.length(); int maxBytes = 10; // max no. of bytes req'd for a single char String enc = com.nary.util.Localization.convertCharSetToCharEncoding( _enc ); StringBuilder out = new StringBuilder( strLen ); ByteArrayOutputStream buf = new ByteArrayOutputStream( maxBytes ); OutputStreamWriter writer = new OutputStreamWriter( buf, enc ); for (int i = 0; i < strLen; i++) { int c = (int) s.charAt(i); // if we don't need to encode this char if ( SAFECHARS.get(c) ){ if ( wroteUnencodedChar ){ // write out any chars that have been written to the writer writeHex( out, buf.toByteArray() ); buf.reset(); wroteUnencodedChar = false; } out.append( (char) c ); }else{ // convert to external encoding before hex conversion try { wroteUnencodedChar = true; writer.write(c); if (c >= 0xD800 && c <= 0xDBFF) { if ( (i+1) < strLen ) { int d = (int) s.charAt(i+1); if ( d >= 0xDC00 && d <= 0xDFFF ) { writer.write(d); i++; } } } writer.flush(); }catch( IOException e ){ buf.reset(); continue; } } } // write out any remaining characters in the buffer if ( wroteUnencodedChar ){ writeHex( out, buf.toByteArray() ); } return out.toString(); } private static void writeHex( StringBuilder _out, byte [] _ba ){ for (int j = 0; j < _ba.length; j++) { _out.append('%'); char ch = Character.toUpperCase( Character.forDigit( (_ba[j] >> 4) & 0xF, 16 ) ); _out.append(ch); ch = Character.toUpperCase( Character.forDigit( _ba[j] & 0xF, 16 ) ); _out.append(ch); } } private static boolean needsEncoded( String _s ){ int strLen = _s.length(); for(int i = 0; i < strLen; i++){ int ch = _s.charAt(i); if ( !( (ch >= 'a' && ch <= 'z') || (ch>= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') ) ){ return true; } } return false; } }// urlEncoder