1 /* 2 Copyright (c) 2001, 2002 Thai Open Source Software Center Ltd 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are 7 met: 8 9 Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 12 Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in 14 the documentation and/or other materials provided with the 15 distribution. 16 17 Neither the name of the Thai Open Source Software Center Ltd nor 18 the names of its contributors may be used to endorse or promote 19 products derived from this software without specific prior written 20 permission. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 26 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 // @@3RD PARTY CODE@@ 35 36 package com.sun.xml.internal.xsom.impl.util; 37 38 import java.io.IOException; 39 import java.io.UnsupportedEncodingException; 40 import java.net.URL; 41 42 public class Uri { 43 private static String utf8 = "UTF-8"; 44 45 public static boolean isValid(String s) { 46 return isValidPercent(s) && isValidFragment(s) && isValidScheme(s); 47 } 48 49 private static final String HEX_DIGITS = "0123456789abcdef"; 50 51 public static String escapeDisallowedChars(String s) { 52 StringBuffer buf = null; 53 int len = s.length(); 54 int done = 0; 55 for (;;) { 56 int i = done; 57 for (;;) { 58 if (i == len) { 59 if (done == 0) 60 return s; 61 break; 62 } 63 if (isExcluded(s.charAt(i))) 64 break; 65 i++; 66 } 67 if (buf == null) 68 buf = new StringBuffer(); 69 if (i > done) { 70 buf.append(s.substring(done, i)); 71 done = i; 72 } 73 if (i == len) 74 break; 75 for (i++; i < len && isExcluded(s.charAt(i)); i++) 76 ; 77 String tem = s.substring(done, i); 78 byte[] bytes; 79 try { 80 bytes = tem.getBytes(utf8); 81 } 82 catch (UnsupportedEncodingException e) { 83 utf8 = "UTF8"; 84 try { 85 bytes = tem.getBytes(utf8); 86 } 87 catch (UnsupportedEncodingException e2) { 88 // Give up 89 return s; 90 } 91 } 92 for (int j = 0; j < bytes.length; j++) { 93 buf.append('%'); 94 buf.append(HEX_DIGITS.charAt((bytes[j] & 0xFF) >> 4)); 95 buf.append(HEX_DIGITS.charAt(bytes[j] & 0xF)); 96 } 97 done = i; 98 } 99 return buf.toString(); 100 } 101 102 private static String excluded = "<>\"{}|\\^`"; 103 104 private static boolean isExcluded(char c) { 105 return c <= 0x20 || c >= 0x7F || excluded.indexOf(c) >= 0; 106 } 107 108 private static boolean isAlpha(char c) { 109 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 110 } 111 112 private static boolean isHexDigit(char c) { 113 return ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || isDigit(c); 114 } 115 116 private static boolean isDigit(char c) { 117 return '0' <= c && c <= '9'; 118 } 119 120 private static boolean isSchemeChar(char c) { 121 return isAlpha(c) || isDigit(c) || c == '+' || c == '-' || c =='.'; 122 } 123 124 private static boolean isValidPercent(String s) { 125 int len = s.length(); 126 for (int i = 0; i < len; i++) 127 if (s.charAt(i) == '%') { 128 if (i + 2 >= len) 129 return false; 130 else if (!isHexDigit(s.charAt(i + 1)) 131 || !isHexDigit(s.charAt(i + 2))) 132 return false; 133 } 134 return true; 135 } 136 137 private static boolean isValidFragment(String s) { 138 int i = s.indexOf('#'); 139 return i < 0 || s.indexOf('#', i + 1) < 0; 140 } 141 142 private static boolean isValidScheme(String s) { 143 if (!isAbsolute(s)) 144 return true; 145 int i = s.indexOf(':'); 146 if (i == 0 147 || i + 1 == s.length() 148 || !isAlpha(s.charAt(0))) 149 return false; 150 while (--i > 0) 151 if (!isSchemeChar(s.charAt(i))) 152 return false; 153 return true; 154 } 155 156 public static String resolve(String baseUri, String uriReference) throws IOException { 157 if (isAbsolute(uriReference)) 158 return uriReference; 159 160 if(baseUri==null) 161 throw new IOException("Unable to resolve relative URI "+uriReference+" without a base URI"); 162 163 if(!isAbsolute(baseUri)) 164 throw new IOException("Unable to resolve relative URI "+uriReference+" because base URI is not absolute: "+baseUri); 165 166 return new URL(new URL(baseUri), uriReference).toString(); 167 } 168 169 public static boolean hasFragmentId(String uri) { 170 return uri.indexOf('#') >= 0; 171 } 172 173 public static boolean isAbsolute(String uri) { 174 int i = uri.indexOf(':'); 175 if (i < 0) 176 return false; 177 while (--i >= 0) { 178 switch (uri.charAt(i)) { 179 case '#': 180 case '/': 181 case '?': 182 return false; 183 } 184 } 185 return true; 186 } 187 }