Created
July 27, 2013 07:46
-
-
Save twuni/6094157 to your computer and use it in GitHub Desktop.
A secure, high performance, thread-safe URL encoder implementation in Java. It's intended to be a drop-in replacement for java.net.URLEncoder that uses mutable CharSequences instead of Strings, for applications which require thorough mutability for sensitive data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.CharBuffer; | |
import java.util.BitSet; | |
public class URLEncoder { | |
private static final char [] IGNORED_BY_DEFAULT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!*()-_'.~".toCharArray(); | |
private static final char [] HEX = "0123456789ABCDEF".toCharArray(); | |
private static final URLEncoder DEFAULT = new URLEncoder(); | |
public static CharSequence encode( CharSequence s ) { | |
return getDefaultInstance().encodeURIComponent( s ); | |
} | |
public static URLEncoder getDefaultInstance() { | |
return DEFAULT; | |
} | |
/** | |
* Convert a number to a character array, using the provided buffer. | |
* | |
* @param number | |
* the number to convert | |
* @param array | |
* the buffer in which to store the character representation of the converted number | |
* @param mapping | |
* an array of characters whose index corresponds to the character representing that | |
* digit. The length of this array determines in which base the number will be | |
* represented in the given array. | |
* @return the given array, after modification. If the array's length is greater than is | |
* necessary, its contents will be right-aligned and left-padded with the mapping for | |
* the number zero. For example, the result of | |
* {@code itoa( 5, new char[8], "01".toCharArray() )} would be "00000101". | |
*/ | |
public static char [] itoa( int number, char [] array, char [] mapping ) { | |
int count = 0; | |
int maximum = array.length - 1; | |
for( int value = number; value > 0; value /= mapping.length ) { | |
int digit = value % mapping.length; | |
value -= digit; | |
array[maximum - count] = mapping[digit]; | |
count++; | |
} | |
if( count <= maximum ) { | |
for( int zero = count; zero <= maximum; zero++ ) { | |
array[maximum - zero] = mapping[0]; | |
} | |
} | |
return array; | |
} | |
public static char [] itoa( int number, int arrayLength, char [] mapping ) { | |
return itoa( number, new char [arrayLength], mapping ); | |
} | |
public static char [] itoa( int number, int arrayLength, String mapping ) { | |
return itoa( number, arrayLength, mapping.toCharArray() ); | |
} | |
private final char [] a = new char [2]; | |
private final BitSet ignored = new BitSet( 256 ); | |
public URLEncoder() { | |
this( IGNORED_BY_DEFAULT ); | |
} | |
/** | |
* Constructs a new URL encoder that encodes everything except the given characters. | |
* | |
* @param unencodedCharacters | |
* an array of characters to ignore when encoding. | |
*/ | |
public URLEncoder( char [] unencodedCharacters ) { | |
for( int i = 0; i < unencodedCharacters.length; i++ ) { | |
ignored.set( unencodedCharacters[i] ); | |
} | |
} | |
public URLEncoder( String unencodedCharacters ) { | |
this( unencodedCharacters.toCharArray() ); | |
} | |
public CharSequence encodeURIComponent( CharSequence s ) { | |
CharBuffer out = CharBuffer.allocate( s.length() * 3 ); | |
out.limit( s.length() ); | |
for( int i = 0; i < s.length(); i++ ) { | |
char c = s.charAt( i ); | |
if( ignored.get( c ) ) { | |
out.append( c ); | |
} else { | |
out.append( '%' ); | |
out.limit( out.limit() + 2 ); | |
itoa( c, a, HEX ); | |
out.append( a[0] ); | |
out.append( a[1] ); | |
} | |
} | |
out.position( 0 ); | |
return out; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment