1 28 29 package HTTPClient; 30 31 32 import java.io.OutputStream ; 33 import java.io.DataOutputStream ; 34 import java.io.FilterOutputStream ; 35 import java.io.ByteArrayOutputStream ; 36 import java.io.IOException ; 37 import java.io.InterruptedIOException ; 38 import java.net.URL ; 39 import java.net.Socket ; 40 import java.net.InetAddress ; 41 import java.net.SocketException ; 42 import java.net.UnknownHostException ; 43 import java.util.Vector ; 44 import java.util.Hashtable ; 45 import java.applet.Applet ; 46 47 48 193 194 public class HTTPConnection 195 implements GlobalConstants, HTTPClientModuleConstants 196 { 197 198 public final static String version = "RPT-HTTPClient/0.3-2"; 199 200 201 private final static Object dflt_context = new Object (); 202 203 204 private Object Context = null; 205 206 207 private int Protocol; 208 209 210 int ServerProtocolVersion; 211 212 213 boolean ServProtVersKnown; 214 215 217 private String RequestProtocolVersion; 218 219 220 private static boolean no_chunked = false; 221 222 223 private static boolean force_1_0 = false; 224 225 226 private String Host; 227 228 229 private int Port; 230 231 232 private String Proxy_Host = null; 233 234 235 private int Proxy_Port; 236 237 238 private static String Default_Proxy_Host = null; 239 240 241 private static int Default_Proxy_Port; 242 243 244 private static CIHashtable non_proxy_host_list = new CIHashtable(); 245 private static Vector non_proxy_dom_list = new Vector (); 246 private static Vector non_proxy_addr_list = new Vector (); 247 private static Vector non_proxy_mask_list = new Vector (); 248 249 250 private SocksClient Socks_client = null; 251 252 253 private static SocksClient Default_Socks_client = null; 254 255 256 private StreamDemultiplexor input_demux = null; 257 258 259 LinkedList DemuxList = new LinkedList(); 260 261 262 private LinkedList RequestList = new LinkedList(); 263 264 265 private boolean DoesKeepAlive = false; 266 267 268 private boolean KeepAliveUnknown = true; 269 270 271 private int KeepAliveReqMax = -1; 272 273 274 private int KeepAliveReqLeft; 275 276 277 private static boolean NeverPipeline = false; 278 279 280 private static boolean NoKeepAlives = false; 281 282 283 private static boolean haveMSLargeWritesBug = false; 284 285 286 private static int DefaultTimeout = 0; 287 288 289 private int Timeout; 290 291 292 private NVPair[] DefaultHeaders = new NVPair[0]; 293 294 295 private static Vector DefaultModuleList; 296 297 298 private Vector ModuleList; 299 300 301 private static boolean DefaultAllowUI = true; 302 303 304 private boolean AllowUI; 305 306 307 static 308 { 309 313 314 try { 316 String host = System.getProperty("http.proxyHost"); 317 if (host == null) 318 throw new Exception (); int port = Integer.getInteger("http.proxyPort", -1).intValue(); 320 321 if (DebugConn) 322 System.err.println("Conn: using proxy " + host + ":" + port); 323 setProxyServer(host, port); 324 } 325 catch (Exception e) 326 { 327 try { 329 if (Boolean.getBoolean("proxySet")) 330 { 331 String host = System.getProperty("proxyHost"); 332 int port = Integer.getInteger("proxyPort", -1).intValue(); 333 if (DebugConn) 334 System.err.println("Conn: using proxy " + host + ":" + port); 335 setProxyServer(host, port); 336 } 337 } 338 catch (Exception ee) 339 { Default_Proxy_Host = null; } 340 } 341 342 343 346 String hosts = System.getProperty("HTTPClient.nonProxyHosts"); 349 if (hosts == null) 350 hosts = System.getProperty("http.nonProxyHosts"); 351 352 String [] _list = Util.splitProperty(hosts); 353 dontProxyFor(_list); 354 359 360 366 try 367 { 368 String host = System.getProperty("HTTPClient.socksHost"); 369 if (host != null && host.length() > 0) 370 { 371 int port = Integer.getInteger("HTTPClient.socksPort", -1).intValue(); 372 int version = Integer.getInteger("HTTPClient.socksVersion", -1).intValue(); 373 if (DebugConn) 374 System.err.println("Conn: using SOCKS " + host + ":" + port); 375 if (version == -1) 376 setSocksServer(host, port); 377 else 378 setSocksServer(host, port, version); 379 } 380 } 381 catch (Exception e) 382 { Default_Socks_client = null; } 383 384 385 387 String modules = "HTTPClient.RetryModule|" + 388 "HTTPClient.CookieModule|" + 389 "HTTPClient.RedirectionModule|" + 390 "HTTPClient.AuthorizationModule|" + 391 "HTTPClient.DefaultModule|" + 392 "HTTPClient.TransferEncodingModule|" + 393 "HTTPClient.ContentMD5Module|" + 394 "HTTPClient.ContentEncodingModule"; 395 396 boolean in_applet = false; 397 try 398 { modules = System.getProperty("HTTPClient.Modules", modules); } 399 catch (SecurityException se) 400 { in_applet = true; } 401 402 DefaultModuleList = new Vector (); 403 String [] list = Util.splitProperty(modules); 404 for (int idx=0; idx<list.length; idx++) 405 { 406 try 407 { 408 DefaultModuleList.addElement(Class.forName(list[idx])); 409 if (DebugConn) 410 System.err.println("Conn: added module " + list[idx]); 411 } 412 catch (ClassNotFoundException cnfe) 413 { 414 if (!in_applet) 415 throw new NoClassDefFoundError (cnfe.getMessage()); 416 417 423 } 424 } 425 426 427 430 try 431 { 432 NeverPipeline = Boolean.getBoolean("HTTPClient.disable_pipelining"); 433 if (DebugConn) 434 if (NeverPipeline) System.err.println("Conn: disabling pipelining"); 435 } 436 catch (Exception e) 437 { } 438 439 442 try 443 { 444 NoKeepAlives = Boolean.getBoolean("HTTPClient.disableKeepAlives"); 445 if (DebugConn) 446 if (NoKeepAlives) System.err.println("Conn: disabling keep-alives"); 447 } 448 catch (Exception e) 449 { } 450 451 454 try 455 { 456 force_1_0 = Boolean.getBoolean("HTTPClient.forceHTTP_1.0"); 457 if (DebugConn) 458 if (force_1_0) System.err.println("Conn: forcing HTTP/1.0 requests"); 459 } 460 catch (Exception e) 461 { } 462 463 466 try 467 { 468 no_chunked = Boolean.getBoolean("HTTPClient.dontChunkRequests"); 469 if (DebugConn) 470 if (no_chunked) System.err.println("Conn: never chunking requests"); 471 } 472 catch (Exception e) 473 { } 474 475 478 try 479 { 480 if (System.getProperty("os.name").indexOf("Windows") >= 0 && 481 System.getProperty("java.version").startsWith("1.1")) 482 haveMSLargeWritesBug = true; 483 if (DebugConn) 484 if (haveMSLargeWritesBug) 485 System.err.println("Conn: splitting large writes into 20K chunks (M$ bug)"); 486 } 487 catch (Exception e) 488 { } 489 } 490 491 492 494 500 public HTTPConnection(Applet applet) throws ProtocolNotSuppException 501 { 502 this(applet.getCodeBase().getProtocol(), 503 applet.getCodeBase().getHost(), 504 applet.getCodeBase().getPort()); 505 } 506 507 512 public HTTPConnection(String host) 513 { 514 Setup(HTTP, host, 80); 515 } 516 517 523 public HTTPConnection(String host, int port) 524 { 525 Setup(HTTP, host, port); 526 } 527 528 537 public HTTPConnection(String prot, String host, int port) throws 538 ProtocolNotSuppException 539 { 540 prot = prot.trim().toLowerCase(); 541 542 if (!prot.equals("http")) 544 throw new ProtocolNotSuppException("Unsupported protocol '" + prot + "'"); 545 546 if (prot.equals("http")) 547 Setup(HTTP, host, port); 548 else if (prot.equals("https")) 549 Setup(HTTPS, host, port); 550 else if (prot.equals("shttp")) 551 Setup(SHTTP, host, port); 552 else if (prot.equals("http-ng")) 553 Setup(HTTP_NG, host, port); 554 } 555 556 562 public HTTPConnection(URL url) throws ProtocolNotSuppException 563 { 564 this(url.getProtocol(), url.getHost(), url.getPort()); 565 } 566 567 574 private void Setup(int prot, String host, int port) 575 { 576 Protocol = prot; 577 Host = host.trim().toLowerCase(); 578 Port = port; 579 580 if (Port == -1) 581 Port = URI.defaultPort(getProtocol()); 582 583 if (Default_Proxy_Host != null && !matchNonProxy(Host)) 584 setCurrentProxy(Default_Proxy_Host, Default_Proxy_Port); 585 else 586 setCurrentProxy(null, 0); 587 588 Socks_client = Default_Socks_client; 589 Timeout = DefaultTimeout; 590 ModuleList = (Vector ) DefaultModuleList.clone(); 591 AllowUI = DefaultAllowUI; 592 if (NoKeepAlives) 593 setDefaultHeaders(new NVPair[] { new NVPair("Connection", "close") }); 594 } 595 596 597 604 private boolean matchNonProxy(String host) 605 { 606 608 if (non_proxy_host_list.get(host) != null) 609 return true; 610 611 612 614 for (int idx=0; idx<non_proxy_dom_list.size(); idx++) 615 if (host.endsWith((String ) non_proxy_dom_list.elementAt(idx))) 616 return true; 617 618 619 621 if (non_proxy_addr_list.size() == 0) 622 return false; 623 624 InetAddress [] host_addr; 625 try 626 { host_addr = InetAddress.getAllByName(host); } 627 catch (UnknownHostException uhe) 628 { return false; } 630 for (int idx=0; idx<non_proxy_addr_list.size(); idx++) 631 { 632 byte[] addr = (byte[]) non_proxy_addr_list.elementAt(idx); 633 byte[] mask = (byte[]) non_proxy_mask_list.elementAt(idx); 634 635 ip_loop: for (int idx2=0; idx2<host_addr.length; idx2++) 636 { 637 byte[] raw_addr = host_addr[idx2].getAddress(); 638 if (raw_addr.length != addr.length) continue; 639 640 for (int idx3=0; idx3<raw_addr.length; idx3++) 641 { 642 if ((raw_addr[idx3] & mask[idx3]) != (addr[idx3] & mask[idx3])) 643 continue ip_loop; 644 } 645 return true; 646 } 647 } 648 649 return false; 650 } 651 652 653 655 666 public HTTPResponse Head(String file) throws IOException , ModuleException 667 { 668 return Head(file, (String ) null, null); 669 } 670 671 683 public HTTPResponse Head(String file, NVPair form_data[]) 684 throws IOException , ModuleException 685 { 686 return Head(file, form_data, null); 687 } 688 689 702 public HTTPResponse Head(String file, NVPair[] form_data, NVPair[] headers) 703 throws IOException , ModuleException 704 { 705 String File = stripRef(file), 706 query = Codecs.nv2query(form_data); 707 if (query != null && query.length() > 0) 708 File += "?" + query; 709 710 return setupRequest("HEAD", File, headers, null, null); 711 } 712 713 725 public HTTPResponse Head(String file, String query) 726 throws IOException , ModuleException 727 { 728 return Head(file, query, null); 729 } 730 731 732 745 public HTTPResponse Head(String file, String query, NVPair[] headers) 746 throws IOException , ModuleException 747 { 748 String File = stripRef(file); 749 if (query != null && query.length() > 0) 750 File += "?" + Codecs.URLEncode(query); 751 752 return setupRequest("HEAD", File, headers, null, null); 753 } 754 755 756 765 public HTTPResponse Get(String file) throws IOException , ModuleException 766 { 767 return Get(file, (String ) null, null); 768 } 769 770 782 public HTTPResponse Get(String file, NVPair form_data[]) 783 throws IOException , ModuleException 784 { 785 return Get(file, form_data, null); 786 } 787 788 801 public HTTPResponse Get(String file, NVPair[] form_data, NVPair[] headers) 802 throws IOException , ModuleException 803 { 804 String File = stripRef(file), 805 query = Codecs.nv2query(form_data); 806 if (query != null && query.length() > 0) 807 File += "?" + query; 808 809 return setupRequest("GET", File, headers, null, null); 810 } 811 812 823 public HTTPResponse Get(String file, String query) 824 throws IOException , ModuleException 825 { 826 return Get(file, query, null); 827 } 828 829 841 public HTTPResponse Get(String file, String query, NVPair[] headers) 842 throws IOException , ModuleException 843 { 844 String File = stripRef(file); 845 if (query != null && query.length() > 0) 846 File += "?" + Codecs.URLEncode(query); 847 848 return setupRequest("GET", File, headers, null, null); 849 } 850 851 852 861 public HTTPResponse Post(String file) throws IOException , ModuleException 862 { 863 return Post(file, (byte []) null, null); 864 } 865 866 879 public HTTPResponse Post(String file, NVPair form_data[]) 880 throws IOException , ModuleException 881 { 882 NVPair[] headers = 883 { new NVPair("Content-type", "application/x-www-form-urlencoded") }; 884 885 return Post(file, Codecs.nv2query(form_data), headers); 886 } 887 888 903 public HTTPResponse Post(String file, NVPair form_data[], NVPair headers[]) 904 throws IOException , ModuleException 905 { 906 int idx; 907 for (idx=0; idx<headers.length; idx++) 908 if (headers[idx].getName().equalsIgnoreCase("Content-type")) break; 909 if (idx == headers.length) 910 { 911 headers = Util.resizeArray(headers, idx+1); 912 headers[idx] = 913 new NVPair("Content-type", "application/x-www-form-urlencoded"); 914 } 915 916 return Post(file, Codecs.nv2query(form_data), headers); 917 } 918 919 932 public HTTPResponse Post(String file, String data) 933 throws IOException , ModuleException 934 { 935 return Post(file, data, null); 936 } 937 938 949 public HTTPResponse Post(String file, String data, NVPair[] headers) 950 throws IOException , ModuleException 951 { 952 byte tmp[] = null; 953 954 if (data != null && data.length() > 0) 955 { 956 tmp = new byte[data.length()]; 957 data.getBytes(0, data.length(), tmp, 0); 958 } 959 960 return Post(file, tmp, headers); 961 } 962 963 974 public HTTPResponse Post(String file, byte data[]) 975 throws IOException , ModuleException 976 { 977 return Post(file, data, null); 978 } 979 980 991 public HTTPResponse Post(String file, byte data[], NVPair[] headers) 992 throws IOException , ModuleException 993 { 994 if (data == null) data = new byte[0]; return setupRequest("POST", stripRef(file), headers, data, null); 996 } 997 998 999 1010 public HTTPResponse Post(String file, HttpOutputStream stream) 1011 throws IOException , ModuleException 1012 { 1013 return Post(file, stream, null); 1014 } 1015 1016 1028 public HTTPResponse Post(String file, HttpOutputStream stream, 1029 NVPair[] headers) 1030 throws IOException , ModuleException 1031 { 1032 return setupRequest("POST", stripRef(file), headers, null, stream); 1033 } 1034 1035 1036 1049 public HTTPResponse Put(String file, String data) 1050 throws IOException , ModuleException 1051 { 1052 return Put(file, data, null); 1053 } 1054 1055 1067 public HTTPResponse Put(String file, String data, NVPair[] headers) 1068 throws IOException , ModuleException 1069 { 1070 byte tmp[] = null; 1071 1072 if (data != null) 1073 { 1074 tmp = new byte[data.length()]; 1075 data.getBytes(0, data.length(), tmp, 0); 1076 } 1077 1078 return Put(file, tmp, headers); 1079 } 1080 1081 1092 public HTTPResponse Put(String file, byte data[]) 1093 throws IOException , ModuleException 1094 { 1095 return Put(file, data, null); 1096 } 1097 1098 1110 public HTTPResponse Put(String file, byte data[], NVPair[] headers) 1111 throws IOException , ModuleException 1112 { 1113 if (data == null) data = new byte[0]; return setupRequest("PUT", stripRef(file), headers, data, null); 1115 } 1116 1117 1128 public HTTPResponse Put(String file, HttpOutputStream stream) 1129 throws IOException , ModuleException 1130 { 1131 return Put(file, stream, null); 1132 } 1133 1134 1146 public HTTPResponse Put(String file, HttpOutputStream stream, 1147 NVPair[] headers) 1148 throws IOException , ModuleException 1149 { 1150 return setupRequest("PUT", stripRef(file), headers, null, stream); 1151 } 1152 1153 1154 1165 public HTTPResponse Options(String file) 1166 throws IOException , ModuleException 1167 { 1168 return Options(file, null, (byte[]) null); 1169 } 1170 1171 1172 1184 public HTTPResponse Options(String file, NVPair[] headers) 1185 throws IOException , ModuleException 1186 { 1187 return Options(file, headers, (byte[]) null); 1188 } 1189 1190 1191 1204 public HTTPResponse Options(String file, NVPair[] headers, byte[] data) 1205 throws IOException , ModuleException 1206 { 1207 return setupRequest("OPTIONS", stripRef(file), headers, data, null); 1208 } 1209 1210 1211 1224 public HTTPResponse Options(String file, NVPair[] headers, 1225 HttpOutputStream stream) 1226 throws IOException , ModuleException 1227 { 1228 return setupRequest("OPTIONS", stripRef(file), headers, null, stream); 1229 } 1230 1231 1232 1241 public HTTPResponse Delete(String file) 1242 throws IOException , ModuleException 1243 { 1244 return Delete(file, null); 1245 } 1246 1247 1248 1258 public HTTPResponse Delete(String file, NVPair[] headers) 1259 throws IOException , ModuleException 1260 { 1261 return setupRequest("DELETE", stripRef(file), headers, null, null); 1262 } 1263 1264 1265 1276 public HTTPResponse Trace(String file, NVPair[] headers) 1277 throws IOException , ModuleException 1278 { 1279 return setupRequest("TRACE", stripRef(file), headers, null, null); 1280 } 1281 1282 1283 1292 public HTTPResponse Trace(String file) 1293 throws IOException , ModuleException 1294 { 1295 return Trace(file, null); 1296 } 1297 1298 1299 1312 public HTTPResponse ExtensionMethod(String method, String file, 1313 byte[] data, NVPair[] headers) 1314 throws IOException , ModuleException 1315 { 1316 return setupRequest(method.trim(), stripRef(file), headers, data, null); 1317 } 1318 1319 1320 1333 public HTTPResponse ExtensionMethod(String method, String file, 1334 HttpOutputStream os, NVPair[] headers) 1335 throws IOException , ModuleException 1336 { 1337 return setupRequest(method.trim(), stripRef(file), headers, null, os); 1338 } 1339 1340 1341 1352 public void stop() 1353 { 1354 for (Request req = (Request) RequestList.enumerate(); req != null; 1355 req = (Request) RequestList.next()) 1356 req.aborted = true; 1357 1358 for (StreamDemultiplexor demux = 1359 (StreamDemultiplexor) DemuxList.enumerate(); 1360 demux != null; demux = (StreamDemultiplexor) DemuxList.next()) 1361 demux.abort(); 1362 } 1363 1364 1365 1386 public void setDefaultHeaders(NVPair[] headers) 1387 { 1388 int length = (headers == null ? 0 : headers.length); 1389 NVPair[] def_hdrs = new NVPair[length]; 1390 1391 int sidx, didx; 1393 for (sidx=0, didx=0; sidx<length; sidx++) 1394 { 1395 String name = headers[sidx].getName().trim(); 1396 if (name.equalsIgnoreCase("Content-length") || 1397 name.equalsIgnoreCase("Host")) 1398 continue; 1399 1400 def_hdrs[didx++] = headers[sidx]; 1401 } 1402 1403 if (didx < length) 1404 def_hdrs = Util.resizeArray(DefaultHeaders, didx); 1405 1406 synchronized (DefaultHeaders) 1407 { DefaultHeaders = def_hdrs; } 1408 } 1409 1410 1411 1416 public NVPair[] getDefaultHeaders() 1417 { 1418 1420 synchronized (DefaultHeaders) 1421 { 1422 NVPair[] headers = new NVPair[DefaultHeaders.length]; 1423 System.arraycopy(DefaultHeaders, 0, headers, 0, headers.length); 1424 return headers; 1425 } 1426 } 1427 1428 1429 1434 public String getProtocol() 1435 { 1436 switch (Protocol) 1437 { 1438 case HTTP: return "http"; 1439 case HTTPS: return "https"; 1440 case SHTTP: return "shttp"; 1441 case HTTP_NG: return "http-ng"; 1442 default: 1443 throw new Error ("HTTPClient Internal Error: invalid protocol " + 1444 Protocol); 1445 } 1446 } 1447 1448 1449 1454 public String getHost() 1455 { 1456 return Host; 1457 } 1458 1459 1460 1466 public int getPort() 1467 { 1468 return Port; 1469 } 1470 1471 1472 1477 public String getProxyHost() 1478 { 1479 return Proxy_Host; 1480 } 1481 1482 1483 1488 public int getProxyPort() 1489 { 1490 return Proxy_Port; 1491 } 1492 1493 1494 1503 public boolean isCompatibleWith(URI uri) 1504 { 1505 if (!uri.getScheme().equals(getProtocol()) || 1506 !uri.getHost().equalsIgnoreCase(Host)) 1507 return false; 1508 1509 int port = uri.getPort(); 1510 if (port == -1) 1511 port = URI.defaultPort(uri.getScheme()); 1512 return port == Port; 1513 } 1514 1515 1516 1530 public void setRawMode(boolean raw) 1531 { 1532 String [] modules = { "HTTPClient.CookieModule", 1534 "HTTPClient.RedirectionModule", 1535 "HTTPClient.AuthorizationModule", 1536 "HTTPClient.DefaultModule", 1537 "HTTPClient.TransferEncodingModule", 1538 "HTTPClient.ContentMD5Module", 1539 "HTTPClient.ContentEncodingModule"}; 1540 1541 for (int idx=0; idx<modules.length; idx++) 1542 { 1543 try 1544 { 1545 if (raw) 1546 removeModule(Class.forName(modules[idx])); 1547 else 1548 addModule(Class.forName(modules[idx]), -1); 1549 } 1550 catch (ClassNotFoundException cnfe) { } 1551 } 1552 } 1553 1554 1555 1562 public static void setDefaultTimeout(int time) 1563 { 1564 DefaultTimeout = time; 1565 } 1566 1567 1568 1574 public static int getDefaultTimeout() 1575 { 1576 return DefaultTimeout; 1577 } 1578 1579 1580 1614 public void setTimeout(int time) 1615 { 1616 Timeout = time; 1617 } 1618 1619 1620 1626 public int getTimeout() 1627 { 1628 return Timeout; 1629 } 1630 1631 1632 1638 public void setAllowUserInteraction(boolean allow) 1639 { 1640 AllowUI = allow; 1641 } 1642 1643 1649 public boolean getAllowUserInteraction() 1650 { 1651 return AllowUI; 1652 } 1653 1654 1655 1660 public static void setDefaultAllowUserInteraction(boolean allow) 1661 { 1662 DefaultAllowUI = allow; 1663 } 1664 1665 1670 public static boolean getDefaultAllowUserInteraction() 1671 { 1672 return DefaultAllowUI; 1673 } 1674 1675 1676 1681 public static Class [] getDefaultModules() 1682 { 1683 synchronized(DefaultModuleList) 1684 { 1685 Class [] modules = new Class [DefaultModuleList.size()]; 1686 DefaultModuleList.copyInto(modules); 1687 return modules; 1688 } 1689 } 1690 1691 1728 public static boolean addDefaultModule(Class module, int pos) 1729 { 1730 try 1732 { HTTPClientModule tmp = (HTTPClientModule) module.newInstance(); } 1733 catch (RuntimeException re) 1734 { throw re; } 1735 catch (Exception e) 1736 { throw new RuntimeException (e.toString()); } 1737 1738 synchronized(DefaultModuleList) 1739 { 1740 if (DefaultModuleList.contains(module)) 1742 return false; 1743 1744 if (pos < 0) 1746 DefaultModuleList.insertElementAt(module, 1747 DefaultModuleList.size()+pos+1); 1748 else 1749 DefaultModuleList.insertElementAt(module, pos); 1750 } 1751 1752 if (DebugConn) 1753 System.err.println("Conn: Added module " + module.getName() + 1754 " to default list"); 1755 1756 return true; 1757 } 1758 1759 1760 1767 public static boolean removeDefaultModule(Class module) 1768 { 1769 boolean removed = DefaultModuleList.removeElement(module); 1770 1771 if (DebugConn) 1772 if (removed) 1773 System.err.println("Conn: Removed module " + module.getName() + 1774 " from default list"); 1775 1776 return removed; 1777 } 1778 1779 1780 1785 public Class [] getModules() 1786 { 1787 synchronized(ModuleList) 1788 { 1789 Class [] modules = new Class [ModuleList.size()]; 1790 ModuleList.copyInto(modules); 1791 return modules; 1792 } 1793 } 1794 1795 1796 1817 public boolean addModule(Class module, int pos) 1818 { 1819 try 1821 { HTTPClientModule tmp = (HTTPClientModule) module.newInstance(); } 1822 catch (RuntimeException re) 1823 { throw re; } 1824 catch (Exception e) 1825 { throw new RuntimeException (e.toString()); } 1826 1827 synchronized(ModuleList) 1828 { 1829 if (ModuleList.contains(module)) 1831 return false; 1832 1833 if (pos < 0) 1835 ModuleList.insertElementAt(module, ModuleList.size()+pos+1); 1836 else 1837 ModuleList.insertElementAt(module, pos); 1838 } 1839 1840 return true; 1841 } 1842 1843 1844 1851 public boolean removeModule(Class module) 1852 { 1853 if (module == null) return false; 1854 return ModuleList.removeElement(module); 1855 } 1856 1857 1858 1884 public void setContext(Object context) 1885 { 1886 if (context == null) 1887 throw new IllegalArgumentException ("Context must be non-null"); 1888 if (Context != null) 1889 throw new RuntimeException ("Context already set"); 1890 1891 Context = context; 1892 } 1893 1894 1895 1902 public Object getContext() 1903 { 1904 if (Context != null) 1905 return Context; 1906 else 1907 return dflt_context; 1908 } 1909 1910 1911 1917 static Object getDefaultContext() 1918 { 1919 return dflt_context; 1920 } 1921 1922 1923 1936 public void addDigestAuthorization(String realm, String user, String passwd) 1937 { 1938 AuthorizationInfo.addDigestAuthorization(Host, Port, realm, user, 1939 passwd, getContext()); 1940 } 1941 1942 1943 1956 public void addBasicAuthorization(String realm, String user, String passwd) 1957 { 1958 AuthorizationInfo.addBasicAuthorization(Host, Port, realm, user, 1959 passwd, getContext()); 1960 } 1961 1962 1963 1988 public static void setProxyServer(String host, int port) 1989 { 1990 if (host == null || host.trim().length() == 0) 1991 Default_Proxy_Host = null; 1992 else 1993 { 1994 Default_Proxy_Host = host.trim().toLowerCase(); 1995 Default_Proxy_Port = port; 1996 } 1997 } 1998 1999 2000 2015 public synchronized void setCurrentProxy(String host, int port) 2016 { 2017 if (host == null || host.trim().length() == 0) 2018 Proxy_Host = null; 2019 else 2020 { 2021 Proxy_Host = host.trim().toLowerCase(); 2022 if (port <= 0) 2023 Proxy_Port = 80; 2024 else 2025 Proxy_Port = port; 2026 } 2027 2028 switch(Protocol) 2030 { 2031 case HTTP: 2032 case HTTPS: 2033 if (force_1_0) 2034 { 2035 ServerProtocolVersion = HTTP_1_0; 2036 ServProtVersKnown = true; 2037 RequestProtocolVersion = "HTTP/1.0"; 2038 } 2039 else 2040 { 2041 ServerProtocolVersion = HTTP_1_1; 2042 ServProtVersKnown = false; 2043 RequestProtocolVersion = "HTTP/1.1"; 2044 } 2045 break; 2046 case HTTP_NG: 2047 ServerProtocolVersion = -1; 2048 ServProtVersKnown = false; 2049 RequestProtocolVersion = ""; 2050 break; 2051 case SHTTP: 2052 ServerProtocolVersion = -1; 2053 ServProtVersKnown = false; 2054 RequestProtocolVersion = "Secure-HTTP/1.3"; 2055 break; 2056 default: 2057 throw new Error ("HTTPClient Internal Error: invalid protocol " + 2058 Protocol); 2059 } 2060 2061 KeepAliveUnknown = true; 2062 DoesKeepAlive = false; 2063 2064 input_demux = null; 2065 early_stall = null; 2066 late_stall = null; 2067 prev_resp = null; 2068 } 2069 2070 2071 2099 public static void dontProxyFor(String host) throws ParseException 2100 { 2101 host = host.trim().toLowerCase(); 2102 2103 2105 if (host.charAt(0) == '.') 2106 { 2107 if (!non_proxy_dom_list.contains(host)) 2108 non_proxy_dom_list.addElement(host); 2109 return; 2110 } 2111 2112 2113 2115 for (int idx=0; idx<host.length(); idx++) 2116 { 2117 if (!Character.isDigit(host.charAt(idx)) && 2118 host.charAt(idx) != '.' && host.charAt(idx) != '/') 2119 { 2120 non_proxy_host_list.put(host, ""); 2121 return; 2122 } 2123 } 2124 2125 2126 2128 byte[] ip_addr; 2129 byte[] ip_mask; 2130 int slash; 2131 if ((slash = host.indexOf('/')) != -1) { 2133 ip_addr = string2arr(host.substring(0, slash)); 2134 ip_mask = string2arr(host.substring(slash+1)); 2135 if (ip_addr.length != ip_mask.length) 2136 throw new ParseException("length of IP-address (" + 2137 ip_addr.length + ") != length of netmask (" + 2138 ip_mask.length + ")"); 2139 } 2140 else 2141 { 2142 ip_addr = string2arr(host); 2143 ip_mask = new byte[ip_addr.length]; 2144 for (int idx=0; idx<ip_mask.length; idx++) 2145 ip_mask[idx] = (byte) 255; 2146 } 2147 2148 2149 2151 ip_loop: for (int idx=0; idx<non_proxy_addr_list.size(); idx++) 2152 { 2153 byte[] addr = (byte[]) non_proxy_addr_list.elementAt(idx); 2154 byte[] mask = (byte[]) non_proxy_mask_list.elementAt(idx); 2155 if (addr.length != ip_addr.length) continue; 2156 2157 for (int idx2=0; idx2<addr.length; idx2++) 2158 { 2159 if ((ip_addr[idx2] & mask[idx2]) != (addr[idx2] & mask[idx2]) || 2160 (mask[idx2] != ip_mask[idx2])) 2161 continue ip_loop; 2162 } 2163 2164 return; } 2166 non_proxy_addr_list.addElement(ip_addr); 2167 non_proxy_mask_list.addElement(ip_mask); 2168 } 2169 2170 2171 2179 public static void dontProxyFor(String [] hosts) 2180 { 2181 if (hosts == null || hosts.length == 0) 2182 return; 2183 2184 for (int idx=0; idx<hosts.length; idx++) 2185 { 2186 try 2187 { 2188 if (hosts[idx] != null) 2189 dontProxyFor(hosts[idx]); 2190 } 2191 catch(ParseException pe) 2192 { 2193 } 2195 } 2196 } 2197 2198 2199 2210 public static boolean doProxyFor(String host) throws ParseException 2211 { 2212 host = host.trim().toLowerCase(); 2213 2214 2216 if (host.charAt(0) == '.') 2217 return non_proxy_dom_list.removeElement(host); 2218 2219 2220 2222 for (int idx=0; idx<host.length(); idx++) 2223 { 2224 if (!Character.isDigit(host.charAt(idx)) && 2225 host.charAt(idx) != '.' && host.charAt(idx) != '/') 2226 return (non_proxy_host_list.remove(host) != null); 2227 } 2228 2229 2230 2232 byte[] ip_addr; 2233 byte[] ip_mask; 2234 int slash; 2235 if ((slash = host.indexOf('/')) != -1) { 2237 ip_addr = string2arr(host.substring(0, slash)); 2238 ip_mask = string2arr(host.substring(slash+1)); 2239 if (ip_addr.length != ip_mask.length) 2240 throw new ParseException("length of IP-address (" + 2241 ip_addr.length + ") != length of netmask (" + 2242 ip_mask.length + ")"); 2243 } 2244 else 2245 { 2246 ip_addr = string2arr(host); 2247 ip_mask = new byte[ip_addr.length]; 2248 for (int idx=0; idx<ip_mask.length; idx++) 2249 ip_mask[idx] = (byte) 255; 2250 } 2251 2252 ip_loop: for (int idx=0; idx<non_proxy_addr_list.size(); idx++) 2253 { 2254 byte[] addr = (byte[]) non_proxy_addr_list.elementAt(idx); 2255 byte[] mask = (byte[]) non_proxy_mask_list.elementAt(idx); 2256 if (addr.length != ip_addr.length) continue; 2257 2258 for (int idx2=0; idx2<addr.length; idx2++) 2259 { 2260 if ((ip_addr[idx2] & mask[idx2]) != (addr[idx2] & mask[idx2]) || 2261 (mask[idx2] != ip_mask[idx2])) 2262 continue ip_loop; 2263 } 2264 2265 non_proxy_addr_list.removeElementAt(idx); 2266 non_proxy_mask_list.removeElementAt(idx); 2267 return true; 2268 } 2269 return false; 2270 } 2271 2272 2273 2280 private static byte[] string2arr(String ip) 2281 { 2282 byte[] arr; 2283 char[] ip_char = new char[ip.length()]; 2284 ip.getChars(0, ip_char.length, ip_char, 0); 2285 2286 int cnt = 0; 2287 for (int idx=0; idx<ip_char.length; idx++) 2288 if (ip_char[idx] == '.') cnt++; 2289 arr = new byte[cnt+1]; 2290 2291 cnt = 0; 2292 int pos = 0; 2293 for (int idx=0; idx<ip_char.length; idx++) 2294 if (ip_char[idx] == '.') 2295 { 2296 arr[cnt] = (byte) Integer.parseInt(ip.substring(pos, idx)); 2297 cnt++; 2298 pos = idx+1; 2299 } 2300 arr[cnt] = (byte) Integer.parseInt(ip.substring(pos)); 2301 2302 return arr; 2303 } 2304 2305 2306 2319 public static void setSocksServer(String host) 2320 { 2321 setSocksServer(host, 1080); 2322 } 2323 2324 2325 2338 public static void setSocksServer(String host, int port) 2339 { 2340 if (port <= 0) 2341 port = 1080; 2342 2343 if (host == null || host.length() == 0) 2344 Default_Socks_client = null; 2345 else 2346 Default_Socks_client = new SocksClient(host, port); 2347 } 2348 2349 2350 2396 public static void setSocksServer(String host, int port, int version) 2397 throws SocksException 2398 { 2399 if (port <= 0) 2400 port = 1080; 2401 2402 if (host == null || host.length() == 0) 2403 Default_Socks_client = null; 2404 else 2405 Default_Socks_client = new SocksClient(host, port, version); 2406 } 2407 2408 2409 2416 private final String stripRef(String file) 2417 { 2418 if (file == null) return ""; 2419 2420 int hash = file.indexOf('#'); 2421 if (hash != -1) 2422 file = file.substring(0,hash); 2423 2424 return file.trim(); 2425 } 2426 2427 2428 2430 2443 private HTTPResponse setupRequest(String method, String resource, 2444 NVPair[] headers, byte[] entity, 2445 HttpOutputStream stream) 2446 throws IOException , ModuleException 2447 { 2448 Request req = new Request(this, method, resource, 2449 mergedHeaders(headers), entity, stream, 2450 AllowUI); 2451 RequestList.addToEnd(req); 2452 2453 try 2454 { 2455 HTTPResponse resp = new HTTPResponse(gen_mod_insts(), Timeout, req); 2456 handleRequest(req, resp, null, true); 2457 return resp; 2458 } 2459 finally 2460 { RequestList.remove(req); } 2461 } 2462 2463 2464 2475 private NVPair[] mergedHeaders(NVPair[] spec) 2476 { 2477 int spec_len = (spec != null ? spec.length : 0), 2478 defs_len; 2479 NVPair[] merged; 2480 2481 synchronized (DefaultHeaders) 2482 { 2483 defs_len = (DefaultHeaders != null ? DefaultHeaders.length : 0); 2484 merged = new NVPair[spec_len + defs_len]; 2485 2486 System.arraycopy(DefaultHeaders, 0, merged, 0, defs_len); 2488 } 2489 2490 int sidx, didx = defs_len; 2492 for (sidx=0; sidx<spec_len; sidx++) 2493 { 2494 String s_name = spec[sidx].getName().trim(); 2495 if (s_name.equalsIgnoreCase("Content-length") || 2496 s_name.equalsIgnoreCase("Host")) 2497 continue; 2498 2499 int search; 2500 for (search=0; search<didx; search++) 2501 { 2502 if (merged[search].getName().trim().equalsIgnoreCase(s_name)) 2503 break; 2504 } 2505 2506 merged[search] = spec[sidx]; 2507 if (search == didx) didx++; 2508 } 2509 2510 if (didx < merged.length) 2511 merged = Util.resizeArray(merged, didx); 2512 2513 return merged; 2514 } 2515 2516 2517 2520 private HTTPClientModule[] gen_mod_insts() 2521 { 2522 synchronized (ModuleList) 2523 { 2524 HTTPClientModule[] mod_insts = 2525 new HTTPClientModule[ModuleList.size()]; 2526 2527 for (int idx=0; idx<ModuleList.size(); idx++) 2528 { 2529 Class mod = (Class ) ModuleList.elementAt(idx); 2530 try 2531 { mod_insts[idx] = (HTTPClientModule) mod.newInstance(); } 2532 catch (Exception e) 2533 { 2534 throw new Error ("HTTPClient Internal Error: could not " + 2535 "create instance of " + mod.getName() + 2536 " -\n" + e); 2537 } 2538 } 2539 2540 return mod_insts; 2541 } 2542 } 2543 2544 2545 2557 void handleRequest(Request req, HTTPResponse http_resp, Response resp, 2558 boolean usemodules) 2559 throws IOException , ModuleException 2560 { 2561 Response[] rsp_arr = { resp }; 2562 HTTPClientModule[] modules = http_resp.getModules(); 2563 2564 2565 2567 if (usemodules) 2568 doModules: for (int idx=0; idx<modules.length; idx++) 2569 { 2570 int sts = modules[idx].requestHandler(req, rsp_arr); 2571 switch (sts) 2572 { 2573 case REQ_CONTINUE: break; 2575 2576 case REQ_RESTART: idx = -1; 2578 continue doModules; 2579 2580 case REQ_SHORTCIRC: break doModules; 2582 2583 case REQ_RESPONSE: case REQ_RETURN: if (rsp_arr[0] == null) 2586 throw new Error ("HTTPClient Internal Error: no " + 2587 "response returned by module " + 2588 modules[idx].getClass().getName()); 2589 http_resp.set(req, rsp_arr[0]); 2590 if (req.getStream() != null) 2591 req.getStream().ignoreData(req); 2592 if (req.internal_subrequest) return; 2593 if (sts == REQ_RESPONSE) 2594 http_resp.handleResponse(); 2595 else 2596 http_resp.init(rsp_arr[0]); 2597 return; 2598 2599 case REQ_NEWCON_RST: if (req.internal_subrequest) return; 2601 req.getConnection(). 2602 handleRequest(req, http_resp, rsp_arr[0], true); 2603 return; 2604 2605 case REQ_NEWCON_SND: if (req.internal_subrequest) return; 2607 req.getConnection(). 2608 handleRequest(req, http_resp, rsp_arr[0], false); 2609 return; 2610 2611 default: throw new Error ("HTTPClient Internal Error: invalid status"+ 2613 " " + sts + " returned by module " + 2614 modules[idx].getClass().getName()); 2615 } 2616 } 2617 2618 if (req.internal_subrequest) return; 2619 2620 2621 2623 if (req.getStream() != null && req.getStream().getLength() == -1) 2624 { 2625 if (!ServProtVersKnown || ServerProtocolVersion < HTTP_1_1 || 2626 no_chunked) 2627 { 2628 req.getStream().goAhead(req, null, http_resp.getTimeout()); 2629 http_resp.set(req, req.getStream()); 2630 } 2631 else 2632 { 2633 int idx; 2635 NVPair[] hdrs = req.getHeaders(); 2636 for (idx=0; idx<hdrs.length; idx++) 2637 if (hdrs[idx].getName().equalsIgnoreCase("Transfer-Encoding")) 2638 break; 2639 2640 if (idx == hdrs.length) 2641 { 2642 hdrs = Util.resizeArray(hdrs, idx+1); 2643 hdrs[idx] = new NVPair("Transfer-Encoding", "chunked"); 2644 req.setHeaders(hdrs); 2645 } 2646 else 2647 { 2648 String v = hdrs[idx].getValue(); 2649 try 2650 { 2651 if (!Util.hasToken(v, "chunked")) 2652 hdrs[idx] = new NVPair("Transfer-Encoding", 2653 v + ", chunked"); 2654 } 2655 catch (ParseException pe) 2656 { throw new IOException (pe.toString()); } 2657 } 2658 2659 http_resp.set(req, sendRequest(req, http_resp.getTimeout())); 2660 } 2661 } 2662 else 2663 http_resp.set(req, sendRequest(req, http_resp.getTimeout())); 2664 2665 if (req.aborted) throw new IOException ("Request aborted by user"); 2666 } 2667 2668 2669 2670 private Response early_stall = null; 2671 private Response late_stall = null; 2672 private Response prev_resp = null; 2673 2674 private boolean output_finished = true; 2675 2676 2690 Response sendRequest(Request req, int con_timeout) 2691 throws IOException , ModuleException 2692 { 2693 ByteArrayOutputStream hdr_buf = new ByteArrayOutputStream (600); 2694 Response resp = null; 2695 boolean keep_alive; 2696 2697 2698 2702 if (early_stall != null) 2703 { 2704 try 2705 { 2706 if (DebugConn) 2707 System.err.println("Conn: Early-stalling Request: " + 2708 req.getMethod() + " " + 2709 req.getRequestURI()); 2710 2711 synchronized(early_stall) 2712 { 2713 try 2715 { early_stall.getVersion(); } 2716 catch (IOException ioe) 2717 { } 2718 early_stall = null; 2719 } 2720 } 2721 catch (NullPointerException npe) 2722 { } 2723 } 2724 2725 2726 String [] con_hdrs = assembleHeaders(req, hdr_buf); 2727 2728 2729 2732 try 2733 { 2734 if (ServerProtocolVersion >= HTTP_1_1 && 2735 !Util.hasToken(con_hdrs[0], "close") 2736 || 2737 ServerProtocolVersion == HTTP_1_0 && 2738 Util.hasToken(con_hdrs[0], "keep-alive") 2739 ) 2740 keep_alive = true; 2741 else 2742 keep_alive = false; 2743 } 2744 catch (ParseException pe) 2745 { throw new IOException (pe.toString()); } 2746 2747 2748 synchronized(this) 2749 { 2750 2754 if (late_stall != null) 2755 { 2756 if (input_demux != null || KeepAliveUnknown) 2757 { 2758 if (DebugConn) 2759 System.err.println("Conn: Stalling Request: " + 2760 req.getMethod() + " " + req.getRequestURI()); 2761 2762 try { 2764 late_stall.getVersion(); 2765 if (KeepAliveUnknown) 2766 determineKeepAlive(late_stall); 2767 } 2768 catch (IOException ioe) 2769 { } 2770 } 2771 2772 late_stall = null; 2773 } 2774 2775 2776 2782 if ((req.getMethod().equals("POST") || req.dont_pipeline) && 2783 prev_resp != null && input_demux != null) 2784 { 2785 if (DebugConn) 2786 System.err.println("Conn: Stalling Request: " + 2787 req.getMethod() + " " + req.getRequestURI()); 2788 2789 try { prev_resp.getVersion(); } 2791 catch (IOException ioe) 2792 { } 2793 } 2794 2795 2796 2799 if (!output_finished) 2800 { 2801 try 2802 { wait(); } 2803 catch (InterruptedException ie) 2804 { throw new IOException (ie.toString()); } 2805 } 2806 2807 2808 if (req.aborted) throw new IOException ("Request aborted by user"); 2809 2810 int try_count = 3; 2811 2819 2820 while (try_count-- > 0) 2821 { 2822 try 2823 { 2824 2826 Socket sock; 2827 if (input_demux == null || 2828 (sock = input_demux.getSocket()) == null) 2829 { 2830 sock = getSocket(con_timeout); 2831 2832 if (Protocol == HTTPS) 2833 { 2834 if (Proxy_Host != null) 2835 { 2836 Socket [] sarr = { sock }; 2837 resp = enableSSLTunneling(sarr, req, con_timeout); 2838 if (resp != null) 2839 { 2840 resp.final_resp = true; 2841 return resp; 2842 } 2843 sock = sarr[0]; 2844 } 2845 2846 } 2848 2849 input_demux = new StreamDemultiplexor(Protocol, sock, this); 2850 DemuxList.addToEnd(input_demux); 2851 KeepAliveReqLeft = KeepAliveReqMax; 2852 } 2853 2854 if (req.aborted) 2855 throw new IOException ("Request aborted by user"); 2856 2857 if (DebugConn) 2858 { 2859 System.err.println("Conn: Sending Request: "); 2860 System.err.println(); 2861 hdr_buf.writeTo(System.err); 2862 } 2863 2864 2865 2867 OutputStream sock_out = sock.getOutputStream(); 2868 if (haveMSLargeWritesBug) 2869 sock_out = new MSLargeWritesBugStream(sock_out); 2870 2871 hdr_buf.writeTo(sock_out); 2872 2873 2874 2876 try 2877 { 2878 if (ServProtVersKnown && 2879 ServerProtocolVersion >= HTTP_1_1 && 2880 Util.hasToken(con_hdrs[1], "100-continue")) 2881 { 2882 resp = new Response(req, (Proxy_Host != null && Protocol != HTTPS), input_demux); 2883 resp.timeout = 60; 2884 if (resp.getContinue() != 100) 2885 break; 2886 } 2887 } 2888 catch (ParseException pe) 2889 { throw new IOException (pe.toString()); } 2890 catch (InterruptedIOException iioe) 2891 { } 2892 finally 2893 { if (resp != null) resp.timeout = 0; } 2894 2895 2896 2898 if (req.getData() != null && req.getData().length > 0) 2899 { 2900 if (req.delay_entity > 0) 2901 { 2902 2905 long num_units = req.delay_entity / 100; 2906 long one_unit = req.delay_entity / num_units; 2907 2908 for (int idx=0; idx<num_units; idx++) 2909 { 2910 if (input_demux.available(null) != 0) 2911 break; 2912 try { Thread.sleep(one_unit); } 2913 catch (InterruptedException ie) { } 2914 } 2915 2916 if (input_demux.available(null) == 0) 2917 sock_out.write(req.getData()); else 2919 keep_alive = false; } 2921 else 2922 sock_out.write(req.getData()); 2923 } 2924 2925 if (req.getStream() != null) 2926 req.getStream().goAhead(req, sock_out, 0); 2927 else 2928 sock_out.flush(); 2929 2930 2931 2934 if (resp == null) 2935 resp = new Response(req, (Proxy_Host != null && 2936 Protocol != HTTPS), 2937 input_demux); 2938 } 2939 catch (IOException ioe) 2940 { 2941 if (DebugConn) 2942 { 2943 System.err.print("Conn: "); 2944 ioe.printStackTrace(); 2945 } 2946 2947 closeDemux(ioe, true); 2948 2949 if (try_count == 0 || ioe instanceof UnknownHostException || 2950 ioe instanceof InterruptedIOException || req.aborted) 2951 throw ioe; 2952 2953 if (DebugConn) 2954 System.err.println("Conn: Retrying request"); 2955 continue; 2956 } 2957 2958 break; 2959 } 2960 2961 prev_resp = resp; 2962 2963 2964 2966 if ((!KeepAliveUnknown && !DoesKeepAlive) || !keep_alive || 2967 (KeepAliveReqMax != -1 && KeepAliveReqLeft-- == 0)) 2968 { 2969 input_demux.markForClose(resp); 2970 input_demux = null; 2971 } 2972 else 2973 input_demux.restartTimer(); 2974 2975 if (DebugConn) 2976 { 2977 if (KeepAliveReqMax != -1) 2978 System.err.println("Conn: Number of requests left: "+ 2979 KeepAliveReqLeft); 2980 } 2981 2982 2983 2986 if (!ServProtVersKnown) 2987 { early_stall = resp; resp.markAsFirstResponse(req); } 2988 2989 2999 if (KeepAliveUnknown || 3000 !IdempotentSequence.methodIsIdempotent(req.getMethod()) || 3002 req.dont_pipeline || NeverPipeline) { late_stall = resp; } 3005 3006 3007 3011 if (req.getStream() != null) 3012 output_finished = false; 3013 else 3014 { 3015 output_finished = true; 3016 notify(); 3017 } 3018 3019 3020 3022 if (DebugConn) System.err.println("Conn: Request sent"); 3023 } 3024 3025 return resp; 3026 } 3027 3028 3029 3037 private Socket getSocket(int con_timeout) throws IOException 3038 { 3039 Socket sock = null; 3040 3041 String actual_host; 3042 int actual_port; 3043 3044 if (Proxy_Host != null) 3045 { 3046 actual_host = Proxy_Host; 3047 actual_port = Proxy_Port; 3048 } 3049 else 3050 { 3051 actual_host = Host; 3052 actual_port = Port; 3053 } 3054 3055 if (DebugConn) 3056 System.err.println("Conn: Creating Socket: " + actual_host + ":" + 3057 actual_port); 3058 3059 if (con_timeout == 0) { 3061 if (Socks_client != null) 3062 sock = Socks_client.getSocket(actual_host, actual_port); 3063 else 3064 { 3065 InetAddress [] addr_list = InetAddress.getAllByName(actual_host); 3067 for (int idx=0; idx<addr_list.length; idx++) 3068 { 3069 try 3070 { 3071 sock = new Socket (addr_list[idx], actual_port); 3072 break; } 3074 catch (SocketException se) { 3076 if (idx == addr_list.length-1) 3077 throw se; } 3079 } 3080 } 3081 } 3082 else 3083 { 3084 EstablishConnection con = 3085 new EstablishConnection(actual_host, actual_port, Socks_client); 3086 con.start(); 3087 try 3088 { con.join((long) con_timeout); } 3089 catch (InterruptedException ie) 3090 { } 3091 3092 if (con.getException() != null) 3093 throw con.getException(); 3094 if ((sock = con.getSocket()) == null) 3095 { 3096 con.forget(); 3097 if ((sock = con.getSocket()) == null) 3098 throw new InterruptedIOException ("Connection establishment timed out"); 3099 } 3100 } 3101 3102 return sock; 3103 } 3104 3105 3106 3118 private Response enableSSLTunneling(Socket [] sock, Request req, int timeout) 3119 throws IOException , ModuleException 3120 { 3121 3123 Vector hdrs = new Vector (); 3124 for (int idx=0; idx<req.getHeaders().length; idx++) 3125 { 3126 String name = req.getHeaders()[idx].getName(); 3127 if (name.equalsIgnoreCase("User-Agent") || 3128 name.equalsIgnoreCase("Proxy-Authorization")) 3129 hdrs.addElement(req.getHeaders()[idx]); 3130 } 3131 3132 3133 3135 NVPair[] h = new NVPair[hdrs.size()]; 3136 hdrs.copyInto(h); 3137 Request connect = new Request(this, "CONNECT", Host+":"+Port, h, 3138 null, null, req.allowUI()); 3139 connect.internal_subrequest = true; 3140 3141 ByteArrayOutputStream hdr_buf = new ByteArrayOutputStream (600); 3142 HTTPResponse r = new HTTPResponse(gen_mod_insts(), timeout, connect); 3143 3144 3145 3147 Response resp = null; 3148 3149 while (true) 3150 { 3151 handleRequest(connect, r, resp, true); 3152 3153 hdr_buf.reset(); 3154 assembleHeaders(connect, hdr_buf); 3155 3156 if (DebugConn) 3157 { 3158 System.err.println("Conn: Sending SSL-Tunneling Subrequest: "); 3159 System.err.println(); 3160 hdr_buf.writeTo(System.err); 3161 } 3162 3163 3164 3166 hdr_buf.writeTo(sock[0].getOutputStream()); 3167 3168 3169 3171 resp = new Response(connect, sock[0].getInputStream()); 3172 if (resp.getStatusCode() == 200) return null; 3173 3174 3175 3177 3179 try 3180 { resp.getData(); } 3181 catch (IOException ioe) 3182 { } 3183 try 3184 { sock[0].close(); } 3185 catch (IOException ioe) 3186 { } 3187 3188 3189 3191 r.set(connect, resp); 3192 if (!r.handleResponse()) return resp; 3193 3194 sock[0] = getSocket(timeout); 3195 } 3196 } 3197 3198 3199 3243 private String [] assembleHeaders(Request req, 3244 ByteArrayOutputStream hdr_buf) 3245 throws IOException 3246 { 3247 DataOutputStream dataout = new DataOutputStream (hdr_buf); 3248 String [] con_hdrs = { "", "" }; 3249 NVPair[] hdrs = req.getHeaders(); 3250 3251 3252 3253 3255 String file = Util.escapeUnsafeChars(req.getRequestURI()); 3256 if (Proxy_Host != null && Protocol != HTTPS && !file.equals("*")) 3257 dataout.writeBytes(req.getMethod() + " http://" + Host + ":" + Port+ 3258 file + " " + RequestProtocolVersion + "\r\n"); 3259 else 3260 dataout.writeBytes(req.getMethod() + " " + file + " " + 3261 RequestProtocolVersion + "\r\n"); 3262 3263 if (Port != 80) 3264 dataout.writeBytes("Host: " + Host + ":" + Port + "\r\n"); 3265 else dataout.writeBytes("Host: " + Host + "\r\n"); 3267 3268 3269 3271 int ct_idx = -1, 3272 ua_idx = -1, 3273 co_idx = -1, 3274 pc_idx = -1, 3275 ka_idx = -1, 3276 ex_idx = -1, 3277 te_idx = -1, 3278 tc_idx = -1, 3279 ug_idx = -1; 3280 for (int idx=0; idx<hdrs.length; idx++) 3281 { 3282 String name = hdrs[idx].getName().trim(); 3283 if (name.equalsIgnoreCase("Content-Type")) ct_idx = idx; 3284 else if (name.equalsIgnoreCase("User-Agent")) ua_idx = idx; 3285 else if (name.equalsIgnoreCase("Connection")) co_idx = idx; 3286 else if (name.equalsIgnoreCase("Proxy-Connection")) pc_idx = idx; 3287 else if (name.equalsIgnoreCase("Keep-Alive")) ka_idx = idx; 3288 else if (name.equalsIgnoreCase("Expect")) ex_idx = idx; 3289 else if (name.equalsIgnoreCase("TE")) te_idx = idx; 3290 else if (name.equalsIgnoreCase("Transfer-Encoding")) tc_idx = idx; 3291 else if (name.equalsIgnoreCase("Upgrade")) ug_idx = idx; 3292 } 3293 3294 3295 3313 3314 String co_hdr = null; 3315 if (!(ServProtVersKnown && ServerProtocolVersion >= HTTP_1_1 && 3316 co_idx == -1)) 3317 { 3318 if (co_idx == -1) 3319 { co_hdr = "Keep-Alive"; 3321 con_hdrs[0] = "Keep-Alive"; 3322 } 3323 else 3324 { 3325 con_hdrs[0] = hdrs[co_idx].getValue().trim(); 3326 co_hdr = con_hdrs[0]; 3327 } 3328 3329 try 3330 { 3331 if (ka_idx != -1 && 3332 Util.hasToken(con_hdrs[0], "keep-alive")) 3333 dataout.writeBytes("Keep-Alive: " + 3334 hdrs[ka_idx].getValue().trim() + "\r\n"); 3335 } 3336 catch (ParseException pe) 3337 { 3338 throw new IOException (pe.toString()); 3339 } 3340 } 3341 3342 if ((Proxy_Host != null && Protocol != HTTPS) && 3343 !(ServProtVersKnown && ServerProtocolVersion >= HTTP_1_1)) 3344 { 3345 if (co_hdr != null) 3346 { 3347 dataout.writeBytes("Proxy-Connection: "); 3348 dataout.writeBytes(co_hdr); 3349 dataout.writeBytes("\r\n"); 3350 co_hdr = null; 3351 } 3352 } 3353 3354 if (co_hdr != null) 3355 { 3356 try 3357 { 3358 if (!Util.hasToken(co_hdr, "TE")) 3359 co_hdr += ", TE"; 3360 } 3361 catch (ParseException pe) 3362 { throw new IOException (pe.toString()); } 3363 } 3364 else 3365 co_hdr = "TE"; 3366 3367 if (ug_idx != -1) 3368 co_hdr += ", Upgrade"; 3369 3370 if (co_hdr != null) 3371 { 3372 dataout.writeBytes("Connection: "); 3373 dataout.writeBytes(co_hdr); 3374 dataout.writeBytes("\r\n"); 3375 } 3376 3377 3378 3379 3381 if (te_idx != -1) 3382 { 3383 dataout.writeBytes("TE: "); 3384 Vector pte; 3385 try 3386 { pte = Util.parseHeader(hdrs[te_idx].getValue()); } 3387 catch (ParseException pe) 3388 { throw new IOException (pe.toString()); } 3389 3390 if (!pte.contains(new HttpHeaderElement("trailers"))) 3391 dataout.writeBytes("trailers, "); 3392 3393 dataout.writeBytes(hdrs[te_idx].getValue().trim() + "\r\n"); 3394 } 3395 else 3396 dataout.writeBytes("TE: trailers\r\n"); 3397 3398 3399 3401 if (ua_idx != -1) 3402 dataout.writeBytes("User-Agent: " + hdrs[ua_idx].getValue().trim() + " " 3403 + version + "\r\n"); 3404 else 3405 dataout.writeBytes("User-Agent: " + version + "\r\n"); 3406 3407 3408 3410 for (int idx=0; idx<hdrs.length; idx++) 3411 { 3412 if (idx != ct_idx && idx != ua_idx && idx != co_idx && 3413 idx != pc_idx && idx != ka_idx && idx != ex_idx && 3414 idx != te_idx) 3415 dataout.writeBytes(hdrs[idx].getName().trim() + ": " + 3416 hdrs[idx].getValue().trim() + "\r\n"); 3417 } 3418 3419 3420 3422 if (req.getData() != null || req.getStream() != null) 3423 { 3424 dataout.writeBytes("Content-type: "); 3425 if (ct_idx != -1) 3426 dataout.writeBytes(hdrs[ct_idx].getValue().trim()); 3427 else 3428 dataout.writeBytes("application/octet-stream"); 3429 dataout.writeBytes("\r\n"); 3430 3431 if (req.getData() != null) 3432 dataout.writeBytes("Content-length: " +req.getData().length + 3433 "\r\n"); 3434 else if (req.getStream().getLength() != -1 && tc_idx == -1) 3435 dataout.writeBytes("Content-length: " + 3436 req.getStream().getLength() + "\r\n"); 3437 3438 if (ex_idx != -1) 3439 { 3440 con_hdrs[1] = hdrs[ex_idx].getValue().trim(); 3441 dataout.writeBytes("Expect: " + con_hdrs[1] + "\r\n"); 3442 } 3443 } 3444 else if (ex_idx != -1) 3445 { 3446 Vector expect_tokens; 3447 try 3448 { expect_tokens = Util.parseHeader(hdrs[ex_idx].getValue()); } 3449 catch (ParseException pe) 3450 { throw new IOException (pe.toString()); } 3451 3452 3453 3455 HttpHeaderElement cont = new HttpHeaderElement("100-continue"); 3456 while (expect_tokens.removeElement(cont)) ; 3457 3458 3459 3461 if (!expect_tokens.isEmpty()) 3462 { 3463 con_hdrs[1] = Util.assembleHeader(expect_tokens); 3464 dataout.writeBytes("Expect: " + con_hdrs[1] + "\r\n"); 3465 } 3466 } 3467 3468 dataout.writeBytes("\r\n"); 3470 return con_hdrs; 3471 } 3472 3473 3474 3481 boolean handleFirstRequest(Request req, Response resp) throws IOException 3482 { 3483 3486 ServerProtocolVersion = String2ProtVers(resp.getVersion()); 3487 ServProtVersKnown = true; 3488 3489 3500 if ((Proxy_Host != null && Protocol != HTTPS) && 3501 resp.getHeader("Via") == null) 3502 ServerProtocolVersion = HTTP_1_0; 3503 3504 if (DebugConn) 3505 System.err.println("Conn: Protocol Version established: " + 3506 ProtVers2String(ServerProtocolVersion)); 3507 3508 3509 3512 if (ServerProtocolVersion == HTTP_1_0 && 3513 (resp.getStatusCode() == 400 || resp.getStatusCode() == 500)) 3514 { 3515 input_demux.markForClose(resp); 3516 input_demux = null; 3517 RequestProtocolVersion = "HTTP/1.0"; 3518 return false; 3519 } 3520 3521 return true; 3522 } 3523 3524 3525 private void determineKeepAlive(Response resp) throws IOException 3526 { 3527 3529 String con; 3530 3531 try 3532 { 3533 if (ServerProtocolVersion >= HTTP_1_1 || 3534 ( 3535 ( 3536 ((Proxy_Host == null || Protocol == HTTPS) && 3537 (con = resp.getHeader("Connection")) != null) 3538 || 3539 ((Proxy_Host != null && Protocol != HTTPS) && 3540 (con = resp.getHeader("Proxy-Connection")) != null) 3541 ) && 3542 Util.hasToken(con, "keep-alive") 3543 ) 3544 ) 3545 { 3546 DoesKeepAlive = true; 3547 3548 if (DebugConn) 3549 System.err.println("Conn: Keep-Alive enabled"); 3550 3551 KeepAliveUnknown = false; 3552 } 3553 else if (resp.getStatusCode() < 400) 3554 KeepAliveUnknown = false; 3555 3556 3557 3559 if (DoesKeepAlive && ServerProtocolVersion == HTTP_1_0 && 3560 (con = resp.getHeader("Keep-Alive")) != null) 3561 { 3562 HttpHeaderElement max = 3563 Util.getElement(Util.parseHeader(con), "max"); 3564 if (max != null && max.getValue() != null) 3565 { 3566 KeepAliveReqMax = Integer.parseInt(max.getValue()); 3567 KeepAliveReqLeft = KeepAliveReqMax; 3568 3569 if (DebugConn) 3570 System.err.println("Conn: Max Keep-Alive requests: "+ 3571 KeepAliveReqMax); 3572 } 3573 } 3574 } 3575 catch (ParseException pe) { } 3576 catch (NumberFormatException nfe) { } 3577 catch (ClassCastException cce) { } 3578 } 3579 3580 3581 synchronized void outputFinished() 3582 { 3583 output_finished = true; 3584 notify(); 3585 } 3586 3587 3588 synchronized void closeDemux(IOException ioe, boolean was_reset) 3589 { 3590 if (input_demux != null) input_demux.close(ioe, was_reset); 3591 3592 early_stall = null; 3593 late_stall = null; 3594 prev_resp = null; 3595 } 3596 3597 3598 final static String ProtVers2String(int prot_vers) 3599 { 3600 return "HTTP/" + (prot_vers >>> 16) + "." + (prot_vers & 0xFFFF); 3601 } 3602 3603 final static int String2ProtVers(String prot_vers) 3604 { 3605 String vers = prot_vers.substring(5); 3606 int dot = vers.indexOf('.'); 3607 return Integer.parseInt(vers.substring(0, dot)) << 16 | 3608 Integer.parseInt(vers.substring(dot+1)); 3609 } 3610 3611 3612 3617 public String toString() 3618 { 3619 return getProtocol() + "://" + getHost() + 3620 (getPort() != URI.defaultPort(getProtocol()) ? ":" + getPort() : ""); 3621 } 3622 3623 3624 private class EstablishConnection extends Thread 3625 { 3626 String actual_host; 3627 int actual_port; 3628 IOException exception; 3629 Socket sock; 3630 SocksClient Socks_client; 3631 boolean close; 3632 3633 3634 EstablishConnection(String host, int port, SocksClient socks) 3635 { 3636 super("EstablishConnection (" + host + ":" + port + ")"); 3637 try { setDaemon(true); } 3638 catch (SecurityException se) { } 3640 actual_host = host; 3641 actual_port = port; 3642 Socks_client = socks; 3643 3644 exception = null; 3645 sock = null; 3646 close = false; 3647 } 3648 3649 3650 public void run() 3651 { 3652 try 3653 { 3654 if (Socks_client != null) 3655 sock = Socks_client.getSocket(actual_host, actual_port); 3656 else 3657 { 3658 InetAddress [] addr_list = InetAddress.getAllByName(actual_host); 3660 for (int idx=0; idx<addr_list.length; idx++) 3661 { 3662 try 3663 { 3664 sock = new Socket (addr_list[idx], actual_port); 3665 break; } 3667 catch (SocketException se) { 3669 if (idx == addr_list.length-1 || close) 3670 throw se; } 3672 } 3673 } 3674 } 3675 catch (IOException ioe) 3676 { 3677 exception = ioe; 3678 } 3679 3680 if (close && sock != null) 3681 { 3682 try 3683 { sock.close(); } 3684 catch (IOException ioe) 3685 { } 3686 sock = null; 3687 } 3688 } 3689 3690 3691 IOException getException() 3692 { 3693 return exception; 3694 } 3695 3696 3697 Socket getSocket() 3698 { 3699 return sock; 3700 } 3701 3702 3703 void forget() 3704 { 3705 close = true; 3706 } 3707 } 3708 3709 3710 3715 private class MSLargeWritesBugStream extends FilterOutputStream 3716 { 3717 private final int CHUNK_SIZE = 20000; 3718 3719 MSLargeWritesBugStream(OutputStream os) 3720 { 3721 super(os); 3722 } 3723 3724 public void write(byte[] b, int off, int len) throws IOException 3725 { 3726 while (len > CHUNK_SIZE) 3727 { 3728 out.write(b, off, CHUNK_SIZE); 3729 off += CHUNK_SIZE; 3730 len -= CHUNK_SIZE; 3731 } 3732 out.write(b, off, len); 3733 } 3734 } 3735} 3736 3737 | Popular Tags |