1 21 22 package org.armedbear.j; 23 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.io.OutputStreamWriter ; 27 import java.net.Socket ; 28 import java.net.URL ; 29 import java.security.Provider ; 30 import java.security.Security ; 31 import java.util.List ; 32 import javax.swing.SwingUtilities ; 33 34 public final class HttpLoadProcess extends LoadProcess implements BackgroundProcess, 35 Runnable , Cancellable 36 { 37 private Socket socket; 38 private boolean render = true; 39 40 private String request; 41 private String responseHeaders; 42 private String contentType; 43 44 private int redirectionCount; 45 46 private FastStringBuffer sbHeaders = new FastStringBuffer(); 47 48 public HttpLoadProcess(Buffer buffer, HttpFile file) 49 { 50 super(buffer, file); 51 } 52 53 public final String getRequest() 54 { 55 return request; 56 } 57 58 public final String getResponseHeaders() 59 { 60 return responseHeaders; 61 } 62 63 public final String getContentType() 64 { 65 return contentType; 66 } 67 68 private final void setContentType(String s) 69 { 70 contentType = s; 71 } 72 73 public void run() 74 { 75 if (buffer != null) { 76 buffer.setBusy(true); 77 buffer.setBackgroundProcess(this); 78 } 79 load(); 80 if (buffer != null && buffer.getBackgroundProcess() == this) { 81 Log.debug("calling setBackgroundProcess(null)"); 82 buffer.setBackgroundProcess(null); 83 buffer.setBusy(false); 84 } 85 } 86 87 private void load() 88 { 89 boolean usingProxy = false; 90 if (file.getProtocol() == File.PROTOCOL_HTTPS) { 91 if (!findProvider()) { 92 error("No SSL provider found"); 93 return; 94 } 95 } 96 cache = Utilities.getTempFile(); 97 if (cache == null) { 98 Log.error("HttpLoadProcess.load cache is null"); 99 return; } 101 Debug.assertTrue(socket == null); 102 String hostName = file.getHostName(); 103 int port = file.getPort(); 104 if (file.getProtocol() == File.PROTOCOL_HTTPS) { 105 socket = createSSLSocket(hostName, port); 106 if (socket == null) { 107 if (!cancelled) 108 error("Can't create SSL socket"); 109 return; 110 } 111 } else { 112 String httpProxy = Editor.preferences().getStringProperty("httpProxy"); 113 if (httpProxy != null) { 114 if (httpProxy.startsWith("http://")) 115 httpProxy = httpProxy.substring(7); 116 int index = httpProxy.indexOf(':'); 117 if (index >= 0) { 118 try { 119 port = Integer.parseInt(httpProxy.substring(index + 1)); 120 hostName = httpProxy.substring(0, index); 121 usingProxy = true; 122 } 123 catch (NumberFormatException e) { 124 Log.error(e); 125 } 126 } 127 } 128 connect(hostName, port); 129 } 130 if (cancelled) { 131 Log.debug("cancelled!!"); 132 if (cancelRunnable != null) 133 SwingUtilities.invokeLater(cancelRunnable); 134 return; 135 } 136 if (socket == null) { 137 if (errorRunnable != null) 138 SwingUtilities.invokeLater(errorRunnable); 139 return; 140 } 141 String location = null; 142 boolean redirected = false; 143 String encoding = null; 144 try { 145 InputStream in = socket.getInputStream(); 146 OutputStreamWriter writer = new OutputStreamWriter (socket.getOutputStream()); 147 FastStringBuffer sb = new FastStringBuffer(1024); 148 sb.append("GET "); 149 sb.append(usingProxy ? file.netPath() : file.canonicalPath()); 150 sb.append(" HTTP/1.0\r\n"); 151 sb.append("Host: "); 152 sb.append(file.getHostName()); 153 sb.append("\r\n"); 154 String userAgent = Editor.preferences().getStringProperty(Property.HTTP_USER_AGENT); 155 if (userAgent != null && userAgent.length() > 0) { 156 sb.append("User-Agent: "); 157 sb.append(userAgent); 158 sb.append("\r\n"); 159 } 160 if (Editor.preferences().getBooleanProperty(Property.HTTP_ENABLE_COOKIES)) { 161 String cookie = Cookie.getCookie(new URL (file.netPath())); 162 if (cookie != null) { 163 sb.append("Cookie: "); 164 sb.append(cookie); 165 sb.append("\r\n"); 166 } 167 } 168 sb.append("\r\n"); 169 request = sb.toString(); 170 writer.write(request); 171 writer.flush(); 172 sb.setLength(0); 173 sbHeaders.append(request); 174 OutputStream out = cache.getOutputStream(); 175 byte[] buf = new byte[16384]; 176 long totalBytes = 0; 177 int totalLength = 0; if (progressNotifier != null) 179 progressNotifier.progressStart(); 180 while (!cancelled) { 181 int bytesRead = 0; 182 try { 183 bytesRead = in.read(buf); 185 } 186 catch (Exception e) { 187 if (!cancelled) 188 Log.error(e); 189 } 190 if (bytesRead <= 0) 191 break; 192 if (sb != null) { 193 int oldLength = sb.length(); 194 sb.append(new String (buf, 0, bytesRead, "ISO8859_1")); 195 String s = sb.toString(); 196 int skip = 4; int index = s.indexOf("\r\n\r\n"); 198 if (index < 0) { 199 index = s.indexOf("\n\n"); 200 skip = 2; } 202 if (index >= 0) { 203 sb = null; 205 responseHeaders = s.substring(0, index + skip); 206 sbHeaders.append(responseHeaders); 207 int statusCode = getStatusCode(responseHeaders); 208 Log.debug("statusCode = " + statusCode); 209 if (statusCode == 301 || statusCode == 302) { 210 location = getLocation(responseHeaders); 212 redirected = true; 213 Log.debug("redirected to |" + location + "|"); 214 Log.debug(request); 215 Log.debug(responseHeaders); 216 } 217 int end = responseHeaders.indexOf('\n'); 219 if (end >= 0) 220 responseHeaders = responseHeaders.substring(end + 1); 221 int contentLength = getContentLength(responseHeaders); 222 if (contentLength != 0) 223 totalLength = responseHeaders.length() + contentLength; 224 Log.debug("responseHeaders = |" + responseHeaders + "|"); 225 Headers headers = Headers.parse(responseHeaders); 226 setContentType(headers.getValue(Headers.CONTENT_TYPE)); 227 Log.debug("content-type = |" + contentType + "|"); 228 String charset = 229 Utilities.getCharsetFromContentType(contentType); 230 Log.debug("charset = |" + charset + "|"); 231 if (charset != null) 232 encoding = Utilities.getEncodingFromCharset(charset); 233 Log.debug("encoding = |" + encoding + "|"); 234 if (Editor.preferences().getBooleanProperty(Property.HTTP_ENABLE_COOKIES)) { 235 String cookie = headers.getValue(Headers.SET_COOKIE); 236 if (cookie != null) 237 Cookie.setCookie(new URL (file.netPath()), cookie); 238 } 239 int offset = index - oldLength + skip; 240 int length = bytesRead - offset; 241 out.write(buf, offset, length); 242 } 243 } else 244 out.write(buf, 0, bytesRead); 245 totalBytes += bytesRead; 246 if (progressNotifier != null) 247 progressNotifier.progress("Received ", totalBytes, totalLength); 248 } 249 if (progressNotifier != null) 250 progressNotifier.progressStop(); 251 out.close(); 252 in.close(); 253 socket.close(); 254 socket = null; 255 } 256 catch (Exception e) { 257 Log.error(e); 258 } 259 if (cancelled) 260 cache.delete(); 261 if (!cache.isFile()) 262 cache = null; 263 if (!cancelled && render && redirected && redirectionCount < 5) { 264 if (cache != null) { 265 if (cache.isFile()) 266 cache.delete(); 267 cache = null; 268 } 269 File parent = file.getParentFile(); 270 if (parent != null) { 271 file = HttpFile.getHttpFile((HttpFile)parent, location); 273 ++redirectionCount; 274 load(); 275 return; 276 } 277 } 278 if (cache != null) { 279 final HttpFile httpFile = (HttpFile) file; 281 httpFile.setCache(cache); 282 httpFile.setHeaders(sbHeaders.toString()); 283 httpFile.setContentType(contentType); 284 httpFile.setEncoding(encoding); 285 cache.setEncoding(encoding); 286 if (successRunnable != null) 287 SwingUtilities.invokeLater(successRunnable); 288 } else if (cancelled) { 289 if (cancelRunnable != null) 290 SwingUtilities.invokeLater(cancelRunnable); 291 } else if (errorRunnable != null) 292 SwingUtilities.invokeLater(errorRunnable); 293 } 294 295 private void connect(final String hostName, final int port) 296 { 297 Debug.assertTrue(socket == null); 298 Log.debug("Connecting to " + hostName + " on port " + port + "..."); 299 if (progressNotifier != null) 300 progressNotifier.setText("Connecting to " + hostName + " on port " + port + "..."); 301 SocketConnection sc = new SocketConnection(hostName, port, 30000, 200, this); 302 socket = sc.connect(); 303 if (socket != null) { 304 if (progressNotifier != null) 305 progressNotifier.setText("Connected to " + hostName); 306 } else 307 setErrorText(sc.getErrorText()); 308 } 309 310 private boolean findProvider() 311 { 312 Provider provider = null; 313 try { 314 provider = 315 (Provider ) Class.forName("com.sun.net.ssl.internal.ssl.Provider").newInstance(); 316 } 317 catch (Exception e) {} 318 if (provider != null) { 319 Security.addProvider(provider); 320 System.setProperty("java.protocol.handler.pkgs", 321 "com.sun.net.ssl.internal.www.protocol"); 322 return true; 323 } 324 return false; 325 } 326 327 private Socket createSSLSocket(String hostName, int port) 328 { 329 try { 330 Class SSLSocketFactory = Class.forName("javax.net.ssl.SSLSocketFactory"); 332 java.lang.reflect.Method getDefault = SSLSocketFactory.getMethod("getDefault", new Class [0]); 333 Object factory = getDefault.invoke(null, new Object [0]); 334 335 Class [] parameterTypes = new Class [2]; 337 parameterTypes[0] = String .class; 338 parameterTypes[1] = Integer.TYPE; 339 java.lang.reflect.Method createSocket = factory.getClass().getMethod("createSocket", parameterTypes); 340 Object [] args = new Object [2]; 341 args[0] = hostName; 342 args[1] = new Integer (port); 343 Socket socket = (Socket ) createSocket.invoke(factory, args); 344 return socket; 345 } 346 catch (Throwable t) { 347 Log.error(t); 348 return null; 349 } 350 } 351 352 private static int getStatusCode(String responseHeaders) 353 { 354 int begin = responseHeaders.indexOf(' ') + 1; 355 if (begin == 0) 356 return -1; 357 int end = responseHeaders.indexOf(' ', begin); 358 if (end < 0) 359 return -1; 360 try { 361 return Utilities.parseInt(responseHeaders.substring(begin, end)); 362 } 363 catch (NumberFormatException e) { 364 return -1; 365 } 366 } 367 368 private static String getLocation(String responseHeaders) 369 { 370 final String lookFor = "\nlocation:"; 371 final int index = responseHeaders.toLowerCase().indexOf(lookFor); 372 if (index < 0) 373 return null; 374 final int begin = index + lookFor.length(); 375 final int end = responseHeaders.indexOf('\n', begin); 376 if (end < 0) 377 return null; 378 String location = responseHeaders.substring(begin, end).trim(); 379 if (location.startsWith("http:/") && !location.startsWith("http://")) { 380 location = "http://".concat(location.substring(6)); 382 } 383 return location; 384 } 385 386 private static int getContentLength(String responseHeaders) 387 { 388 final String lookFor = "\r\ncontent-length:"; 389 final int index = responseHeaders.toLowerCase().indexOf(lookFor); 390 if (index < 0) 391 return 0; final String value = responseHeaders.substring(index + lookFor.length()).trim(); 393 try { 394 return Utilities.parseInt(value); 395 } 396 catch (NumberFormatException e) { 397 return 0; 398 } 399 } 400 401 private void error(String errorText) 402 { 403 Log.error(errorText); 404 if (errorRunnable != null) { 405 errorRunnable.setMessage(errorText); 406 SwingUtilities.invokeLater(errorRunnable); 407 } 408 } 409 410 public static void httpShowHeaders() 411 { 412 final Editor editor = Editor.currentEditor(); 413 final Buffer buffer = editor.getBuffer(); 414 final File file = buffer.getFile(); 415 if (file instanceof HttpFile) { 416 editor.setWaitCursor(); 417 final String title = "httpShowHeaders ".concat(file.netPath()); 418 Buffer buf = null; 419 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 420 Buffer b = it.nextBuffer(); 421 if (b instanceof OutputBuffer && b.getParentBuffer() == buffer) { 422 if (title.equals(b.getTitle())) { 423 buf = b; 424 break; 425 } 426 } 427 } 428 if (buf == null) { 429 buf = OutputBuffer.getOutputBuffer(((HttpFile)file).getHeaders()); 430 buf.setParentBuffer(buffer); 431 buf.setTitle(title); 432 } 433 editor.makeNext(buf); 434 editor.activateInOtherWindow(buf); 435 editor.setDefaultCursor(); 436 } 437 } 438 } 439 | Popular Tags |