1 17 18 package org.apache.tomcat.util.net; 19 20 21 import java.io.Serializable ; 22 import java.net.MalformedURLException ; 23 24 25 46 47 public final class URL implements Serializable { 48 49 50 52 53 61 public URL(String spec) throws MalformedURLException { 62 63 this(null, spec); 64 65 } 66 67 68 80 public URL(URL context, String spec) throws MalformedURLException { 81 82 String original = spec; 83 int i, limit, c; 84 int start = 0; 85 String newProtocol = null; 86 boolean aRef = false; 87 88 try { 89 90 limit = spec.length(); 92 while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { 93 limit--; 94 } 95 while ((start < limit) && (spec.charAt(start) <= ' ')) { 96 start++; 97 } 98 99 if (spec.regionMatches(true, start, "url:", 0, 4)) { 101 start += 4; 102 } 103 104 if ((start < spec.length()) && (spec.charAt(start) == '#')) { 106 aRef = true; 107 } 108 109 for (i = start; !aRef && (i < limit) ; i++) { 111 c = spec.charAt(i); 112 if (c == ':') { 113 String s = spec.substring(start, i).toLowerCase(); 114 newProtocol = s; 116 start = i + 1; 117 break; 118 } else if( c == '#' ) { 119 aRef = true; 120 } else if( !isSchemeChar((char)c) ) { 121 break; 122 } 123 } 124 125 protocol = newProtocol; 127 if ((context != null) && ((newProtocol == null) || 128 newProtocol.equalsIgnoreCase(context.getProtocol()))) { 129 if ((context.getPath() != null) && 134 (context.getPath().startsWith("/"))) 135 newProtocol = null; 136 if (newProtocol == null) { 137 protocol = context.getProtocol(); 138 authority = context.getAuthority(); 139 userInfo = context.getUserInfo(); 140 host = context.getHost(); 141 port = context.getPort(); 142 file = context.getFile(); 143 int question = file.lastIndexOf("?"); 144 if (question < 0) 145 path = file; 146 else 147 path = file.substring(0, question); 148 } 149 } 150 151 if (protocol == null) 152 throw new MalformedURLException ("no protocol: " + original); 153 154 i = spec.indexOf('#', start); 156 if (i >= 0) { 157 ref = spec.substring(i + 1, limit); 158 limit = i; 159 } 160 161 parse(spec, start, limit); 163 if (context != null) 164 normalize(); 165 166 167 } catch (MalformedURLException e) { 168 throw e; 169 } catch (Exception e) { 170 throw new MalformedURLException (e.toString()); 171 } 172 173 } 174 175 176 177 178 179 190 public URL(String protocol, String host, String file) 191 throws MalformedURLException { 192 193 this(protocol, host, -1, file); 194 195 } 196 197 198 212 public URL(String protocol, String host, int port, String file) 213 throws MalformedURLException { 214 215 this.protocol = protocol; 216 this.host = host; 217 this.port = port; 218 219 int hash = file.indexOf('#'); 220 this.file = hash < 0 ? file : file.substring(0, hash); 221 this.ref = hash < 0 ? null : file.substring(hash + 1); 222 int question = file.lastIndexOf('?'); 223 if (question >= 0) { 224 query = file.substring(question + 1); 225 path = file.substring(0, question); 226 } else 227 path = file; 228 229 if ((host != null) && (host.length() > 0)) 230 authority = (port == -1) ? host : host + ":" + port; 231 232 } 233 234 235 237 238 241 private String authority = null; 242 243 244 247 private String file = null; 248 249 250 253 private String host = null; 254 255 256 259 private String path = null; 260 261 262 265 private int port = -1; 266 267 268 271 private String protocol = null; 272 273 274 277 private String query = null; 278 279 280 283 private String ref = null; 284 285 286 289 private String userInfo = null; 290 291 292 294 295 305 public boolean equals(Object obj) { 306 307 if (obj == null) 308 return (false); 309 if (!(obj instanceof URL)) 310 return (false); 311 URL other = (URL) obj; 312 if (!sameFile(other)) 313 return (false); 314 return (compare(ref, other.getRef())); 315 316 } 317 318 319 322 public String getAuthority() { 323 324 return (this.authority); 325 326 } 327 328 329 335 public String getFile() { 336 337 if (file == null) 338 return (""); 339 return (this.file); 340 341 } 342 343 344 347 public String getHost() { 348 349 return (this.host); 350 351 } 352 353 354 357 public String getPath() { 358 359 if (this.path == null) 360 return (""); 361 return (this.path); 362 363 } 364 365 366 369 public int getPort() { 370 371 return (this.port); 372 373 } 374 375 376 379 public String getProtocol() { 380 381 return (this.protocol); 382 383 } 384 385 386 389 public String getQuery() { 390 391 return (this.query); 392 393 } 394 395 396 399 public String getRef() { 400 401 return (this.ref); 402 403 } 404 405 406 409 public String getUserInfo() { 410 411 return (this.userInfo); 412 413 } 414 415 416 427 public void normalize() throws MalformedURLException { 428 429 if (path == null) { 431 if (query != null) 432 file = "?" + query; 433 else 434 file = ""; 435 return; 436 } 437 438 String normalized = path; 440 if (normalized.equals("/.")) { 441 path = "/"; 442 if (query != null) 443 file = path + "?" + query; 444 else 445 file = path; 446 return; 447 } 448 449 if (normalized.indexOf('\\') >= 0) 451 normalized = normalized.replace('\\', '/'); 452 if (!normalized.startsWith("/")) 453 normalized = "/" + normalized; 454 455 while (true) { 457 int index = normalized.indexOf("//"); 458 if (index < 0) 459 break; 460 normalized = normalized.substring(0, index) + 461 normalized.substring(index + 1); 462 } 463 464 while (true) { 466 int index = normalized.indexOf("/./"); 467 if (index < 0) 468 break; 469 normalized = normalized.substring(0, index) + 470 normalized.substring(index + 2); 471 } 472 473 while (true) { 475 int index = normalized.indexOf("/../"); 476 if (index < 0) 477 break; 478 if (index == 0) 479 throw new MalformedURLException 480 ("Invalid relative URL reference"); 481 int index2 = normalized.lastIndexOf('/', index - 1); 482 normalized = normalized.substring(0, index2) + 483 normalized.substring(index + 3); 484 } 485 486 if (normalized.endsWith("/.")) 488 normalized = normalized.substring(0, normalized.length() - 1); 489 490 if (normalized.endsWith("/..")) { 492 int index = normalized.length() - 3; 493 int index2 = normalized.lastIndexOf('/', index - 1); 494 if (index2 < 0) 495 throw new MalformedURLException 496 ("Invalid relative URL reference"); 497 normalized = normalized.substring(0, index2 + 1); 498 } 499 500 path = normalized; 502 if (query != null) 503 file = path + "?" + query; 504 else 505 file = path; 506 507 } 508 509 510 516 public boolean sameFile(URL other) { 517 518 if (!compare(protocol, other.getProtocol())) 519 return (false); 520 if (!compare(host, other.getHost())) 521 return (false); 522 if (port != other.getPort()) 523 return (false); 524 if (!compare(file, other.getFile())) 525 return (false); 526 return (true); 527 528 } 529 530 531 535 public String toExternalForm() { 536 537 StringBuffer sb = new StringBuffer (); 538 if (protocol != null) { 539 sb.append(protocol); 540 sb.append(":"); 541 } 542 if (authority != null) { 543 sb.append("//"); 544 sb.append(authority); 545 } 546 if (path != null) 547 sb.append(path); 548 if (query != null) { 549 sb.append('?'); 550 sb.append(query); 551 } 552 if (ref != null) { 553 sb.append('#'); 554 sb.append(ref); 555 } 556 return (sb.toString()); 557 558 } 559 560 561 564 public String toString() { 565 566 StringBuffer sb = new StringBuffer ("URL["); 567 sb.append("authority="); 568 sb.append(authority); 569 sb.append(", file="); 570 sb.append(file); 571 sb.append(", host="); 572 sb.append(host); 573 sb.append(", port="); 574 sb.append(port); 575 sb.append(", protocol="); 576 sb.append(protocol); 577 sb.append(", query="); 578 sb.append(query); 579 sb.append(", ref="); 580 sb.append(ref); 581 sb.append(", userInfo="); 582 sb.append(userInfo); 583 sb.append("]"); 584 return (sb.toString()); 585 586 588 } 589 590 591 593 594 601 private boolean compare(String first, String second) { 602 603 if (first == null) { 604 if (second == null) 605 return (true); 606 else 607 return (false); 608 } else { 609 if (second == null) 610 return (false); 611 else 612 return (first.equals(second)); 613 } 614 615 } 616 617 618 635 private void parse(String spec, int start, int limit) 636 throws MalformedURLException { 637 638 int question = spec.lastIndexOf('?', limit - 1); 640 if ((question >= 0) && (question < limit)) { 641 query = spec.substring(question + 1, limit); 642 limit = question; 643 } else { 644 query = null; 645 } 646 647 if (spec.indexOf("//", start) == start) { 649 int pathStart = spec.indexOf("/", start + 2); 650 if ((pathStart >= 0) && (pathStart < limit)) { 651 authority = spec.substring(start + 2, pathStart); 652 start = pathStart; 653 } else { 654 authority = spec.substring(start + 2, limit); 655 start = limit; 656 } 657 if (authority.length() > 0) { 658 int at = authority.indexOf('@'); 659 if( at >= 0 ) { 660 userInfo = authority.substring(0,at); 661 } 662 int ipv6 = authority.indexOf('[',at+1); 663 int hStart = at+1; 664 if( ipv6 >= 0 ) { 665 hStart = ipv6; 666 ipv6 = authority.indexOf(']', ipv6); 667 if( ipv6 < 0 ) { 668 throw new MalformedURLException ( 669 "Closing ']' not found in IPV6 address: " + authority); 670 } else { 671 at = ipv6-1; 672 } 673 } 674 675 int colon = authority.indexOf(':', at+1); 676 if (colon >= 0) { 677 try { 678 port = 679 Integer.parseInt(authority.substring(colon + 1)); 680 } catch (NumberFormatException e) { 681 throw new MalformedURLException (e.toString()); 682 } 683 host = authority.substring(hStart, colon); 684 } else { 685 host = authority.substring(hStart); 686 port = -1; 687 } 688 } 689 } 690 691 if (spec.indexOf("/", start) == start) { path = spec.substring(start, limit); 694 if (query != null) 695 file = path + "?" + query; 696 else 697 file = path; 698 return; 699 } 700 701 if (path == null) { 703 if (query != null) 704 file = "?" + query; 705 else 706 file = null; 707 return; 708 } 709 if (!path.startsWith("/")) 710 throw new MalformedURLException 711 ("Base path does not start with '/'"); 712 if (!path.endsWith("/")) 713 path += "/../"; 714 path += spec.substring(start, limit); 715 if (query != null) 716 file = path + "?" + query; 717 else 718 file = path; 719 return; 720 721 } 722 723 727 public static boolean isSchemeChar(char c) { 728 return Character.isLetterOrDigit(c) || 729 c == '+' || c == '-' || c == '.'; 730 } 731 732 } 733 | Popular Tags |