package com.xerox.amazonws.common; import java.io.CharArrayWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.BitSet; import java.security.AccessController; import sun.security.action.GetPropertyAction; /** * This encoder is to be used instead of the URLEncoder when encoding params for version 2 signing */ public class SignerEncoder { private static BitSet dontEncode; private static String defaultEncoding; static { // encode everything except what is included in the bitset dontEncode = new BitSet(256); for (int i='a'; i<='z'; i++) { dontEncode.set(i); } for (int i='A'; i<='Z'; i++) { dontEncode.set(i); } for (int i='0'; i<='9'; i++) { dontEncode.set(i); } dontEncode.set('-'); dontEncode.set('_'); dontEncode.set('.'); dontEncode.set('~'); defaultEncoding = (String)AccessController.doPrivileged(new GetPropertyAction("file.encoding")); } public static String encode(String str) throws UnsupportedEncodingException { int lowerDiff = 'a' - 'A'; StringBuffer ret = new StringBuffer(str.length()); CharArrayWriter charsToEscape = new CharArrayWriter(); try { for (int pos = 0; pos < str.length(); pos++) { int chr = (int)str.charAt(pos); if (dontEncode.get(chr)) { ret.append((char)chr); } else { do { charsToEscape.write(chr); if (chr >= 0xD800 && chr <= 0xDBFF) { if (pos < (str.length()-1)) { int lower = (int)str.charAt(pos+1); if (lower >= 0xDC00 && lower <= 0xDFFF) { charsToEscape.write(lower); pos++; } } } pos++; } while (pos < str.length() && !dontEncode.get((chr = (int)str.charAt(pos)))); charsToEscape.flush(); String tmp = new String(charsToEscape.toCharArray()); byte [] bytes = tmp.getBytes("UTF-8"); for (int i=0; i<bytes.length; i++) { ret.append("%"); char ch = Character.forDigit((bytes[i] >> 4) & 0xf, 16); if (Character.isLetter(ch)) { ch -= lowerDiff; } ret.append(ch); ch = Character.forDigit(bytes[i] & 0xf, 16); if (Character.isLetter(ch)) { ch -= lowerDiff; } ret.append(ch); } charsToEscape.reset(); } } } catch (UnsupportedEncodingException ex) { } return ret.toString(); } public static void main(String [] args) throws Exception { String test1 = "abcdef ABCDEF -_.~"; System.out.println("'"+test1+"' signer encoded as '"+SignerEncoder.encode(test1)+"'"); String test2 = "hi\u2022there\077"; System.out.println("'"+test2+"' signer encoded as '"+SignerEncoder.encode(test2)+"'"); System.out.println("'"+test2+"' url encoded as '"+java.net.URLEncoder.encode(test2, "UTF-8")+"'"); } }