1 27 package org.htmlparser.http; 28 29 import java.io.File ; 30 import java.io.IOException ; 31 import java.net.HttpURLConnection ; 32 import java.net.MalformedURLException ; 33 import java.net.URL ; 34 import java.net.URLConnection ; 35 import java.net.UnknownHostException ; 36 import java.text.ParseException ; 37 import java.text.SimpleDateFormat ; 38 import java.util.Date ; 39 import java.util.Enumeration ; 40 import java.util.Hashtable ; 41 import java.util.List ; 42 import java.util.Map ; 43 import java.util.Properties ; 44 import java.util.StringTokenizer ; 45 import java.util.Vector ; 46 47 import org.htmlparser.util.ParserException; 48 49 52 public class ConnectionManager 53 { 54 58 protected static Hashtable mDefaultRequestProperties = new Hashtable (); 59 static 60 { 61 mDefaultRequestProperties.put ("User-Agent", "HTMLParser/" + org.htmlparser.Parser.VERSION_NUMBER); 62 mDefaultRequestProperties.put ("Accept-Encoding", "gzip, deflate"); 63 } 64 65 68 static private final String [] mFourOhFour = 69 { 70 "The web site you seek cannot be located, but countless more exist", 71 "You step in the stream, but the water has moved on. This page is not here.", 72 "Yesterday the page existed. Today it does not. The internet is like that.", 73 "That page was so big. It might have been very useful. But now it is gone.", 74 "Three things are certain: death, taxes and broken links. Guess which has occured.", 75 "Chaos reigns within. Reflect, repent and enter the correct URL. Order shall return.", 76 "Stay the patient course. Of little worth is your ire. The page is not found.", 77 "A non-existant URL reduces your expensive computer to a simple stone.", 78 "Many people have visited that page. Today, you are not one of the lucky ones.", 79 "Cutting the wind with a knife. Bookmarking a URL. Both are ephemeral.", 80 }; 81 82 85 static private final char[] mCharacterTable = 86 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); 87 88 91 protected Hashtable mRequestProperties; 92 93 96 protected String mProxyHost; 97 98 101 protected int mProxyPort; 102 103 106 protected String mProxyUser; 107 108 111 protected String mProxyPassword; 112 113 116 protected String mUser; 117 118 121 protected String mPassword; 122 123 127 protected Hashtable mCookieJar; 128 129 132 protected ConnectionMonitor mMonitor; 133 134 137 public ConnectionManager () 138 { 139 this (getDefaultRequestProperties ()); 140 } 141 142 146 public ConnectionManager (Hashtable properties) 147 { 148 mRequestProperties = properties; 149 mProxyHost = null; 150 mProxyPort = 0; 151 mProxyUser = null; 152 mProxyPassword = null; 153 mUser = null; 154 mPassword = null; 155 mCookieJar = null; 156 mMonitor = null; 157 158 } 159 160 164 169 public static Hashtable getDefaultRequestProperties () 170 { 171 return (mDefaultRequestProperties); 172 } 173 174 223 public static void setDefaultRequestProperties (Hashtable properties) 224 { 225 mDefaultRequestProperties = properties; 226 } 227 228 235 public static String getRequestHeader (HttpURLConnection connection) 236 { 237 StringBuffer buffer; 239 Map map; 240 String key; 241 List items; 242 243 buffer = new StringBuffer (1024); 244 buffer.append (connection.getRequestMethod ()); 245 buffer.append (" "); 246 buffer.append (connection.getURL ()); 247 buffer.append (" HTTP/1.1\n"); 248 map = connection.getRequestProperties (); 249 for (java.util.Iterator iterator = map.keySet ().iterator (); iterator.hasNext ();) 250 { 251 key = (String )iterator.next (); 252 items = (List )map.get (key); 253 buffer.append (key); 254 buffer.append (": "); 255 for (int i = 0; i < items.size (); i++) 256 { 257 if (0 != i) 258 buffer.append (", "); 259 buffer.append (items.get (i)); 260 } 261 buffer.append ("\n"); 262 } 263 264 return (buffer.toString ()); 265 } 266 267 277 public static String getResponseHeader (HttpURLConnection connection) 278 { 279 StringBuffer buffer; 281 int code; 282 String message; 283 String key; 284 String value; 285 286 buffer = new StringBuffer (1024); 287 try 288 { 289 code = connection.getResponseCode (); 290 if (-1 != code) 291 { 292 message = connection.getResponseMessage (); 293 buffer.append ("HTTP/1.1 "); 294 buffer.append (code); 295 buffer.append (" "); 296 buffer.append (message); 297 buffer.append ("\n"); 298 for (int i = 0; null != (value = connection.getHeaderField (i)); i++) 299 { 300 key = connection.getHeaderFieldKey (i); 301 if (null != key) 302 { 303 buffer.append (key); 304 buffer.append (": "); 305 buffer.append (value); 306 buffer.append ("\n"); 307 } 308 } 309 } 310 } 311 catch (IOException ioe) 312 { 313 buffer.append (ioe.toString ()); 314 } 315 316 return (buffer.toString ()); 317 } 318 319 324 public Hashtable getRequestProperties () 325 { 326 return (mRequestProperties); 327 } 328 329 340 public void setRequestProperties (Hashtable properties) 341 { 342 mRequestProperties = properties; 343 } 344 345 348 public String getProxyHost () 349 { 350 return (mProxyHost); 351 } 352 353 357 public void setProxyHost (String host) 358 { 359 mProxyHost = host; 360 } 361 362 365 public int getProxyPort () 366 { 367 return (mProxyPort); 368 } 369 370 373 public void setProxyPort (int port) 374 { 375 mProxyPort = port; 376 } 377 378 382 public String getProxyUser () 383 { 384 return (mProxyUser); 385 } 386 387 391 public void setProxyUser (String user) 392 { 393 mProxyUser = user; 394 } 395 396 399 public String getProxyPassword () 400 { 401 return (mProxyPassword); 402 } 403 404 407 public void setProxyPassword (String password) 408 { 409 mProxyPassword = password; 410 } 411 412 416 public String getUser () 417 { 418 return (mUser); 419 } 420 421 425 public void setUser (String user) 426 { 427 mUser = user; 428 } 429 430 433 public String getPassword () 434 { 435 return (mPassword); 436 } 437 438 441 public void setPassword (String password) 442 { 443 mPassword = password; 444 } 445 446 450 public boolean getCookieProcessingEnabled () 451 { 452 return (null != mCookieJar); 453 } 454 455 460 public void setCookieProcessingEnabled (boolean enable) 461 { 462 if (enable) 463 mCookieJar = (null == mCookieJar) ? new Hashtable () : mCookieJar; 464 else 465 mCookieJar = null; 466 } 467 468 473 public void setCookie (Cookie cookie, String domain) 474 { 475 String path; 476 Vector cookies; 477 Cookie probe; 478 479 if (null != cookie.getDomain ()) 480 domain = cookie.getDomain (); 481 path = cookie.getPath (); 482 if (null == mCookieJar) 483 mCookieJar = new Hashtable (); cookies = (Vector )mCookieJar.get (domain); 485 if (null != cookies) 486 { 487 for (int j = 0; j < cookies.size (); j++) 488 { 489 probe = (Cookie)cookies.elementAt (j); 490 if (probe.getName ().equalsIgnoreCase (cookie.getName ())) 491 { 492 if (probe.getPath ().equals (path)) 494 { 495 cookies.setElementAt (cookie, j); break; 497 } 498 else if (path.startsWith (probe.getPath ())) 499 { 500 cookies.insertElementAt (cookie, j); 501 break; 502 } 503 } 504 } 505 } 506 else 507 { cookies = new Vector (); 509 cookies.addElement (cookie); 510 mCookieJar.put (domain, cookies); 511 } 512 513 } 514 515 518 public ConnectionMonitor getMonitor () 519 { 520 return mMonitor; 521 } 522 523 526 public void setMonitor (ConnectionMonitor monitor) 527 { 528 mMonitor = monitor; 529 } 530 531 536 public URLConnection openConnection (URL url) 537 throws 538 ParserException 539 { 540 Properties sysprops; 541 Hashtable properties; 542 Enumeration enumeration; 543 String key; 544 String value; 545 String set = null; String host = null; String port = null; String host2 = null; String port2 = null; HttpURLConnection http; 551 URLConnection ret; 552 553 try 554 { 555 try 556 { 557 if ((null != getProxyHost ()) && (0 != getProxyPort ())) 559 { 560 sysprops = System.getProperties (); 561 set = (String )sysprops.put ("proxySet", "true"); 562 host = (String )sysprops.put ("proxyHost", getProxyHost ()); 563 port = (String )sysprops.put ("proxyPort", Integer.toString (getProxyPort ())); 564 host2 = (String )sysprops.put ("http.proxyHost", getProxyHost ()); 566 port2 = (String )sysprops.put ("http.proxyPort", Integer.toString (getProxyPort ())); 567 System.setProperties (sysprops); 568 569 } 570 571 ret = url.openConnection (); 573 if (ret instanceof HttpURLConnection ) 574 { 575 http = (HttpURLConnection )ret; 576 577 properties = getRequestProperties (); 579 if (null != properties) 580 for (enumeration = properties.keys (); enumeration.hasMoreElements ();) 581 { 582 key = (String )enumeration.nextElement (); 583 value = (String )properties.get (key); 584 ret.setRequestProperty (key, value); 585 } 586 587 if ((null != getProxyUser ()) && (null != getProxyPassword ())) 589 { 590 String authorization = getProxyUser () + ":" + getProxyPassword (); 591 String encodedauthorization = encode (authorization.getBytes("ISO-8859-1")); 592 ret.setRequestProperty ("Proxy-Authorization", encodedauthorization); 593 } 594 595 if ((null != getUser ()) && (null != getPassword ())) 597 { 598 String authorization = getUser () + ":" + getPassword (); 599 String encodedauthorization = encode (authorization.getBytes("ISO-8859-1")); 600 ret.setRequestProperty ("Authorization", "Basic " + encodedauthorization); 601 } 602 603 addCookies (ret); 605 606 if (null != getMonitor ()) 607 getMonitor ().preConnect (http); 608 } 609 else 610 http = null; 611 612 try 613 { 614 ret.connect (); 615 616 if (null != http) 617 { 618 if (null != getMonitor ()) 619 getMonitor ().postConnect (http); 620 621 parseCookies (ret); 622 } 623 } 624 catch (UnknownHostException uhe) 625 { 626 int message = (int)(Math.random () * mFourOhFour.length); 627 throw new ParserException (mFourOhFour[message], uhe); 628 } 629 catch (IOException ioe) 630 { 631 throw new ParserException (ioe.getMessage (), ioe); 632 } 633 } 634 finally 635 { 636 if ((null != getProxyHost ()) && (0 != getProxyPort ())) 637 { 638 sysprops = System.getProperties (); 639 if (null != set) 640 sysprops.put ("proxySet", set); 641 else 642 sysprops.remove ("proxySet"); 643 if (null != host) 644 sysprops.put ("proxyHost", host); 645 else 646 sysprops.remove ("proxyHost"); 647 if (null != port) 648 sysprops.put ("proxyPort", port); 649 else 650 sysprops.remove ("proxyPort"); 651 if (null != host2) 652 sysprops.put ("http.proxyHost", host2); 653 else 654 sysprops.remove ("http.proxyHost"); 655 if (null != port2) 656 sysprops.put ("http.proxyPort", port2); 657 else 658 sysprops.remove ("http.proxyPort"); 659 System.setProperties (sysprops); 660 } 661 } 662 } 663 catch (IOException ioe) 664 { 665 String msg = "HTMLParser.openConnection() : Error in opening a connection to " + url.toExternalForm (); 666 ParserException ex = new ParserException (msg, ioe); 667 throw ex; 668 } 669 670 return (ret); 671 } 672 673 678 public final static String encode (byte[] array) 679 { 680 int last; int count; int separators; int length; char[] encoded; int left; int end; 687 int block; int r; int n; int index; String ret; 692 693 if ((null != array) && (0 != array.length)) 694 { 695 last = array.length - 1; 696 count = (last / 3 + 1) << 2; 697 separators = (count - 1) / 76; 698 length = count + separators; 699 encoded = new char[length]; 700 index = 0; 701 separators = 0; 702 for (int i = 0; i <= last; i += 3) 703 { 704 left = last - i; 705 end = (left > 1 ? 2 : left); 706 707 block = 0; 709 r = 16; 710 for (int j = 0; j <= end; j++) 711 { 712 n = array[i + j]; 713 block += (n < 0 ? n + 256 : n) << r; 714 r -= 8; 715 } 716 717 encoded[index++] = mCharacterTable[(block >>> 18) & 0x3f]; 719 encoded[index++] = mCharacterTable[(block >>> 12) & 0x3f]; 720 encoded[index++] = left > 0 ? mCharacterTable[(block >>> 6) & 0x3f] : '='; 721 encoded[index++] = left > 1 ? mCharacterTable[block & 0x3f] : '='; 722 723 if ((0 == (index - separators) % 76) && (index < length)) 724 { 725 encoded[index++] = '\n'; 726 separators += 1; 727 } 728 } 729 ret = new String (encoded); 730 } 731 else 732 ret = ""; 733 734 return (ret); 735 } 736 737 743 public String fixSpaces (String url) 744 { 745 int index; 746 int length; 747 char ch; 748 StringBuffer buffer; 749 750 index = url.indexOf (' '); 751 if (-1 != index) 752 { 753 length = url.length (); 754 buffer = new StringBuffer (length * 3); 755 buffer.append (url.substring (0, index)); 756 for (int i = index; i < length; i++) 757 { 758 ch = url.charAt (i); 759 if (ch==' ') 760 buffer.append ("%20"); 761 else 762 buffer.append (ch); 763 } 764 url = buffer.toString (); 765 } 766 767 return (url); 768 } 769 770 779 public URLConnection openConnection (String string) 780 throws 781 ParserException 782 { 783 final String prefix = "file://localhost"; 784 String resource; 785 URL url; 786 StringBuffer buffer; 787 URLConnection ret; 788 789 try 790 { 791 url = new URL (fixSpaces (string)); 792 ret = openConnection (url); 793 } 794 catch (MalformedURLException murle) 795 { try 797 { 798 File file = new File (string); 799 resource = file.getCanonicalPath (); 800 buffer = new StringBuffer (prefix.length () + resource.length ()); 801 buffer.append (prefix); 802 if (!resource.startsWith ("/")) 803 buffer.append ("/"); 804 buffer.append (resource); 805 url = new URL (fixSpaces (buffer.toString ())); 806 ret = openConnection (url); 807 } 808 catch (MalformedURLException murle2) 809 { 810 String msg = "HTMLParser.openConnection() : Error in opening a connection to " + string; 811 ParserException ex = new ParserException (msg, murle2); 812 throw ex; 813 } 814 catch (IOException ioe) 815 { 816 String msg = "HTMLParser.openConnection() : Error in opening a connection to " + string; 817 ParserException ex = new ParserException (msg, ioe); 818 throw ex; 819 } 820 } 821 822 return (ret); 823 } 824 825 844 public void addCookies (URLConnection connection) 845 { 846 Vector list; 847 URL url; 848 String host; 849 String path; 850 String domain; 851 852 if (null != mCookieJar) 853 { 854 list = null; 855 url = connection.getURL (); 857 host = url.getHost (); 858 path = url.getPath (); 859 if (0 == path.length ()) 860 path = "/"; 861 if (null != host) 862 { list = addCookies ((Vector )mCookieJar.get (host), path, list); 864 domain = getDomain (host); 865 if (null != domain) 866 list = addCookies ((Vector )mCookieJar.get (domain), path, list); 867 else 868 list = addCookies ((Vector )mCookieJar.get ("." + host), path, list); 870 } 871 if (null != list) 872 connection.setRequestProperty ("Cookie", generateCookieProperty (list)); 873 } 874 } 875 876 883 protected Vector addCookies (Vector cookies, String path, Vector list) 884 { 885 Cookie cookie; 886 Date expires; 887 Date now; 888 889 if (null != cookies) 890 { 891 now = new Date (); 892 for (int i = 0; i < cookies.size (); i++) 893 { 894 cookie = (Cookie)cookies.elementAt (i); 895 expires = cookie.getExpiryDate (); 896 if ((null != expires) && expires.before (now)) 897 { 898 cookies.remove (i); 899 i--; } 901 else 902 if (path.startsWith (cookie.getPath ())) 903 { 904 if (null == list) 905 list = new Vector (); 906 list.addElement (cookie); 907 } 908 } 909 } 910 911 return (list); 912 } 913 914 920 protected String getDomain (String host) 921 { 922 StringTokenizer tokenizer; 923 int count; 924 String server; 925 int length; 926 boolean ok; 927 char c; 928 String ret; 929 930 ret = null; 931 932 tokenizer = new StringTokenizer (host, "."); 933 count = tokenizer.countTokens (); 934 if (3 <= count) 935 { 936 length = host.length (); 939 ok = false; 940 for (int i = 0; i < length && !ok; i++) 941 { 942 c = host.charAt (i); 943 if (!(Character.isDigit (c) || (c == '.'))) 944 ok = true; 945 } 946 if (ok) 947 { 948 server = tokenizer.nextToken (); 950 length = server.length (); 951 ret = host.substring (length); 952 } 953 } 954 955 return (ret); 956 } 957 958 963 protected String generateCookieProperty (Vector cookies) 964 { 965 int version; 966 Cookie cookie; 967 StringBuffer buffer; 968 String ret; 969 970 ret = null; 971 972 buffer = new StringBuffer (); 973 version = 0; 974 for (int i = 0; i < cookies.size (); i++) 975 version = Math.max (version, ((Cookie)cookies.elementAt (i)).getVersion ()); 976 if (0 != version) 977 { 978 buffer.append ("$Version=\""); 979 buffer.append (version); 980 buffer.append ("\""); 981 } 982 for (int i = 0; i < cookies.size (); i++) 983 { 984 cookie = (Cookie)cookies.elementAt (i); 985 if (0 != buffer.length ()) 986 buffer.append ("; "); 987 buffer.append (cookie.getName ()); 988 buffer.append ("="); 989 if (0 != version) 990 buffer.append ("\""); 991 buffer.append (cookie.getValue ()); 992 if (0 != version) 993 buffer.append ("\""); 994 if (0 != version) 995 { 996 if ((null != cookie.getPath ()) 997 && (0 != cookie.getPath ().length ())) 998 { 999 buffer.append ("; $Path=\""); 1000 buffer.append (cookie.getPath ()); 1001 buffer.append ("\""); 1002 } 1003 if ((null != cookie.getDomain ()) 1004 && (0 != cookie.getDomain ().length ())) 1005 { 1006 buffer.append ("; $Domain=\""); 1007 buffer.append (cookie.getDomain ()); 1008 buffer.append ("\""); 1009 } 1010 } 1011 } 1012 if (0 != buffer.length ()) 1013 ret = buffer.toString (); 1014 1015 return (ret); 1016 } 1017 1018 1021 public void parseCookies (URLConnection connection) 1022 { 1023 String string; 1024 Vector cookies; 1025 StringTokenizer tokenizer; 1026 String token; 1027 int index; 1028 String name; 1029 String key; 1030 String value; 1031 Cookie cookie; 1032 1033 string = connection.getHeaderField ("Set-Cookie"); 1034 if (null != string) 1035 { 1036 cookies = new Vector (); 1048 tokenizer = new StringTokenizer (string, ";,", true); 1049 cookie = null; 1050 while (tokenizer.hasMoreTokens ()) 1051 { 1052 token = tokenizer.nextToken ().trim (); 1053 if (token.equals (";")) 1054 continue; 1055 else if (token.equals (",")) 1056 { 1057 cookie = null; 1058 continue; 1059 } 1060 1061 index = token.indexOf ('='); 1062 if (-1 == index) 1063 { 1064 name = token; 1065 value = null; 1066 if (null == cookie) 1067 throw new IllegalStateException ("no cookie value"); 1068 key = name.toLowerCase (); 1069 } 1070 else 1071 { 1072 name = token.substring (0, index); 1073 value = token.substring (index + 1); 1074 key = name.toLowerCase (); 1075 } 1076 1077 if (null == cookie) 1078 { 1079 cookie = new Cookie (name, value); 1080 cookies.addElement (cookie); 1081 } 1082 else 1083 { 1084 if (key.equals ("expires")) { 1086 String comma = tokenizer.nextToken (); 1087 String rest = tokenizer.nextToken (); 1088 SimpleDateFormat format = new SimpleDateFormat ("EEE, dd-MMM-yy kk:mm:ss z"); 1089 try 1090 { 1091 Date date = format.parse (value + comma + rest); 1092 cookie.setExpiryDate (date); 1093 } 1094 catch (ParseException pe) 1095 { 1096 cookie.setExpiryDate (null); 1098 } 1099 } 1100 else 1101 if (key.equals ("domain")) 1102 cookie.setDomain (value); 1103 else 1104 if (key.equals ("path")) 1105 cookie.setPath (value); 1106 else 1107 if (key.equals ("secure")) 1108 cookie.setSecure (true); 1109 else 1110 if (key.equals ("comment")) 1111 cookie.setComment (value); 1112 else 1113 if (key.equals ("version")) 1114 cookie.setVersion (Integer.parseInt (value)); 1115 else 1116 if (key.equals ("max-age")) 1117 { 1118 Date date = new Date (); 1119 long then = date.getTime () + Integer.parseInt (value) * 1000; 1120 date.setTime (then); 1121 cookie.setExpiryDate (date); 1122 } 1123 else 1124 { cookie = new Cookie (name, value); 1127 cookies.addElement (cookie); 1128 } 1129 } 1130 } 1131 if (0 != cookies.size ()) 1132 saveCookies (cookies, connection); 1133 } 1134 } 1135 1136 protected void saveCookies (Vector list, URLConnection connection) 1137 { 1138 Cookie cookie; 1139 String domain; 1140 1141 for (int i = 0; i < list.size (); i++) 1142 { 1143 cookie = (Cookie)list.elementAt (i); 1144 domain = cookie.getDomain (); 1145 if (null == domain) 1146 domain = connection.getURL ().getHost (); 1147 setCookie (cookie, domain); 1148 } 1149 } 1150} 1151 1152 | Popular Tags |