1 16 package org.apache.commons.vfs.provider; 17 18 import org.apache.commons.vfs.FileName; 19 import org.apache.commons.vfs.FileSystemException; 20 import org.apache.commons.vfs.FileType; 21 import org.apache.commons.vfs.VFS; 22 23 30 public final class UriParser 31 { 32 35 private static final char SEPARATOR_CHAR = FileName.SEPARATOR_CHAR; 36 37 41 public static final char TRANS_SEPARATOR = '\\'; 43 44 private UriParser() 45 { 46 } 47 48 51 public static String extractFirstElement(final StringBuffer name) 52 { 53 final int len = name.length(); 54 if (len < 1) 55 { 56 return null; 57 } 58 int startPos = 0; 59 if (name.charAt(0) == SEPARATOR_CHAR) 60 { 61 startPos = 1; 62 } 63 for (int pos = startPos; pos < len; pos++) 64 { 65 if (name.charAt(pos) == SEPARATOR_CHAR) 66 { 67 final String elem = name.substring(startPos, pos); 69 name.delete(startPos, pos + 1); 70 return elem; 71 } 72 } 73 74 final String elem = name.substring(startPos); 76 name.setLength(0); 77 return elem; 78 } 79 80 92 public static FileType normalisePath(final StringBuffer path) 93 throws FileSystemException 94 { 95 FileType fileType = FileType.FOLDER; 96 if (path.length() == 0) 97 { 98 return fileType; 99 } 100 101 if (path.charAt(path.length() - 1) != '/') 102 { 103 fileType = FileType.FILE; 104 } 105 106 109 int startFirstElem = 0; 111 if (path.charAt(0) == SEPARATOR_CHAR) 112 { 113 if (path.length() == 1) 114 { 115 return fileType; 116 } 117 startFirstElem = 1; 118 } 119 120 int startElem = startFirstElem; 122 int maxlen = path.length(); 123 while (startElem < maxlen) 124 { 125 int endElem = startElem; 127 for (; endElem < maxlen && path.charAt(endElem) != SEPARATOR_CHAR; endElem++) 128 { 129 } 130 131 final int elemLen = endElem - startElem; 132 if (elemLen == 0) 133 { 134 path.delete(endElem, endElem + 1); 136 maxlen = path.length(); 137 continue; 138 } 139 if (elemLen == 1 && path.charAt(startElem) == '.') 140 { 141 path.delete(startElem, endElem + 1); 143 maxlen = path.length(); 144 continue; 145 } 146 if (elemLen == 2 && path.charAt(startElem) == '.' 147 && path.charAt(startElem + 1) == '.') 148 { 149 if (startElem == startFirstElem) 151 { 152 throw new FileSystemException( 154 "vfs.provider/invalid-relative-path.error"); 155 } 156 157 int pos = startElem - 2; 159 for (; pos >= 0 && path.charAt(pos) != SEPARATOR_CHAR; pos--) 160 { 161 } 162 startElem = pos + 1; 163 164 path.delete(startElem, endElem + 1); 165 maxlen = path.length(); 166 continue; 167 } 168 169 startElem = endElem + 1; 171 } 172 173 if (!VFS.isUriStyle()) 175 { 176 if (maxlen > 0 && path.charAt(maxlen - 1) == SEPARATOR_CHAR 177 && maxlen > 1) 178 { 179 path.delete(maxlen - 1, maxlen); 180 } 181 } 182 183 return fileType; 184 } 185 186 189 public static boolean fixSeparators(final StringBuffer name) 190 { 191 boolean changed = false; 192 final int maxlen = name.length(); 193 for (int i = 0; i < maxlen; i++) 194 { 195 final char ch = name.charAt(i); 196 if (ch == TRANS_SEPARATOR) 197 { 198 name.setCharAt(i, SEPARATOR_CHAR); 199 changed = true; 200 } 201 } 202 return changed; 203 } 204 205 212 public static String extractScheme(final String uri) 213 { 214 return extractScheme(uri, null); 215 } 216 217 227 public static String extractScheme(final String uri, 228 final StringBuffer buffer) 229 { 230 if (buffer != null) 231 { 232 buffer.setLength(0); 233 buffer.append(uri); 234 } 235 236 final int maxPos = uri.length(); 237 for (int pos = 0; pos < maxPos; pos++) 238 { 239 final char ch = uri.charAt(pos); 240 241 if (ch == ':') 242 { 243 final String scheme = uri.substring(0, pos); 245 if (buffer != null) 246 { 247 buffer.delete(0, pos + 1); 248 } 249 return scheme; 250 } 251 252 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) 253 { 254 continue; 256 } 257 if (pos > 0 258 && ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.')) 259 { 260 continue; 264 } 265 266 break; 268 } 269 270 return null; 272 } 273 274 277 public static String decode(final String encodedStr) 278 throws FileSystemException 279 { 280 if (encodedStr == null) 281 { 282 return null; 283 } 284 final StringBuffer buffer = new StringBuffer (encodedStr); 285 decode(buffer, 0, buffer.length()); 286 return buffer.toString(); 287 } 288 289 292 public static void decode(final StringBuffer buffer, final int offset, 293 final int length) throws FileSystemException 294 { 295 int index = offset; 296 int count = length; 297 for (; count > 0; count--, index++) 298 { 299 final char ch = buffer.charAt(index); 300 if (ch != '%') 301 { 302 continue; 303 } 304 if (count < 3) 305 { 306 throw new FileSystemException( 307 "vfs.provider/invalid-escape-sequence.error", buffer 308 .substring(index, index + count)); 309 } 310 311 int dig1 = Character.digit(buffer.charAt(index + 1), 16); 313 int dig2 = Character.digit(buffer.charAt(index + 2), 16); 314 if (dig1 == -1 || dig2 == -1) 315 { 316 throw new FileSystemException( 317 "vfs.provider/invalid-escape-sequence.error", buffer 318 .substring(index, index + 3)); 319 } 320 char value = (char) (dig1 << 4 | dig2); 321 322 buffer.setCharAt(index, value); 324 buffer.delete(index + 1, index + 3); 325 count -= 2; 326 } 327 } 328 329 332 public static void appendEncoded(final StringBuffer buffer, 333 final String unencodedValue, final char[] reserved) 334 { 335 final int offset = buffer.length(); 336 buffer.append(unencodedValue); 337 encode(buffer, offset, unencodedValue.length(), reserved); 338 } 339 340 344 public static void encode(final StringBuffer buffer, final int offset, 345 final int length, final char[] reserved) 346 { 347 int index = offset; 348 int count = length; 349 for (; count > 0; index++, count--) 350 { 351 final char ch = buffer.charAt(index); 352 boolean match = (ch == '%'); 353 if (reserved != null) 354 { 355 for (int i = 0; !match && i < reserved.length; i++) 356 { 357 if (ch == reserved[i]) 358 { 359 match = true; 360 } 361 } 362 } 363 if (match) 364 { 365 char[] digits = 367 { Character.forDigit(((ch >> 4) & 0xF), 16), 368 Character.forDigit((ch & 0xF), 16) }; 369 buffer.setCharAt(index, '%'); 370 buffer.insert(index + 1, digits); 371 index += 2; 372 } 373 } 374 } 375 376 379 public static String encode(final String decodedStr) 380 { 381 return encode(decodedStr, null); 382 } 383 384 public static String encode(final String decodedStr, final char[] reserved) 385 { 386 if (decodedStr == null) 387 { 388 return null; 389 } 390 final StringBuffer buffer = new StringBuffer (decodedStr); 391 encode(buffer, 0, buffer.length(), reserved); 392 return buffer.toString(); 393 } 394 395 public static String [] encode(String [] strings) 396 { 397 if (strings == null) 398 { 399 return null; 400 } 401 for (int i = 0; i < strings.length; i++) 402 { 403 strings[i] = encode(strings[i]); 404 } 405 return strings; 406 } 407 408 public static void checkUriEncoding(String uri) throws FileSystemException 409 { 410 decode(uri); 411 } 412 413 public static void canonicalizePath(StringBuffer buffer, int offset, 414 int length, FileNameParser fileNameParser) 415 throws FileSystemException 416 { 417 int index = offset; 418 int count = length; 419 for (; count > 0; count--, index++) 420 { 421 final char ch = buffer.charAt(index); 422 if (ch == '%') 423 { 424 if (count < 3) 425 { 426 throw new FileSystemException( 427 "vfs.provider/invalid-escape-sequence.error", 428 buffer.substring(index, index + count)); 429 } 430 431 int dig1 = Character.digit(buffer.charAt(index + 1), 16); 433 int dig2 = Character.digit(buffer.charAt(index + 2), 16); 434 if (dig1 == -1 || dig2 == -1) 435 { 436 throw new FileSystemException( 437 "vfs.provider/invalid-escape-sequence.error", 438 buffer.substring(index, index + 3)); 439 } 440 char value = (char) (dig1 << 4 | dig2); 441 442 boolean match = (value == '%') 443 || (fileNameParser != null && fileNameParser 444 .encodeCharacter(value)); 445 446 if (match) 447 { 448 index += 2; 450 count -= 2; 451 continue; 452 } 453 454 buffer.setCharAt(index, value); 456 buffer.delete(index + 1, index + 3); 457 count -= 2; 458 } 459 else if (fileNameParser.encodeCharacter(ch)) 460 { 461 char[] digits = 463 { Character.forDigit(((ch >> 4) & 0xF), 16), 464 Character.forDigit((ch & 0xF), 16) }; 465 buffer.setCharAt(index, '%'); 466 buffer.insert(index + 1, digits); 467 index += 2; 468 } 469 } 470 } 471 472 public static String extractQueryString(StringBuffer name) 473 { 474 for (int pos = 0; pos < name.length(); pos++) 475 { 476 if (name.charAt(pos) == '?') 477 { 478 String queryString = name.substring(pos + 1); 479 name.delete(pos, name.length()); 480 return queryString; 481 } 482 } 483 484 return null; 485 } 486 } 487 | Popular Tags |