001 package com.thaiopensource.util; 002 003 import java.net.URL; 004 import java.net.MalformedURLException; 005 import java.io.UnsupportedEncodingException; 006 007 public class Uri { 008 private static String utf8 = "UTF-8"; 009 010 public static boolean isValid(String s) { 011 return isValidPercent(s) && isValidFragment(s) && isValidScheme(s); 012 } 013 014 private static final String HEX_DIGITS = "0123456789abcdef"; 015 016 public static String escapeDisallowedChars(String s) { 017 StringBuffer buf = null; 018 int len = s.length(); 019 int done = 0; 020 for (;;) { 021 int i = done; 022 for (;;) { 023 if (i == len) { 024 if (done == 0) 025 return s; 026 break; 027 } 028 if (isExcluded(s.charAt(i))) 029 break; 030 i++; 031 } 032 if (buf == null) 033 buf = new StringBuffer(); 034 if (i > done) { 035 buf.append(s.substring(done, i)); 036 done = i; 037 } 038 if (i == len) 039 break; 040 for (i++; i < len && isExcluded(s.charAt(i)); i++) 041 ; 042 String tem = s.substring(done, i); 043 byte[] bytes; 044 try { 045 bytes = tem.getBytes(utf8); 046 } 047 catch (UnsupportedEncodingException e) { 048 utf8 = "UTF8"; 049 try { 050 bytes = tem.getBytes(utf8); 051 } 052 catch (UnsupportedEncodingException e2) { 053 // Give up 054 return s; 055 } 056 } 057 for (int j = 0; j < bytes.length; j++) { 058 buf.append('%'); 059 buf.append(HEX_DIGITS.charAt((bytes[j] & 0xFF) >> 4)); 060 buf.append(HEX_DIGITS.charAt(bytes[j] & 0xF)); 061 } 062 done = i; 063 } 064 return buf.toString(); 065 } 066 067 private static final String excluded = "<>\"{}|\\^`"; 068 069 private static boolean isExcluded(char c) { 070 return c <= 0x20 || c >= 0x7F || excluded.indexOf(c) >= 0; 071 } 072 073 private static boolean isAlpha(char c) { 074 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 075 } 076 077 private static boolean isHexDigit(char c) { 078 return ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || isDigit(c); 079 } 080 081 private static boolean isDigit(char c) { 082 return '0' <= c && c <= '9'; 083 } 084 085 private static boolean isSchemeChar(char c) { 086 return isAlpha(c) || isDigit(c) || c == '+' || c == '-' || c =='.'; 087 } 088 089 private static boolean isValidPercent(String s) { 090 int len = s.length(); 091 for (int i = 0; i < len; i++) 092 if (s.charAt(i) == '%') { 093 if (i + 2 >= len) 094 return false; 095 else if (!isHexDigit(s.charAt(i + 1)) 096 || !isHexDigit(s.charAt(i + 2))) 097 return false; 098 } 099 return true; 100 } 101 102 private static boolean isValidFragment(String s) { 103 int i = s.indexOf('#'); 104 return i < 0 || s.indexOf('#', i + 1) < 0; 105 } 106 107 private static boolean isValidScheme(String s) { 108 if (!isAbsolute(s)) 109 return true; 110 int i = s.indexOf(':'); 111 if (i == 0 112 || i + 1 == s.length() 113 || !isAlpha(s.charAt(0))) 114 return false; 115 while (--i > 0) 116 if (!isSchemeChar(s.charAt(i))) 117 return false; 118 return true; 119 } 120 121 public static String resolve(String baseUri, String uriReference) { 122 if (!isAbsolute(uriReference) && baseUri != null && isAbsolute(baseUri)) { 123 try { 124 return new URL(new URL(baseUri), uriReference).toString(); 125 } 126 catch (MalformedURLException e) { } 127 } 128 return uriReference; 129 } 130 131 public static boolean hasFragmentId(String uri) { 132 return uri.indexOf('#') >= 0; 133 } 134 135 public static boolean isAbsolute(String uri) { 136 int i = uri.indexOf(':'); 137 if (i < 0) 138 return false; 139 while (--i >= 0) { 140 switch (uri.charAt(i)) { 141 case '#': 142 case '/': 143 case '?': 144 return false; 145 } 146 } 147 return true; 148 } 149 }