1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 package HTTPClient;
38
39 import java.io.OutputStream;
40 import java.io.DataOutputStream;
41 import java.io.FilterOutputStream;
42 import java.io.ByteArrayOutputStream;
43 import java.io.IOException;
44 import java.io.InterruptedIOException;
45 import java.net.URL;
46 import java.net.Socket;
47 import java.net.InetAddress;
48 import java.net.SocketException;
49 import java.net.ConnectException;
50 import java.net.UnknownHostException;
51 import java.net.NoRouteToHostException;
52 import java.util.Vector;
53 import java.util.concurrent.atomic.AtomicLong;
54 import java.applet.Applet;
55
56 import javax.net.ssl.SSLSocket;
57 import javax.net.ssl.SSLException;
58 import javax.net.ssl.SSLSocketFactory;
59 import javax.security.cert.X509Certificate;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 public class HTTPConnection implements GlobalConstants, HTTPClientModuleConstants
207 {
208
209 public final static String version = "RPT-HTTPClient/0.3-3E";
210
211
212 private final static Object dflt_context = new Object();
213
214
215 private Object Context = null;
216
217
218 private int Protocol;
219
220
221 int ServerProtocolVersion;
222
223
224 boolean ServProtVersKnown;
225
226
227
228 private String RequestProtocolVersion;
229
230
231 private String Host;
232
233
234 private int Port;
235
236
237 private InetAddress LocalAddr;
238
239
240 private int LocalPort;
241
242
243 private String Proxy_Host = null;
244
245
246 private int Proxy_Port;
247
248
249 private static String Default_Proxy_Host = null;
250
251
252 private static int Default_Proxy_Port;
253
254
255 private static CIHashtable non_proxy_host_list = new CIHashtable();
256 private static Vector non_proxy_dom_list = new Vector();
257 private static Vector non_proxy_addr_list = new Vector();
258 private static Vector non_proxy_mask_list = new Vector();
259
260
261 private SocksClient Socks_client = null;
262
263
264 private static SocksClient Default_Socks_client = null;
265
266
267 private StreamDemultiplexor input_demux = null;
268
269
270 LinkedList DemuxList = new LinkedList();
271
272
273 private LinkedList RequestList = new LinkedList();
274
275
276 private boolean doesKeepAlive = false;
277
278
279 private boolean keepAliveUnknown = true;
280
281
282 private int keepAliveReqMax = -1;
283
284
285 private int keepAliveReqLeft;
286
287
288 private static boolean no_chunked = false;
289
290
291 private static boolean force_1_0 = false;
292
293
294 private static boolean neverPipeline = false;
295
296
297 private static boolean noKeepAlives = false;
298
299
300 private static boolean haveMSLargeWritesBug = false;
301
302
303
304 static boolean deferStreamed = false;
305
306
307
308 private static boolean noTrailers = false;
309
310
311 private AtomicLong DNS_time = new AtomicLong();
312
313
314 private AtomicLong con_time = new AtomicLong();
315 private AtomicLong connectionsEstablished = new AtomicLong();
316
317 public interface TimeAuthority {
318 long getTimeInMilliseconds();
319 }
320
321 private static TimeAuthority standardTimeAuthority =
322 new TimeAuthority() {
323 public long getTimeInMilliseconds() {
324 return System.currentTimeMillis();
325 }
326 };
327
328 private TimeAuthority timeAuthority = standardTimeAuthority;
329
330 public void setTimeAuthority(TimeAuthority timeAuthority) {
331 this.timeAuthority = timeAuthority;
332 }
333
334 public TimeAuthority getTimeAuthority() {
335 return timeAuthority;
336 }
337
338
339
340 private static int DefaultTimeout = 0;
341
342
343 private int Timeout;
344
345
346 private NVPair[] DefaultHeaders = new NVPair[0];
347
348
349 private static Vector DefaultModuleList;
350
351
352 private Vector ModuleList;
353
354
355 private static boolean defaultAllowUI = true;
356
357
358 private boolean allowUI;
359
360
361 private static SSLSocketFactory defaultSSLFactory =
362 (SSLSocketFactory) SSLSocketFactory.getDefault();
363
364
365 private SSLSocketFactory sslFactory;
366
367
368 static
369 {
370
371
372
373
374
375 try
376 {
377 String host = System.getProperty("http.proxyHost");
378 if (host == null)
379 throw new Exception();
380 int port = Integer.getInteger("http.proxyPort", -1).intValue();
381
382 Log.write(Log.CONN, "Conn: using proxy " + host + ":" + port);
383 setProxyServer(host, port);
384 }
385 catch (Exception e)
386 {
387 try
388 {
389 if (Boolean.getBoolean("proxySet"))
390 {
391 String host = System.getProperty("proxyHost");
392 int port = Integer.getInteger("proxyPort", -1).intValue();
393 Log.write(Log.CONN, "Conn: using proxy " + host + ":" + port);
394 setProxyServer(host, port);
395 }
396 }
397 catch (Exception ee)
398 { Default_Proxy_Host = null; }
399 }
400
401
402
403
404
405 try
406 {
407 String hosts = System.getProperty("HTTPClient.nonProxyHosts");
408 if (hosts == null)
409 hosts = System.getProperty("http.nonProxyHosts");
410
411 String[] list = Util.splitProperty(hosts);
412 dontProxyFor(list);
413 }
414 catch (Exception e)
415 { }
416
417
418
419
420
421
422
423
424 try
425 {
426 String host = System.getProperty("HTTPClient.socksHost");
427 if (host != null && host.length() > 0)
428 {
429 int port = Integer.getInteger("HTTPClient.socksPort", -1).intValue();
430 int version = Integer.getInteger("HTTPClient.socksVersion", -1).intValue();
431 Log.write(Log.CONN, "Conn: using SOCKS " + host + ":" + port);
432 if (version == -1)
433 setSocksServer(host, port);
434 else
435 setSocksServer(host, port, version);
436 }
437 }
438 catch (Exception e)
439 { Default_Socks_client = null; }
440
441
442
443
444 String modules = "HTTPClient.RetryModule|" +
445 "HTTPClient.CookieModule|" +
446 "HTTPClient.RedirectionModule|" +
447 "HTTPClient.AuthorizationModule|" +
448 "HTTPClient.DefaultModule|" +
449 "HTTPClient.TransferEncodingModule|" +
450 "HTTPClient.ContentMD5Module|" +
451 "HTTPClient.ContentEncodingModule";
452
453 boolean in_applet = false;
454 try
455 { modules = System.getProperty("HTTPClient.Modules", modules); }
456 catch (SecurityException se)
457 { in_applet = true; }
458
459 DefaultModuleList = new Vector();
460 String[] list = Util.splitProperty(modules);
461 for (int idx=0; idx<list.length; idx++)
462 {
463 try
464 {
465 DefaultModuleList.addElement(Class.forName(list[idx]));
466 Log.write(Log.CONN, "Conn: added module " + list[idx]);
467 }
468 catch (ClassNotFoundException cnfe)
469 {
470 if (!in_applet)
471 throw new NoClassDefFoundError(cnfe.getMessage());
472
473
474
475
476
477
478
479 }
480 }
481
482
483
484
485
486 try
487 {
488 neverPipeline = Boolean.getBoolean("HTTPClient.disable_pipelining");
489 if (neverPipeline)
490 Log.write(Log.CONN, "Conn: disabling pipelining");
491 }
492 catch (Exception e)
493 { }
494
495
496
497
498 try
499 {
500 noKeepAlives = Boolean.getBoolean("HTTPClient.disableKeepAlives");
501 if (noKeepAlives)
502 Log.write(Log.CONN, "Conn: disabling keep-alives");
503 }
504 catch (Exception e)
505 { }
506
507
508
509
510 try
511 {
512 force_1_0 = Boolean.getBoolean("HTTPClient.forceHTTP_1.0");
513 if (force_1_0)
514 Log.write(Log.CONN, "Conn: forcing HTTP/1.0 requests");
515 }
516 catch (Exception e)
517 { }
518
519
520
521
522 try
523 {
524 no_chunked = Boolean.getBoolean("HTTPClient.dontChunkRequests");
525 if (no_chunked)
526 Log.write(Log.CONN, "Conn: never chunking requests");
527 }
528 catch (Exception e)
529 { }
530
531
532
533
534 try
535 {
536 if (System.getProperty("os.name").indexOf("Windows") >= 0 &&
537 System.getProperty("java.version").startsWith("1.1"))
538 haveMSLargeWritesBug = true;
539 if (haveMSLargeWritesBug)
540 Log.write(Log.CONN, "Conn: splitting large writes into 20K chunks (M$ bug)");
541 }
542 catch (Exception e)
543 { }
544
545
546
547
548
549 try
550 {
551 noTrailers = Boolean.getBoolean("HTTPClient.disableTrailers");
552 if (noTrailers)
553 Log.write(Log.CONN, "Conn: disabling trailers");
554 }
555 catch (Exception e)
556 { }
557
558
559
560
561
562
563
564
565 try
566 {
567 deferStreamed = Boolean.getBoolean("HTTPClient.deferStreamed");
568 if (deferStreamed)
569 Log.write(Log.CONN, "Conn: enabling defered handling of " +
570 "responses to streamed requests");
571 }
572 catch (Exception e)
573 { }
574 }
575
576
577 private static final String[] sslCipherSuites;
578 private static final String[] sslProtocols;
579
580 static {
581 final String cipherSuiteProperty =
582 System.getProperty("https.cipherSuites");
583
584 if (cipherSuiteProperty != null) {
585 sslCipherSuites = cipherSuiteProperty.split(",");
586 }
587 else {
588 sslCipherSuites = defaultSSLFactory.getSupportedCipherSuites();
589 }
590
591 final String protocolProperty = System.getProperty("https.protocols");
592
593 if (protocolProperty != null) {
594 sslProtocols = protocolProperty.split(",");
595 }
596 else {
597 try {
598 final SSLSocket socket = (SSLSocket)defaultSSLFactory.createSocket();
599 sslProtocols = socket.getSupportedProtocols();
600 socket.close();
601 }
602 catch (IOException e) {
603 throw new ExceptionInInitializerError(e);
604 }
605 }
606 }
607
608
609
610
611
612
613
614
615
616
617 public static String[] getSSLCipherSuites() {
618 return sslCipherSuites;
619 }
620
621
622
623
624
625
626
627
628
629
630 public static String[] getSSLProtocols() {
631 return sslProtocols;
632 }
633
634
635
636
637
638
639
640
641
642
643 public HTTPConnection(Applet applet) throws ProtocolNotSuppException
644 {
645 this(applet.getCodeBase().getProtocol(),
646 applet.getCodeBase().getHost(),
647 applet.getCodeBase().getPort());
648 }
649
650
651
652
653
654
655 public HTTPConnection(String host)
656 {
657 Setup(HTTP, host, 80, null, -1);
658 }
659
660
661
662
663
664
665
666 public HTTPConnection(String host, int port)
667 {
668 Setup(HTTP, host, port, null, -1);
669 }
670
671
672
673
674
675
676
677
678
679
680 public HTTPConnection(String prot, String host, int port)
681 throws ProtocolNotSuppException
682 {
683 this(prot, host, port, null, -1);
684 }
685
686
687
688
689
690
691
692
693
694
695
696
697
698 public HTTPConnection(String prot, String host, int port,
699 InetAddress localAddr, int localPort)
700 throws ProtocolNotSuppException
701 {
702 prot = prot.trim().toLowerCase();
703
704 if (!prot.equals("http") && !prot.equals("https"))
705 throw new ProtocolNotSuppException("Unsupported protocol '" + prot + "'");
706
707 if (prot.equals("http"))
708 Setup(HTTP, host, port, localAddr, localPort);
709 else if (prot.equals("https"))
710 Setup(HTTPS, host, port, localAddr, localPort);
711 else if (prot.equals("shttp"))
712 Setup(SHTTP, host, port, localAddr, localPort);
713 else if (prot.equals("http-ng"))
714 Setup(HTTP_NG, host, port, localAddr, localPort);
715 }
716
717
718
719
720
721
722
723 public HTTPConnection(URL url) throws ProtocolNotSuppException
724 {
725 this(url.getProtocol(), url.getHost(), url.getPort());
726 }
727
728
729
730
731
732
733
734 public HTTPConnection(URI uri) throws ProtocolNotSuppException
735 {
736 this(uri.getScheme(), uri.getHost(), uri.getPort());
737 }
738
739
740
741
742
743
744
745
746
747
748 private void Setup(int prot, String host, int port, InetAddress localAddr,
749 int localPort)
750 {
751 Protocol = prot;
752 Host = host.trim().toLowerCase();
753 Port = port;
754 LocalAddr = localAddr;
755 LocalPort = localPort;
756
757 if (Port == -1)
758 Port = URI.defaultPort(getProtocol());
759
760 if (Default_Proxy_Host != null && !matchNonProxy(Host))
761 setCurrentProxy(Default_Proxy_Host, Default_Proxy_Port);
762 else
763 setCurrentProxy(null, 0);
764
765 Socks_client = Default_Socks_client;
766 Timeout = DefaultTimeout;
767 ModuleList = (Vector) DefaultModuleList.clone();
768 allowUI = defaultAllowUI;
769 if (noKeepAlives)
770 setDefaultHeaders(new NVPair[] { new NVPair("Connection", "close") });
771 sslFactory = defaultSSLFactory;
772 }
773
774
775
776
777
778
779
780
781
782 private boolean matchNonProxy(String host)
783 {
784
785
786 if (non_proxy_host_list.get(host) != null)
787 return true;
788
789
790
791
792 for (int idx=0; idx<non_proxy_dom_list.size(); idx++)
793 if (host.endsWith((String) non_proxy_dom_list.elementAt(idx)))
794 return true;
795
796
797
798
799 if (non_proxy_addr_list.size() == 0)
800 return false;
801
802 InetAddress[] host_addr;
803 try
804 { host_addr = InetAddress.getAllByName(host); }
805 catch (UnknownHostException uhe)
806 { return false; }
807
808 for (int idx=0; idx<non_proxy_addr_list.size(); idx++)
809 {
810 byte[] addr = (byte[]) non_proxy_addr_list.elementAt(idx);
811 byte[] mask = (byte[]) non_proxy_mask_list.elementAt(idx);
812
813 ip_loop: for (int idx2=0; idx2<host_addr.length; idx2++)
814 {
815 byte[] raw_addr = host_addr[idx2].getAddress();
816 if (raw_addr.length != addr.length) continue;
817
818 for (int idx3=0; idx3<raw_addr.length; idx3++)
819 {
820 if ((raw_addr[idx3] & mask[idx3]) != (addr[idx3] & mask[idx3]))
821 continue ip_loop;
822 }
823 return true;
824 }
825 }
826
827 return false;
828 }
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844 public HTTPResponse Head(String file) throws IOException, ModuleException
845 {
846 return Head(file, (String) null, null);
847 }
848
849
850
851
852
853
854
855
856
857
858
859
860
861 public HTTPResponse Head(String file, NVPair form_data[])
862 throws IOException, ModuleException
863 {
864 return Head(file, form_data, null);
865 }
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880 public HTTPResponse Head(String file, NVPair[] form_data, NVPair[] headers)
881 throws IOException, ModuleException
882 {
883 String File = stripRef(file),
884 query = Codecs.nv2query(form_data);
885 if (query != null && query.length() > 0)
886 File += "?" + query;
887
888 return setupRequest("HEAD", File, headers, null, null);
889 }
890
891
892
893
894
895
896
897
898
899
900
901
902
903 public HTTPResponse Head(String file, String query)
904 throws IOException, ModuleException
905 {
906 return Head(file, query, null);
907 }
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923 public HTTPResponse Head(String file, String query, NVPair[] headers)
924 throws IOException, ModuleException
925 {
926 String File = stripRef(file);
927 if (query != null && query.length() > 0)
928 File += "?" + Codecs.URLEncode(query);
929
930 return setupRequest("HEAD", File, headers, null, null);
931 }
932
933
934
935
936
937
938
939
940
941
942
943 public HTTPResponse Get(String file) throws IOException, ModuleException
944 {
945 return Get(file, (String) null, null);
946 }
947
948
949
950
951
952
953
954
955
956
957
958
959
960 public HTTPResponse Get(String file, NVPair form_data[])
961 throws IOException, ModuleException
962 {
963 return Get(file, form_data, null);
964 }
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979 public HTTPResponse Get(String file, NVPair[] form_data, NVPair[] headers)
980 throws IOException, ModuleException
981 {
982 String File = stripRef(file),
983 query = Codecs.nv2query(form_data);
984 if (query != null && query.length() > 0)
985 File += "?" + query;
986
987 return setupRequest("GET", File, headers, null, null);
988 }
989
990
991
992
993
994
995
996
997
998
999
1000
1001 public HTTPResponse Get(String file, String query)
1002 throws IOException, ModuleException
1003 {
1004 return Get(file, query, null);
1005 }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 public HTTPResponse Get(String file, String query, NVPair[] headers)
1020 throws IOException, ModuleException
1021 {
1022 String File = stripRef(file);
1023 if (query != null && query.length() > 0)
1024 File += "?" + Codecs.URLEncode(query);
1025
1026 return setupRequest("GET", File, headers, null, null);
1027 }
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039 public HTTPResponse Post(String file) throws IOException, ModuleException
1040 {
1041 return Post(file, (byte []) null, null);
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 public HTTPResponse Post(String file, NVPair form_data[])
1058 throws IOException, ModuleException
1059 {
1060 NVPair[] headers =
1061
1062
1063 { new NVPair("Content-Type", "application/x-www-form-urlencoded") };
1064
1065
1066 return Post(file, Codecs.nv2query(form_data), headers);
1067 }
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 public HTTPResponse Post(String file, NVPair form_data[], NVPair headers[])
1085 throws IOException, ModuleException
1086 {
1087 int idx;
1088 for (idx=0; idx<headers.length; idx++)
1089 if (headers[idx] != null &&
1090 headers[idx].getName().equalsIgnoreCase("Content-type")) break;
1091 if (idx == headers.length)
1092 {
1093 headers = Util.resizeArray(headers, idx+1);
1094 headers[idx] =
1095
1096
1097 new NVPair("Content-Type", "application/x-www-form-urlencoded");
1098
1099 }
1100
1101 return Post(file, Codecs.nv2query(form_data), headers);
1102 }
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117 public HTTPResponse Post(String file, String data)
1118 throws IOException, ModuleException
1119 {
1120 return Post(file, data, null);
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 public HTTPResponse Post(String file, String data, NVPair[] headers)
1136 throws IOException, ModuleException
1137 {
1138 byte tmp[] = null;
1139
1140 if (data != null && data.length() > 0)
1141 tmp = data.getBytes();
1142
1143 return Post(file, tmp, headers);
1144 }
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 public HTTPResponse Post(String file, byte data[])
1158 throws IOException, ModuleException
1159 {
1160 return Post(file, data, null);
1161 }
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174 public HTTPResponse Post(String file, byte data[], NVPair[] headers)
1175 throws IOException, ModuleException
1176 {
1177 if (data == null) data = new byte[0];
1178 return setupRequest("POST", stripRef(file), headers, data, null);
1179 }
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 public HTTPResponse Post(String file, HttpOutputStream stream)
1194 throws IOException, ModuleException
1195 {
1196 return Post(file, stream, null);
1197 }
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211 public HTTPResponse Post(String file, HttpOutputStream stream,
1212 NVPair[] headers)
1213 throws IOException, ModuleException
1214 {
1215 return setupRequest("POST", stripRef(file), headers, null, stream);
1216 }
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232 public HTTPResponse Put(String file, String data)
1233 throws IOException, ModuleException
1234 {
1235 return Put(file, data, null);
1236 }
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251 public HTTPResponse Put(String file, String data, NVPair[] headers)
1252 throws IOException, ModuleException
1253 {
1254 byte tmp[] = null;
1255
1256 if (data != null && data.length() > 0)
1257 tmp = data.getBytes();
1258
1259 return Put(file, tmp, headers);
1260 }
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 public HTTPResponse Put(String file, byte data[])
1274 throws IOException, ModuleException
1275 {
1276 return Put(file, data, null);
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291 public HTTPResponse Put(String file, byte data[], NVPair[] headers)
1292 throws IOException, ModuleException
1293 {
1294 if (data == null) data = new byte[0];
1295 return setupRequest("PUT", stripRef(file), headers, data, null);
1296 }
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309 public HTTPResponse Put(String file, HttpOutputStream stream)
1310 throws IOException, ModuleException
1311 {
1312 return Put(file, stream, null);
1313 }
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327 public HTTPResponse Put(String file, HttpOutputStream stream,
1328 NVPair[] headers)
1329 throws IOException, ModuleException
1330 {
1331 return setupRequest("PUT", stripRef(file), headers, null, stream);
1332 }
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 public HTTPResponse Options(String file)
1347 throws IOException, ModuleException
1348 {
1349 return Options(file, null, (byte[]) null);
1350 }
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 public HTTPResponse Options(String file, NVPair[] headers)
1366 throws IOException, ModuleException
1367 {
1368 return Options(file, headers, (byte[]) null);
1369 }
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385 public HTTPResponse Options(String file, NVPair[] headers, byte[] data)
1386 throws IOException, ModuleException
1387 {
1388 return setupRequest("OPTIONS", stripRef(file), headers, data, null);
1389 }
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405 public HTTPResponse Options(String file, NVPair[] headers,
1406 HttpOutputStream stream)
1407 throws IOException, ModuleException
1408 {
1409 return setupRequest("OPTIONS", stripRef(file), headers, null, stream);
1410 }
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422 public HTTPResponse Delete(String file)
1423 throws IOException, ModuleException
1424 {
1425 return Delete(file, null);
1426 }
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439 public HTTPResponse Delete(String file, NVPair[] headers)
1440 throws IOException, ModuleException
1441 {
1442 return setupRequest("DELETE", stripRef(file), headers, null, null);
1443 }
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 public HTTPResponse Trace(String file, NVPair[] headers)
1458 throws IOException, ModuleException
1459 {
1460 return setupRequest("TRACE", stripRef(file), headers, null, null);
1461 }
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473 public HTTPResponse Trace(String file)
1474 throws IOException, ModuleException
1475 {
1476 return Trace(file, null);
1477 }
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493 public HTTPResponse ExtensionMethod(String method, String file,
1494 byte[] data, NVPair[] headers)
1495 throws IOException, ModuleException
1496 {
1497 return setupRequest(method.trim(), stripRef(file), headers, data, null);
1498 }
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 public HTTPResponse ExtensionMethod(String method, String file,
1515 HttpOutputStream os, NVPair[] headers)
1516 throws IOException, ModuleException
1517 {
1518 return setupRequest(method.trim(), stripRef(file), headers, null, os);
1519 }
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535 public void stop()
1536 {
1537 for (Request req = (Request) RequestList.enumerate(); req != null;
1538 req = (Request) RequestList.next())
1539 req.aborted = true;
1540
1541 for (StreamDemultiplexor demux =
1542 (StreamDemultiplexor) DemuxList.enumerate();
1543 demux != null; demux = (StreamDemultiplexor) DemuxList.next())
1544 demux.abort();
1545 }
1546
1547
1548
1549
1550
1551
1552
1553 public static void setDefaultSSLSocketFactory(SSLSocketFactory sslFactory)
1554 {
1555 defaultSSLFactory = sslFactory;
1556 }
1557
1558
1559
1560
1561
1562
1563 public static SSLSocketFactory getDefaultSSLSocketFactory()
1564 {
1565 return defaultSSLFactory;
1566 }
1567
1568
1569
1570
1571
1572
1573
1574 public void setSSLSocketFactory(SSLSocketFactory sslFactory)
1575 {
1576 this.sslFactory = sslFactory;
1577 }
1578
1579
1580
1581
1582
1583
1584 public SSLSocketFactory getSSLSocketFactory()
1585 {
1586 return sslFactory;
1587 }
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610 public void setDefaultHeaders(NVPair[] headers)
1611 {
1612 int length = (headers == null ? 0 : headers.length);
1613 NVPair[] def_hdrs = new NVPair[length];
1614
1615
1616 int sidx, didx;
1617 for (sidx=0, didx=0; sidx<length; sidx++)
1618 {
1619 if (headers[sidx] == null)
1620 continue;
1621
1622 String name = headers[sidx].getName().trim();
1623 if (name.equalsIgnoreCase("Content-length"))
1624 continue;
1625
1626 def_hdrs[didx++] = headers[sidx];
1627 }
1628
1629 if (didx < length)
1630 def_hdrs = Util.resizeArray(def_hdrs, didx);
1631
1632 synchronized (DefaultHeaders)
1633 { DefaultHeaders = def_hdrs; }
1634 }
1635
1636
1637
1638
1639
1640
1641
1642 public NVPair[] getDefaultHeaders()
1643 {
1644 synchronized (DefaultHeaders)
1645 {
1646 return (NVPair[]) DefaultHeaders.clone();
1647 }
1648 }
1649
1650
1651
1652
1653
1654
1655
1656 public String getProtocol()
1657 {
1658 switch (Protocol)
1659 {
1660 case HTTP: return "http";
1661 case HTTPS: return "https";
1662 case SHTTP: return "shttp";
1663 case HTTP_NG: return "http-ng";
1664 default:
1665 throw new Error("HTTPClient Internal Error: invalid protocol " +
1666 Protocol);
1667 }
1668 }
1669
1670
1671
1672
1673
1674
1675
1676 public String getHost()
1677 {
1678 return Host;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688 public int getPort()
1689 {
1690 return Port;
1691 }
1692
1693
1694
1695
1696
1697
1698
1699 public String getProxyHost()
1700 {
1701 return Proxy_Host;
1702 }
1703
1704
1705
1706
1707
1708
1709
1710 public int getProxyPort()
1711 {
1712 return Proxy_Port;
1713 }
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725 public boolean isCompatibleWith(URI uri)
1726 {
1727 if (!uri.getScheme().equals(getProtocol()) ||
1728 !uri.getHost().equalsIgnoreCase(Host))
1729 return false;
1730
1731 int port = uri.getPort();
1732 if (port == -1)
1733 port = URI.defaultPort(uri.getScheme());
1734 return port == Port;
1735 }
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752 public void setRawMode(boolean raw)
1753 {
1754
1755 String[] modules = { "HTTPClient.CookieModule",
1756 "HTTPClient.RedirectionModule",
1757 "HTTPClient.AuthorizationModule",
1758 "HTTPClient.DefaultModule",
1759 "HTTPClient.TransferEncodingModule",
1760 "HTTPClient.ContentMD5Module",
1761 "HTTPClient.ContentEncodingModule"};
1762
1763 for (int idx=0; idx<modules.length; idx++)
1764 {
1765 try
1766 {
1767 if (raw)
1768 removeModule(Class.forName(modules[idx]));
1769 else
1770 addModule(Class.forName(modules[idx]), -1);
1771 }
1772 catch (ClassNotFoundException cnfe) { }
1773 }
1774 }
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784 public static void setDefaultTimeout(int time)
1785 {
1786 DefaultTimeout = time;
1787 }
1788
1789
1790
1791
1792
1793
1794
1795
1796 public static int getDefaultTimeout()
1797 {
1798 return DefaultTimeout;
1799 }
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833 public void setTimeout(int time)
1834 {
1835 Timeout = time;
1836 }
1837
1838
1839
1840
1841
1842
1843
1844
1845 public int getTimeout()
1846 {
1847 return Timeout;
1848 }
1849
1850
1851
1852
1853
1854
1855
1856
1857 public void setAllowUserInteraction(boolean allow)
1858 {
1859 allowUI = allow;
1860 }
1861
1862
1863
1864
1865
1866
1867
1868 public boolean getAllowUserInteraction()
1869 {
1870 return allowUI;
1871 }
1872
1873
1874
1875
1876
1877
1878
1879 public static void setDefaultAllowUserInteraction(boolean allow)
1880 {
1881 defaultAllowUI = allow;
1882 }
1883
1884
1885
1886
1887
1888
1889 public static boolean getDefaultAllowUserInteraction()
1890 {
1891 return defaultAllowUI;
1892 }
1893
1894
1895
1896
1897
1898
1899
1900 public static Class[] getDefaultModules()
1901 {
1902 return getModules(DefaultModuleList);
1903 }
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944 public static boolean addDefaultModule(Class module, int pos)
1945 {
1946 return addModule(DefaultModuleList, module, pos);
1947 }
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959 public static boolean removeDefaultModule(Class module)
1960 {
1961 return removeModule(DefaultModuleList, module);
1962 }
1963
1964
1965
1966
1967
1968
1969
1970 public Class[] getModules()
1971 {
1972 return getModules(ModuleList);
1973 }
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997 public boolean addModule(Class module, int pos)
1998 {
1999 return addModule(ModuleList, module, pos);
2000 }
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010 public boolean removeModule(Class module)
2011 {
2012 return removeModule(ModuleList, module);
2013 }
2014
2015 private static final Class[] getModules(Vector list)
2016 {
2017 synchronized(list)
2018 {
2019 Class[] modules = new Class[list.size()];
2020 list.copyInto(modules);
2021 return modules;
2022 }
2023 }
2024
2025 private static final boolean addModule(Vector list, Class module, int pos)
2026 {
2027 if (module == null) return false;
2028
2029
2030 try
2031 { HTTPClientModule tmp = (HTTPClientModule) module.newInstance(); }
2032 catch (RuntimeException re)
2033 { throw re; }
2034 catch (Exception e)
2035 { throw new RuntimeException(e.toString()); }
2036
2037 synchronized (list)
2038 {
2039
2040 if (list.contains(module))
2041 return false;
2042
2043
2044 if (pos < 0)
2045 list.insertElementAt(module, DefaultModuleList.size()+pos+1);
2046 else
2047 list.insertElementAt(module, pos);
2048 }
2049
2050 Log.write(Log.CONN, "Conn: Added module " + module.getName() +
2051 " to " +
2052 ((list == DefaultModuleList) ? "default " : "") +
2053 "list");
2054
2055 return true;
2056 }
2057
2058 private static final boolean removeModule(Vector list, Class module)
2059 {
2060 if (module == null) return false;
2061
2062 boolean removed = list.removeElement(module);
2063 if (removed)
2064 Log.write(Log.CONN, "Conn: Removed module " + module.getName() +
2065 " from " +
2066 ((list == DefaultModuleList) ? "default " : "") +
2067 "list");
2068
2069 return removed;
2070 }
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099 public void setContext(Object context)
2100 {
2101 if (context == null)
2102 throw new IllegalArgumentException("Context must be non-null");
2103 if (Context != null)
2104 throw new IllegalStateException("Context already set");
2105
2106 Context = context;
2107 }
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117 public Object getContext()
2118 {
2119 if (Context != null)
2120 return Context;
2121 else
2122 return dflt_context;
2123 }
2124
2125
2126
2127
2128
2129
2130
2131
2132 public static Object getDefaultContext()
2133 {
2134 return dflt_context;
2135 }
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151 public void addDigestAuthorization(String realm, String user, String passwd)
2152 {
2153 AuthorizationInfo.addDigestAuthorization(Host, Port, realm, user,
2154 passwd, getContext());
2155 }
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171 public void addBasicAuthorization(String realm, String user, String passwd)
2172 {
2173 AuthorizationInfo.addBasicAuthorization(Host, Port, realm, user,
2174 passwd, getContext());
2175 }
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203 public static void setProxyServer(String host, int port)
2204 {
2205 if (host == null || host.trim().length() == 0)
2206 Default_Proxy_Host = null;
2207 else
2208 {
2209 Default_Proxy_Host = host.trim().toLowerCase();
2210 Default_Proxy_Port = port;
2211 }
2212 }
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230 public synchronized void setCurrentProxy(String host, int port)
2231 {
2232 if (host == null || host.trim().length() == 0)
2233 Proxy_Host = null;
2234 else
2235 {
2236 Proxy_Host = host.trim().toLowerCase();
2237 if (port <= 0)
2238 Proxy_Port = 80;
2239 else
2240 Proxy_Port = port;
2241 }
2242
2243
2244 switch(Protocol)
2245 {
2246 case HTTP:
2247 case HTTPS:
2248 if (force_1_0)
2249 {
2250 ServerProtocolVersion = HTTP_1_0;
2251 ServProtVersKnown = true;
2252 RequestProtocolVersion = "HTTP/1.0";
2253 }
2254 else
2255 {
2256 ServerProtocolVersion = HTTP_1_1;
2257 ServProtVersKnown = false;
2258 RequestProtocolVersion = "HTTP/1.1";
2259 }
2260 break;
2261 case HTTP_NG:
2262 ServerProtocolVersion = -1;
2263 ServProtVersKnown = false;
2264 RequestProtocolVersion = "";
2265 break;
2266 case SHTTP:
2267 ServerProtocolVersion = -1;
2268 ServProtVersKnown = false;
2269 RequestProtocolVersion = "Secure-HTTP/1.3";
2270 break;
2271 default:
2272 throw new Error("HTTPClient Internal Error: invalid protocol " +
2273 Protocol);
2274 }
2275
2276 keepAliveUnknown = true;
2277 doesKeepAlive = false;
2278
2279 input_demux = null;
2280 early_stall = null;
2281 late_stall = null;
2282 prev_resp = null;
2283 }
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314 public static void dontProxyFor(String host) throws ParseException
2315 {
2316 host = host.trim().toLowerCase();
2317
2318
2319
2320 if (host.charAt(0) == '.')
2321 {
2322 if (!non_proxy_dom_list.contains(host))
2323 non_proxy_dom_list.addElement(host);
2324 return;
2325 }
2326
2327
2328
2329
2330 for (int idx=0; idx<host.length(); idx++)
2331 {
2332 if (!Character.isDigit(host.charAt(idx)) &&
2333 host.charAt(idx) != '.' && host.charAt(idx) != '/')
2334 {
2335 non_proxy_host_list.put(host, "");
2336 return;
2337 }
2338 }
2339
2340
2341
2342
2343 byte[] ip_addr;
2344 byte[] ip_mask;
2345 int slash;
2346 if ((slash = host.indexOf('/')) != -1)
2347 {
2348 ip_addr = string2arr(host.substring(0, slash));
2349 ip_mask = string2arr(host.substring(slash+1));
2350 if (ip_addr.length != ip_mask.length)
2351 throw new ParseException("length of IP-address (" +
2352 ip_addr.length + ") != length of netmask (" +
2353 ip_mask.length + ")");
2354 }
2355 else
2356 {
2357 ip_addr = string2arr(host);
2358 ip_mask = new byte[ip_addr.length];
2359 for (int idx=0; idx<ip_mask.length; idx++)
2360 ip_mask[idx] = (byte) 255;
2361 }
2362
2363
2364
2365
2366 ip_loop: for (int idx=0; idx<non_proxy_addr_list.size(); idx++)
2367 {
2368 byte[] addr = (byte[]) non_proxy_addr_list.elementAt(idx);
2369 byte[] mask = (byte[]) non_proxy_mask_list.elementAt(idx);
2370 if (addr.length != ip_addr.length) continue;
2371
2372 for (int idx2=0; idx2<addr.length; idx2++)
2373 {
2374 if ((ip_addr[idx2] & mask[idx2]) != (addr[idx2] & mask[idx2]) ||
2375 (mask[idx2] != ip_mask[idx2]))
2376 continue ip_loop;
2377 }
2378
2379 return;
2380 }
2381 non_proxy_addr_list.addElement(ip_addr);
2382 non_proxy_mask_list.addElement(ip_mask);
2383 }
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394 public static void dontProxyFor(String[] hosts)
2395 {
2396 if (hosts == null || hosts.length == 0)
2397 return;
2398
2399 for (int idx=0; idx<hosts.length; idx++)
2400 {
2401 try
2402 {
2403 if (hosts[idx] != null)
2404 dontProxyFor(hosts[idx]);
2405 }
2406 catch(ParseException pe)
2407 {
2408
2409 }
2410 }
2411 }
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427 public static boolean doProxyFor(String host) throws ParseException
2428 {
2429 host = host.trim().toLowerCase();
2430
2431
2432
2433 if (host.charAt(0) == '.')
2434 return non_proxy_dom_list.removeElement(host);
2435
2436
2437
2438
2439 for (int idx=0; idx<host.length(); idx++)
2440 {
2441 if (!Character.isDigit(host.charAt(idx)) &&
2442 host.charAt(idx) != '.' && host.charAt(idx) != '/')
2443 return (non_proxy_host_list.remove(host) != null);
2444 }
2445
2446
2447
2448
2449 byte[] ip_addr;
2450 byte[] ip_mask;
2451 int slash;
2452 if ((slash = host.indexOf('/')) != -1)
2453 {
2454 ip_addr = string2arr(host.substring(0, slash));
2455 ip_mask = string2arr(host.substring(slash+1));
2456 if (ip_addr.length != ip_mask.length)
2457 throw new ParseException("length of IP-address (" +
2458 ip_addr.length + ") != length of netmask (" +
2459 ip_mask.length + ")");
2460 }
2461 else
2462 {
2463 ip_addr = string2arr(host);
2464 ip_mask = new byte[ip_addr.length];
2465 for (int idx=0; idx<ip_mask.length; idx++)
2466 ip_mask[idx] = (byte) 255;
2467 }
2468
2469 ip_loop: for (int idx=0; idx<non_proxy_addr_list.size(); idx++)
2470 {
2471 byte[] addr = (byte[]) non_proxy_addr_list.elementAt(idx);
2472 byte[] mask = (byte[]) non_proxy_mask_list.elementAt(idx);
2473 if (addr.length != ip_addr.length) continue;
2474
2475 for (int idx2=0; idx2<addr.length; idx2++)
2476 {
2477 if ((ip_addr[idx2] & mask[idx2]) != (addr[idx2] & mask[idx2]) ||
2478 (mask[idx2] != ip_mask[idx2]))
2479 continue ip_loop;
2480 }
2481
2482 non_proxy_addr_list.removeElementAt(idx);
2483 non_proxy_mask_list.removeElementAt(idx);
2484 return true;
2485 }
2486 return false;
2487 }
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497 private static byte[] string2arr(String ip)
2498 {
2499 byte[] arr;
2500 char[] ip_char = new char[ip.length()];
2501 ip.getChars(0, ip_char.length, ip_char, 0);
2502
2503 int cnt = 0;
2504 for (int idx=0; idx<ip_char.length; idx++)
2505 if (ip_char[idx] == '.') cnt++;
2506 arr = new byte[cnt+1];
2507
2508 cnt = 0;
2509 int pos = 0;
2510 for (int idx=0; idx<ip_char.length; idx++)
2511 if (ip_char[idx] == '.')
2512 {
2513 arr[cnt] = (byte) Integer.parseInt(ip.substring(pos, idx));
2514 cnt++;
2515 pos = idx+1;
2516 }
2517 arr[cnt] = (byte) Integer.parseInt(ip.substring(pos));
2518
2519 return arr;
2520 }
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536 public static void setSocksServer(String host)
2537 {
2538 setSocksServer(host, 1080);
2539 }
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555 public static void setSocksServer(String host, int port)
2556 {
2557 if (port <= 0)
2558 port = 1080;
2559
2560 if (host == null || host.length() == 0)
2561 Default_Socks_client = null;
2562 else
2563 Default_Socks_client = new SocksClient(host, port);
2564 }
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613 public static void setSocksServer(String host, int port, int version)
2614 throws SocksException
2615 {
2616 if (port <= 0)
2617 port = 1080;
2618
2619 if (host == null || host.length() == 0)
2620 Default_Socks_client = null;
2621 else
2622 Default_Socks_client = new SocksClient(host, port, version);
2623 }
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633 private final String stripRef(String file)
2634 {
2635 if (file == null) return "";
2636
2637 int hash = file.indexOf('#');
2638 if (hash != -1)
2639 file = file.substring(0,hash);
2640
2641 return file.trim();
2642 }
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663 protected final HTTPResponse setupRequest(String method, String resource,
2664 NVPair[] headers, byte[] entity,
2665 HttpOutputStream stream)
2666 throws IOException, ModuleException
2667 {
2668 Request req = new Request(this, method, resource,
2669 mergedHeaders(headers), entity, stream,
2670 allowUI);
2671 RequestList.addToEnd(req);
2672
2673 try
2674 {
2675 HTTPResponse resp = new HTTPResponse(gen_mod_insts(), Timeout, req);
2676 handleRequest(req, resp, null, true);
2677 return resp;
2678 }
2679 finally
2680 { RequestList.remove(req); }
2681 }
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694 private NVPair[] mergedHeaders(NVPair[] spec)
2695 {
2696 int spec_len = (spec != null ? spec.length : 0),
2697 defs_len;
2698 NVPair[] merged;
2699
2700 synchronized (DefaultHeaders)
2701 {
2702 defs_len = (DefaultHeaders != null ? DefaultHeaders.length : 0);
2703 merged = new NVPair[spec_len + defs_len];
2704
2705
2706 System.arraycopy(DefaultHeaders, 0, merged, 0, defs_len);
2707 }
2708
2709
2710 int sidx, didx = defs_len;
2711 for (sidx=0; sidx<spec_len; sidx++)
2712 {
2713 if (spec[sidx] == null)
2714 continue;
2715
2716 String s_name = spec[sidx].getName().trim();
2717 if (s_name.equalsIgnoreCase("Content-length"))
2718 continue;
2719
2720 int search;
2721 for (search=0; search<didx; search++)
2722 {
2723 if (merged[search].getName().trim().equalsIgnoreCase(s_name))
2724 break;
2725 }
2726
2727 merged[search] = spec[sidx];
2728 if (search == didx) didx++;
2729 }
2730
2731 if (didx < merged.length)
2732 merged = Util.resizeArray(merged, didx);
2733
2734 return merged;
2735 }
2736
2737
2738
2739
2740
2741 private HTTPClientModule[] gen_mod_insts()
2742 {
2743 synchronized (ModuleList)
2744 {
2745 HTTPClientModule[] mod_insts =
2746 new HTTPClientModule[ModuleList.size()];
2747
2748 for (int idx=0; idx<ModuleList.size(); idx++)
2749 {
2750 Class mod = (Class) ModuleList.elementAt(idx);
2751 try
2752 { mod_insts[idx] = (HTTPClientModule) mod.newInstance(); }
2753 catch (Exception e)
2754 {
2755 throw new Error("HTTPClient Internal Error: could not " +
2756 "create instance of " + mod.getName() +
2757 " -\n" + e);
2758 }
2759 }
2760
2761 return mod_insts;
2762 }
2763 }
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778 void handleRequest(Request req, HTTPResponse http_resp, Response resp,
2779 boolean usemodules)
2780 throws IOException, ModuleException
2781 {
2782 Response[] rsp_arr = { resp };
2783 HTTPClientModule[] modules = http_resp.getModules();
2784
2785
2786
2787
2788 if (usemodules)
2789 doModules: for (int idx=0; idx<modules.length; idx++)
2790 {
2791 int sts = modules[idx].requestHandler(req, rsp_arr);
2792 switch (sts)
2793 {
2794 case REQ_CONTINUE:
2795 break;
2796
2797 case REQ_RESTART:
2798 idx = -1;
2799 continue doModules;
2800
2801 case REQ_SHORTCIRC:
2802 break doModules;
2803
2804 case REQ_RESPONSE:
2805 case REQ_RETURN:
2806 if (rsp_arr[0] == null)
2807 throw new Error("HTTPClient Internal Error: no " +
2808 "response returned by module " +
2809 modules[idx].getClass().getName());
2810 http_resp.set(req, rsp_arr[0]);
2811 if (req.getStream() != null)
2812 req.getStream().ignoreData(req);
2813 if (req.internal_subrequest) return;
2814 if (sts == REQ_RESPONSE)
2815 http_resp.handleResponse();
2816 else
2817 http_resp.init(rsp_arr[0]);
2818 return;
2819
2820 case REQ_NEWCON_RST:
2821 if (req.internal_subrequest) return;
2822 req.getConnection().
2823 handleRequest(req, http_resp, rsp_arr[0], true);
2824 return;
2825
2826 case REQ_NEWCON_SND:
2827 if (req.internal_subrequest) return;
2828 req.getConnection().
2829 handleRequest(req, http_resp, rsp_arr[0], false);
2830 return;
2831
2832 default:
2833 throw new Error("HTTPClient Internal Error: invalid status"+
2834 " " + sts + " returned by module " +
2835 modules[idx].getClass().getName());
2836 }
2837 }
2838
2839 if (req.internal_subrequest) return;
2840
2841
2842
2843
2844 if (req.getStream() != null && req.getStream().getLength() == -1)
2845 {
2846 if (!ServProtVersKnown || ServerProtocolVersion < HTTP_1_1 ||
2847 no_chunked)
2848 {
2849 req.getStream().goAhead(req, null, http_resp.getTimeout());
2850 http_resp.set(req, req.getStream());
2851 }
2852 else
2853 {
2854
2855 int idx;
2856 NVPair[] hdrs = req.getHeaders();
2857 for (idx=0; idx<hdrs.length; idx++)
2858 if (hdrs[idx].getName().equalsIgnoreCase("Transfer-Encoding"))
2859 break;
2860
2861 if (idx == hdrs.length)
2862 {
2863 hdrs = Util.resizeArray(hdrs, idx+1);
2864 hdrs[idx] = new NVPair("Transfer-Encoding", "chunked");
2865 req.setHeaders(hdrs);
2866 }
2867 else
2868 {
2869 String v = hdrs[idx].getValue();
2870 try
2871 {
2872 if (!Util.hasToken(v, "chunked"))
2873 hdrs[idx] = new NVPair("Transfer-Encoding",
2874 v + ", chunked");
2875 }
2876 catch (ParseException pe)
2877 { throw new IOException(pe.toString()); }
2878 }
2879
2880 http_resp.set(req, sendRequest(req, http_resp.getTimeout()));
2881 }
2882 }
2883 else
2884 http_resp.set(req, sendRequest(req, http_resp.getTimeout()));
2885
2886 if (req.aborted) throw new IOException("Request aborted by user");
2887 }
2888
2889
2890
2891 private volatile Response early_stall = null;
2892 private volatile Response late_stall = null;
2893 private volatile Response prev_resp = null;
2894
2895 private boolean output_finished = true;
2896
2897
2898 private boolean check_certificates = true;
2899 private boolean test_connnection_health_with_blocking_read = false;
2900
2901 public final void setCheckCertificates(boolean b)
2902 {
2903 check_certificates = b;
2904 }
2905
2906 public final boolean getCheckCertificates()
2907 {
2908 return check_certificates;
2909 }
2910
2911 public final void setTestConnectionHealthWithBlockingRead(boolean b)
2912 {
2913 test_connnection_health_with_blocking_read = b;
2914 }
2915
2916 public final boolean getTestConnectionHealthWithBlockingRead()
2917 {
2918 return test_connnection_health_with_blocking_read;
2919 }
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929 public final void setLocalAddress(InetAddress localAddress, int localPort) {
2930 LocalAddr = localAddress;
2931 LocalPort = localPort;
2932 }
2933
2934 final InetAddress getLocalAddress() {
2935 return LocalAddr;
2936 }
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953 Response sendRequest(Request req, int con_timeout)
2954 throws IOException, ModuleException
2955 {
2956 ByteArrayOutputStream hdr_buf = new ByteArrayOutputStream(600);
2957 Response resp = null;
2958 boolean keep_alive;
2959
2960
2961
2962
2963
2964
2965 if (early_stall != null)
2966 {
2967 try
2968 {
2969 Log.write(Log.CONN, "Conn: Early-stalling Request: " +
2970 req.getMethod() + " " +
2971 req.getRequestURI());
2972
2973 synchronized (early_stall)
2974 {
2975
2976 try
2977 { early_stall.getVersion(); }
2978 catch (IOException ioe)
2979 { }
2980 early_stall = null;
2981 }
2982 }
2983 catch (NullPointerException npe)
2984 { }
2985 }
2986
2987
2988 String[] con_hdrs = assembleHeaders(req, hdr_buf);
2989
2990
2991
2992
2993
2994 try
2995 {
2996 if (ServerProtocolVersion >= HTTP_1_1 &&
2997 !Util.hasToken(con_hdrs[0], "close")
2998 ||
2999 ServerProtocolVersion == HTTP_1_0 &&
3000 Util.hasToken(con_hdrs[0], "keep-alive")
3001 )
3002 keep_alive = true;
3003 else
3004 keep_alive = false;
3005 }
3006 catch (ParseException pe)
3007 { throw new IOException(pe.toString()); }
3008
3009
3010 synchronized (this)
3011 {
3012
3013
3014
3015
3016 if (late_stall != null)
3017 {
3018 if (input_demux != null || keepAliveUnknown)
3019 {
3020 Log.write(Log.CONN, "Conn: Stalling Request: " +
3021 req.getMethod() + " " + req.getRequestURI());
3022
3023 try
3024 {
3025 late_stall.getVersion();
3026 if (keepAliveUnknown)
3027 determineKeepAlive(late_stall);
3028 }
3029 catch (IOException ioe)
3030 { }
3031 }
3032
3033 late_stall = null;
3034 }
3035
3036
3037
3038
3039
3040
3041
3042
3043 if ((req.getMethod().equals("POST") || req.dont_pipeline) &&
3044 prev_resp != null && input_demux != null)
3045 {
3046 Log.write(Log.CONN, "Conn: Stalling Request: " +
3047 req.getMethod() + " " + req.getRequestURI());
3048
3049 try
3050 { prev_resp.getVersion(); }
3051 catch (IOException ioe)
3052 { }
3053 }
3054
3055
3056
3057
3058
3059 if (!output_finished)
3060 {
3061 try
3062 { wait(); }
3063 catch (InterruptedException ie)
3064 { throw new IOException(ie.toString()); }
3065 }
3066
3067
3068 if (req.aborted) throw new IOException("Request aborted by user");
3069
3070 int try_count = 3;
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080 while (try_count-- > 0)
3081 {
3082 try
3083 {
3084
3085
3086 Socket sock;
3087 if (input_demux == null ||
3088 (sock = input_demux.getSocket()) == null)
3089 {
3090 sock = getSocket(con_timeout);
3091
3092 if (Protocol == HTTPS)
3093 {
3094 if (Proxy_Host != null)
3095 {
3096 Socket[] sarr = { sock };
3097 resp = enableSSLTunneling(sarr, req, con_timeout);
3098 if (resp != null)
3099 {
3100 resp.final_resp = true;
3101 return resp;
3102 }
3103 sock = sarr[0];
3104 }
3105
3106 sock.setSoTimeout(con_timeout);
3107 sock = sslFactory.createSocket(sock, Host, Port, true);
3108
3109
3110 final SSLSocket sslSocket = (SSLSocket)sock;
3111
3112 sslSocket.setEnabledCipherSuites(getSSLCipherSuites());
3113 sslSocket.setEnabledProtocols(getSSLProtocols());
3114
3115 if (getCheckCertificates()) {
3116
3117
3118 checkCert(((SSLSocket) sock).getSession().
3119 getPeerCertificateChain()[0], Host);
3120
3121
3122 }
3123
3124 }
3125
3126 else {
3127 sock.setSoTimeout(con_timeout);
3128 }
3129
3130
3131 input_demux = new StreamDemultiplexor(Protocol, sock, this);
3132 DemuxList.addToEnd(input_demux);
3133 keepAliveReqLeft = keepAliveReqMax;
3134 }
3135
3136 if (req.aborted)
3137 throw new IOException("Request aborted by user");
3138
3139 Log.write(Log.CONN, "Conn: Sending Request: ", hdr_buf);
3140
3141
3142
3143
3144 OutputStream sock_out = sock.getOutputStream();
3145 if (haveMSLargeWritesBug)
3146 sock_out = new MSLargeWritesBugStream(sock_out);
3147
3148 hdr_buf.writeTo(sock_out);
3149
3150
3151
3152
3153 try
3154 {
3155 if (ServProtVersKnown &&
3156 ServerProtocolVersion >= HTTP_1_1 &&
3157 Util.hasToken(con_hdrs[1], "100-continue"))
3158 {
3159 resp = new Response(req, (Proxy_Host != null && Protocol != HTTPS), input_demux);
3160 resp.timeout = 60;
3161 if (resp.getContinue() != 100)
3162 break;
3163 }
3164 }
3165 catch (ParseException pe)
3166 { throw new IOException(pe.toString()); }
3167 catch (InterruptedIOException iioe)
3168 { }
3169 finally
3170 { if (resp != null) resp.timeout = 0; }
3171
3172
3173
3174
3175 if (req.getData() != null && req.getData().length > 0)
3176 {
3177 if (req.delay_entity > 0)
3178 {
3179
3180
3181
3182 long num_units = req.delay_entity / 100;
3183 long one_unit = req.delay_entity / num_units;
3184
3185 for (int idx=0; idx<num_units; idx++)
3186 {
3187 if (input_demux.available(null) != 0)
3188 break;
3189 try { Thread.sleep(one_unit); }
3190 catch (InterruptedException ie) { }
3191 }
3192
3193 if (input_demux.available(null) == 0)
3194
3195
3196 writeData(sock_out, req.getData());
3197
3198 else
3199 keep_alive = false;
3200 }
3201 else
3202
3203
3204 writeData(sock_out, req.getData());
3205
3206
3207 }
3208
3209 if (req.getStream() != null)
3210 req.getStream().goAhead(req, sock_out, 0);
3211 else
3212 sock_out.flush();
3213
3214
3215
3216
3217
3218 if (resp == null)
3219
3220 {
3221 final Response r = new Response(req, (Proxy_Host != null &&
3222 Protocol != HTTPS),
3223 input_demux);
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236 if (getTestConnectionHealthWithBlockingRead() &&
3237
3238
3239 req.getStream() == null) {
3240 r.getVersion();
3241 }
3242
3243 resp = r;
3244 }
3245
3246
3247
3248
3249
3250 }
3251 catch (IOException ioe)
3252 {
3253 Log.write(Log.CONN, "Conn: ", ioe);
3254
3255 closeDemux(ioe, true);
3256
3257 if (try_count == 0 || ioe instanceof UnknownHostException ||
3258 ioe instanceof ConnectException ||
3259 ioe instanceof NoRouteToHostException ||
3260 ioe instanceof InterruptedIOException || req.aborted)
3261 throw ioe;
3262
3263 Log.write(Log.CONN, "Conn: Retrying request");
3264 continue;
3265 }
3266
3267 break;
3268 }
3269
3270 prev_resp = resp;
3271
3272
3273
3274
3275 if ((!keepAliveUnknown && !doesKeepAlive) || !keep_alive ||
3276 (keepAliveReqMax != -1 && keepAliveReqLeft-- == 0))
3277 {
3278 input_demux.markForClose(resp);
3279 input_demux = null;
3280 }
3281 else
3282 input_demux.restartTimer();
3283
3284 if (keepAliveReqMax != -1)
3285 Log.write(Log.CONN, "Conn: Number of requests left: "+
3286 keepAliveReqLeft);
3287
3288
3289
3290
3291
3292 if (!ServProtVersKnown)
3293 { early_stall = resp; resp.markAsFirstResponse(req); }
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305 if (keepAliveUnknown ||
3306
3307 !IdempotentSequence.methodIsIdempotent(req.getMethod()) ||
3308 req.dont_pipeline ||
3309 neverPipeline)
3310 { late_stall = resp; }
3311
3312
3313
3314
3315
3316
3317 if (req.getStream() != null)
3318 output_finished = false;
3319 else
3320 {
3321 output_finished = true;
3322 notify();
3323 }
3324
3325
3326
3327
3328 Log.write(Log.CONN, "Conn: Request sent");
3329 }
3330
3331 return resp;
3332 }
3333
3334
3335 private void writeData(OutputStream out, byte[] buffer)
3336 throws IOException {
3337
3338 final BandwidthLimiter bandwidthLimiter =
3339 getBandwidthLimiterFactory().create();
3340
3341 int position = 0;
3342
3343 do {
3344 final int bytesToSend =
3345 Math.min(buffer.length - position,
3346 bandwidthLimiter.maximumBytes(position));
3347
3348 out.write(buffer, position, bytesToSend);
3349
3350 position += bytesToSend;
3351 }
3352 while (position < buffer.length);
3353 }
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364 private Socket getSocket(int con_timeout) throws IOException
3365 {
3366 Socket sock = null;
3367
3368 String actual_host;
3369 int actual_port;
3370
3371 if (Proxy_Host != null)
3372 {
3373 actual_host = Proxy_Host;
3374 actual_port = Proxy_Port;
3375 }
3376 else
3377 {
3378 actual_host = Host;
3379 actual_port = Port;
3380 }
3381
3382 Log.write(Log.CONN, "Conn: Creating Socket: " + actual_host + ":" +
3383 actual_port);
3384
3385 if (con_timeout == 0)
3386 {
3387 if (Socks_client != null)
3388 sock = Socks_client.getSocket(actual_host, actual_port);
3389 else
3390 {
3391
3392 final long startTime =
3393 getTimeAuthority().getTimeInMilliseconds();
3394
3395
3396 InetAddress[] addr_list = InetAddress.getAllByName(actual_host);
3397
3398
3399 DNS_time.set(
3400 Math.max(getTimeAuthority().getTimeInMilliseconds() -
3401 startTime,
3402 0));
3403
3404 for (int idx=0; idx<addr_list.length; idx++)
3405 {
3406 try
3407 {
3408 if (LocalAddr == null)
3409 sock = new Socket(addr_list[idx], actual_port);
3410 else
3411 sock = new Socket(addr_list[idx], actual_port,
3412 LocalAddr, LocalPort);
3413
3414 sock.setSoLinger(true, 0);
3415 sock.setKeepAlive(false);
3416
3417
3418 con_time.set(
3419 Math.max(getTimeAuthority().getTimeInMilliseconds() -
3420 startTime,
3421 0));
3422 connectionsEstablished.incrementAndGet();
3423
3424 break;
3425 }
3426 catch (SocketException se)
3427 {
3428 if (idx == addr_list.length-1)
3429 throw se;
3430 }
3431 }
3432 }
3433 }
3434 else
3435 {
3436 EstablishConnection con =
3437 new EstablishConnection(actual_host, actual_port, Socks_client);
3438 con.start();
3439 try
3440 { con.join((long) con_timeout); }
3441 catch (InterruptedException ie)
3442 { }
3443
3444 if (con.getException() != null)
3445 throw con.getException();
3446 if ((sock = con.getSocket()) == null)
3447 {
3448 con.forget();
3449 if ((sock = con.getSocket()) == null)
3450 throw new InterruptedIOException("Connection establishment timed out");
3451 }
3452 }
3453
3454 return sock;
3455 }
3456
3457
3458 public long getDnsTime(){
3459 return DNS_time.get();
3460 }
3461
3462 public long getConnectTime(){
3463 return con_time.get();
3464 }
3465
3466 public long getConnectionsEstablished(){
3467 return connectionsEstablished.get();
3468 }
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483 private Response enableSSLTunneling(Socket[] sock, Request req, int timeout)
3484 throws IOException, ModuleException
3485 {
3486
3487
3488 Vector hdrs = new Vector();
3489 for (int idx=0; idx<req.getHeaders().length; idx++)
3490 {
3491 String name = req.getHeaders()[idx].getName();
3492 if (name.equalsIgnoreCase("User-Agent") ||
3493 name.equalsIgnoreCase("Proxy-Authorization"))
3494 hdrs.addElement(req.getHeaders()[idx]);
3495 }
3496
3497
3498
3499
3500 NVPair[] h = new NVPair[hdrs.size()];
3501 hdrs.copyInto(h);
3502 Request connect = new Request(this, "CONNECT", Host+":"+Port, h,
3503 null, null, req.allowUI());
3504 connect.internal_subrequest = true;
3505
3506 ByteArrayOutputStream hdr_buf = new ByteArrayOutputStream(600);
3507 HTTPResponse r = new HTTPResponse(gen_mod_insts(), timeout, connect);
3508
3509
3510
3511
3512 Response resp = null;
3513
3514 while (true)
3515 {
3516 handleRequest(connect, r, resp, true);
3517
3518 hdr_buf.reset();
3519 assembleHeaders(connect, hdr_buf);
3520
3521 Log.write(Log.CONN, "Conn: Sending SSL-Tunneling Subrequest: ",
3522 hdr_buf);
3523
3524
3525
3526
3527 hdr_buf.writeTo(sock[0].getOutputStream());
3528
3529
3530
3531
3532 resp = new Response(connect, sock[0].getInputStream());
3533 if (resp.getStatusCode() == 200) return null;
3534
3535
3536
3537
3538
3539
3540 try
3541 { resp.getData(); }
3542 catch (IOException ioe)
3543 { }
3544 try
3545 { sock[0].close(); }
3546 catch (IOException ioe)
3547 { }
3548
3549
3550
3551
3552 r.set(connect, resp);
3553 if (!r.handleResponse()) return resp;
3554
3555 sock[0] = getSocket(timeout);
3556 }
3557 }
3558
3559
3560
3561
3562
3563 private static void checkCert(X509Certificate cert, String host)
3564 throws IOException
3565 {
3566 String name;
3567 try
3568 {
3569 name = ((sun.security.x509.X500Name) cert.getSubjectDN()).
3570 getCommonName().toLowerCase();
3571 }
3572 catch (Throwable t)
3573 { return; }
3574
3575 if (Util.wildcardMatch(name, host))
3576 return;
3577
3578 throw new SSLException("Name in certificate `" + name + "' does not " +
3579 "match host name `" + host + "'");
3580 }
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631 private String[] assembleHeaders(Request req,
3632 ByteArrayOutputStream hdr_buf)
3633 throws IOException
3634 {
3635 DataOutputStream dataout = new DataOutputStream(hdr_buf);
3636 String[] con_hdrs = { "", "" };
3637 NVPair[] hdrs = req.getHeaders();
3638
3639
3640
3641
3642
3643 int ho_idx = -1,
3644 ct_idx = -1,
3645 ua_idx = -1,
3646 co_idx = -1,
3647 pc_idx = -1,
3648 ka_idx = -1,
3649 ex_idx = -1,
3650 te_idx = -1,
3651 tc_idx = -1,
3652 ug_idx = -1;
3653 for (int idx=0; idx<hdrs.length; idx++)
3654 {
3655 String name = hdrs[idx].getName().trim().toLowerCase();
3656 if (name.equals("host")) ho_idx = idx;
3657 else if (name.equals("content-type")) ct_idx = idx;
3658 else if (name.equals("user-agent")) ua_idx = idx;
3659 else if (name.equals("connection")) co_idx = idx;
3660 else if (name.equals("proxy-connection")) pc_idx = idx;
3661 else if (name.equals("keep-alive")) ka_idx = idx;
3662 else if (name.equals("expect")) ex_idx = idx;
3663 else if (name.equals("te")) te_idx = idx;
3664 else if (name.equals("transfer-encoding")) tc_idx = idx;
3665 else if (name.equals("upgrade")) ug_idx = idx;
3666 }
3667
3668
3669
3670
3671 String file = Util.escapeUnsafeChars(req.getRequestURI());
3672 if (Proxy_Host != null && Protocol != HTTPS && !file.equals("*"))
3673 dataout.writeBytes(req.getMethod() + " http://" + Host + ":" + Port+
3674 file + " " + RequestProtocolVersion + "\r\n");
3675 else
3676 dataout.writeBytes(req.getMethod() + " " + file + " " +
3677 RequestProtocolVersion + "\r\n");
3678
3679 String h_hdr = (ho_idx >= 0) ? hdrs[ho_idx].getValue().trim() : Host;
3680 if (Port != URI.defaultPort(getProtocol()))
3681 dataout.writeBytes("Host: " + h_hdr + ":" + Port + "\r\n");
3682 else
3683 dataout.writeBytes("Host: " + h_hdr + "\r\n");
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705 String co_hdr = null;
3706 if (!(ServProtVersKnown && ServerProtocolVersion >= HTTP_1_1 &&
3707 co_idx == -1))
3708 {
3709 if (co_idx == -1)
3710 {
3711 co_hdr = "Keep-Alive";
3712 con_hdrs[0] = "Keep-Alive";
3713 }
3714 else
3715 {
3716 con_hdrs[0] = hdrs[co_idx].getValue().trim();
3717 co_hdr = con_hdrs[0];
3718 }
3719
3720 try
3721 {
3722 if (ka_idx != -1 &&
3723 Util.hasToken(con_hdrs[0], "keep-alive"))
3724 dataout.writeBytes("Keep-Alive: " +
3725 hdrs[ka_idx].getValue().trim() + "\r\n");
3726 }
3727 catch (ParseException pe)
3728 {
3729 throw new IOException(pe.toString());
3730 }
3731 }
3732
3733 if ((Proxy_Host != null && Protocol != HTTPS) &&
3734 !(ServProtVersKnown && ServerProtocolVersion >= HTTP_1_1))
3735 {
3736 if (co_hdr != null)
3737 {
3738 dataout.writeBytes("Proxy-Connection: ");
3739 dataout.writeBytes(co_hdr);
3740 dataout.writeBytes("\r\n");
3741 co_hdr = null;
3742 }
3743 }
3744
3745
3746 if (!noTrailers) {
3747
3748 if (co_hdr != null)
3749 {
3750 try
3751 {
3752 if (!Util.hasToken(co_hdr, "TE"))
3753 co_hdr += ", TE";
3754 }
3755 catch (ParseException pe)
3756 { throw new IOException(pe.toString()); }
3757 }
3758 else
3759 co_hdr = "TE";
3760
3761 }
3762
3763
3764 if (ug_idx != -1)
3765 co_hdr += ", Upgrade";
3766
3767 if (co_hdr != null)
3768 {
3769 dataout.writeBytes("Connection: ");
3770 dataout.writeBytes(co_hdr);
3771 dataout.writeBytes("\r\n");
3772 }
3773
3774
3775
3776
3777
3778 if (!noTrailers) {
3779
3780 if (te_idx != -1)
3781 {
3782 dataout.writeBytes("TE: ");
3783 Vector pte;
3784 try
3785 { pte = Util.parseHeader(hdrs[te_idx].getValue()); }
3786 catch (ParseException pe)
3787 { throw new IOException(pe.toString()); }
3788
3789 if (!pte.contains(new HttpHeaderElement("trailers")))
3790 dataout.writeBytes("trailers, ");
3791
3792 dataout.writeBytes(hdrs[te_idx].getValue().trim() + "\r\n");
3793 }
3794 else
3795 dataout.writeBytes("TE: trailers\r\n");
3796
3797 }
3798
3799
3800
3801
3802
3803 if (ua_idx != -1)
3804
3805
3806
3807 dataout.writeBytes("User-Agent: " + hdrs[ua_idx].getValue().trim() +
3808 "\r\n");
3809
3810 else
3811 dataout.writeBytes("User-Agent: " + version + "\r\n");
3812
3813
3814
3815 for (int idx=0; idx<hdrs.length; idx++)
3816 {
3817 if (idx != ct_idx && idx != ua_idx && idx != co_idx &&
3818 idx != pc_idx && idx != ka_idx && idx != ex_idx &&
3819 idx != te_idx && idx != ho_idx)
3820 dataout.writeBytes(hdrs[idx].getName().trim() + ": " +
3821 hdrs[idx].getValue().trim() + "\r\n");
3822 }
3823
3824
3825
3826
3827 if (req.getData() != null || req.getStream() != null)
3828 {
3829
3830
3831 dataout.writeBytes("Content-Type: ");
3832
3833 if (ct_idx != -1)
3834 dataout.writeBytes(hdrs[ct_idx].getValue().trim());
3835 else
3836 dataout.writeBytes("application/octet-stream");
3837 dataout.writeBytes("\r\n");
3838
3839 if (req.getData() != null)
3840 dataout.writeBytes("Content-length: " +req.getData().length +
3841 "\r\n");
3842 else if (req.getStream().getLength() != -1 && tc_idx == -1)
3843 dataout.writeBytes("Content-length: " +
3844 req.getStream().getLength() + "\r\n");
3845
3846 if (ex_idx != -1)
3847 {
3848 con_hdrs[1] = hdrs[ex_idx].getValue().trim();
3849 dataout.writeBytes("Expect: " + con_hdrs[1] + "\r\n");
3850 }
3851 }
3852 else if (ex_idx != -1)
3853 {
3854 Vector expect_tokens;
3855 try
3856 { expect_tokens = Util.parseHeader(hdrs[ex_idx].getValue()); }
3857 catch (ParseException pe)
3858 { throw new IOException(pe.toString()); }
3859
3860
3861
3862
3863 HttpHeaderElement cont = new HttpHeaderElement("100-continue");
3864 while (expect_tokens.removeElement(cont)) ;
3865
3866
3867
3868
3869 if (!expect_tokens.isEmpty())
3870 {
3871 con_hdrs[1] = Util.assembleHeader(expect_tokens);
3872 dataout.writeBytes("Expect: " + con_hdrs[1] + "\r\n");
3873 }
3874 }
3875
3876 dataout.writeBytes("\r\n");
3877
3878 return con_hdrs;
3879 }
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889 boolean handleFirstRequest(Request req, Response resp) throws IOException
3890 {
3891
3892
3893
3894 ServerProtocolVersion = String2ProtVers(resp.getVersion());
3895 ServProtVersKnown = true;
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910 int sts = resp.getStatusCode();
3911 if ((Proxy_Host != null && Protocol != HTTPS) &&
3912 resp.getHeader("Via") == null &&
3913 sts != 407 && sts != 502 && sts != 504)
3914 ServerProtocolVersion = HTTP_1_0;
3915
3916 Log.write(Log.CONN, "Conn: Protocol Version established: " +
3917 ProtVers2String(ServerProtocolVersion));
3918
3919
3920
3921
3922
3923 if (ServerProtocolVersion == HTTP_1_0 &&
3924 (resp.getStatusCode() == 400 || resp.getStatusCode() == 500))
3925 {
3926 if (input_demux != null)
3927 input_demux.markForClose(resp);
3928 input_demux = null;
3929 RequestProtocolVersion = "HTTP/1.0";
3930 return false;
3931 }
3932
3933 return true;
3934 }
3935
3936
3937 private void determineKeepAlive(Response resp) throws IOException
3938 {
3939
3940
3941 String con;
3942
3943 try
3944 {
3945 if (ServerProtocolVersion >= HTTP_1_1 ||
3946 (
3947 (
3948 ((Proxy_Host == null || Protocol == HTTPS) &&
3949 (con = resp.getHeader("Connection")) != null)
3950 ||
3951 ((Proxy_Host != null && Protocol != HTTPS) &&
3952 (con = resp.getHeader("Proxy-Connection")) != null)
3953 ) &&
3954 Util.hasToken(con, "keep-alive")
3955 )
3956 )
3957 {
3958 doesKeepAlive = true;
3959 keepAliveUnknown = false;
3960
3961 Log.write(Log.CONN, "Conn: Keep-Alive enabled");
3962 }
3963 else if (resp.getStatusCode() < 400)
3964 keepAliveUnknown = false;
3965
3966
3967
3968
3969 if (doesKeepAlive && ServerProtocolVersion == HTTP_1_0 &&
3970 (con = resp.getHeader("Keep-Alive")) != null)
3971 {
3972 HttpHeaderElement max =
3973 Util.getElement(Util.parseHeader(con), "max");
3974 if (max != null && max.getValue() != null)
3975 {
3976 keepAliveReqMax = Integer.parseInt(max.getValue());
3977 keepAliveReqLeft = keepAliveReqMax;
3978
3979 Log.write(Log.CONN, "Conn: Max Keep-Alive requests: " +
3980 keepAliveReqMax);
3981 }
3982 }
3983 }
3984 catch (ParseException pe) { }
3985 catch (NumberFormatException nfe) { }
3986 catch (ClassCastException cce) { }
3987 }
3988
3989
3990 synchronized void outputFinished()
3991 {
3992 output_finished = true;
3993 notify();
3994 }
3995
3996
3997 synchronized void closeDemux(IOException ioe, boolean was_reset)
3998 {
3999 if (input_demux != null) input_demux.close(ioe, was_reset);
4000
4001 early_stall = null;
4002 late_stall = null;
4003 prev_resp = null;
4004 }
4005
4006
4007 final static String ProtVers2String(int prot_vers)
4008 {
4009 return "HTTP/" + (prot_vers >>> 16) + "." + (prot_vers & 0xFFFF);
4010 }
4011
4012 final static int String2ProtVers(String prot_vers)
4013 {
4014 String vers = prot_vers.substring(5);
4015 int dot = vers.indexOf('.');
4016 return Integer.parseInt(vers.substring(0, dot)) << 16 |
4017 Integer.parseInt(vers.substring(dot+1));
4018 }
4019
4020
4021
4022
4023
4024
4025
4026 public String toString()
4027 {
4028 return getProtocol() + "://" + getHost() +
4029 (getPort() != URI.defaultPort(getProtocol()) ? ":" + getPort() : "");
4030 }
4031
4032
4033 private class EstablishConnection extends Thread
4034 {
4035 String actual_host;
4036 int actual_port;
4037 IOException exception;
4038 Socket sock;
4039 SocksClient Socks_client;
4040 boolean close;
4041
4042
4043 EstablishConnection(String host, int port, SocksClient socks)
4044 {
4045 super("EstablishConnection (" + host + ":" + port + ")");
4046 try { setDaemon(true); }
4047 catch (SecurityException se) { }
4048
4049 actual_host = host;
4050 actual_port = port;
4051 Socks_client = socks;
4052
4053 exception = null;
4054 sock = null;
4055 close = false;
4056 }
4057
4058
4059 public void run()
4060 {
4061 try
4062 {
4063 if (Socks_client != null)
4064 sock = Socks_client.getSocket(actual_host, actual_port);
4065 else
4066 {
4067
4068 final long startTime =
4069 getTimeAuthority().getTimeInMilliseconds();
4070
4071
4072
4073 InetAddress[] addr_list = InetAddress.getAllByName(actual_host);
4074
4075
4076 DNS_time.set(
4077 Math.max(getTimeAuthority().getTimeInMilliseconds()
4078 - startTime,
4079 0));
4080
4081 for (int idx=0; idx<addr_list.length; idx++)
4082 {
4083 try
4084 {
4085 if (LocalAddr == null)
4086 sock = new Socket(addr_list[idx], actual_port);
4087 else
4088 sock = new Socket(addr_list[idx], actual_port,
4089 LocalAddr, LocalPort);
4090
4091 sock.setSoLinger(true, 0);
4092 sock.setKeepAlive(false);
4093
4094
4095 con_time.set(
4096 Math.max(
4097 getTimeAuthority().getTimeInMilliseconds()
4098 - startTime,
4099 0));
4100
4101 break;
4102 }
4103 catch (SocketException se)
4104 {
4105 if (idx == addr_list.length-1 || close)
4106 throw se;
4107 }
4108 }
4109 }
4110 }
4111 catch (IOException ioe)
4112 {
4113 exception = ioe;
4114 }
4115
4116 if (close && sock != null)
4117 {
4118 try
4119 { sock.close(); }
4120 catch (IOException ioe)
4121 { }
4122 sock = null;
4123 }
4124 }
4125
4126
4127 IOException getException()
4128 {
4129 return exception;
4130 }
4131
4132
4133 Socket getSocket()
4134 {
4135 return sock;
4136 }
4137
4138
4139 void forget()
4140 {
4141 close = true;
4142 }
4143 }
4144
4145
4146
4147
4148
4149
4150
4151 private class MSLargeWritesBugStream extends FilterOutputStream
4152 {
4153 private final int CHUNK_SIZE = 20000;
4154
4155 MSLargeWritesBugStream(OutputStream os)
4156 {
4157 super(os);
4158 }
4159
4160 public void write(byte[] b, int off, int len) throws IOException
4161 {
4162 while (len > CHUNK_SIZE)
4163 {
4164 out.write(b, off, CHUNK_SIZE);
4165 off += CHUNK_SIZE;
4166 len -= CHUNK_SIZE;
4167 }
4168 out.write(b, off, len);
4169 }
4170 }
4171
4172
4173
4174
4175
4176 public static interface BandwidthLimiter {
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187 int maximumBytes(int position);
4188 }
4189
4190 public static interface BandwidthLimiterFactory {
4191 BandwidthLimiter create();
4192 }
4193
4194 private static BandwidthLimiterFactory
4195 s_defaultBandwidthLimiterFactory =
4196 new DefaultBandwidthLimiterFactory();
4197
4198 private BandwidthLimiterFactory m_bandwidthLimiterFactory =
4199 s_defaultBandwidthLimiterFactory;
4200
4201 public void setBufferGrowthStrategyFactory(BandwidthLimiterFactory f) {
4202 if (f == null) {
4203 m_bandwidthLimiterFactory = s_defaultBandwidthLimiterFactory;
4204 }
4205 else {
4206 m_bandwidthLimiterFactory = f;
4207 }
4208 }
4209
4210 BandwidthLimiterFactory getBandwidthLimiterFactory() {
4211 return m_bandwidthLimiterFactory;
4212 }
4213
4214 private static final class UnlimitedBandwidthLimiter
4215 implements BandwidthLimiter {
4216
4217 public int maximumBytes(int position) {
4218 return Integer.MAX_VALUE;
4219 }
4220 }
4221
4222 private static final class DefaultBandwidthLimiterFactory
4223 implements BandwidthLimiterFactory {
4224
4225 final BandwidthLimiter m_unlimitedBandwidthLimiter =
4226 new UnlimitedBandwidthLimiter();
4227
4228 public BandwidthLimiter create() {
4229
4230 return m_unlimitedBandwidthLimiter;
4231 }
4232 }
4233
4234
4235 }