1 2 24 25 26 27 28 package com.lutris.mime; 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 import java.util.Hashtable ; 32 33 import com.lutris.util.BMByteSearch; 34 import com.lutris.util.BMByteSearchStream; 35 36 46 public class MultipartMimeInputStream extends InputStream 47 { 48 53 private BMByteSearchStream inputSource; 54 55 59 private boolean closed; 60 61 64 private BMByteSearch searchPattern; 65 66 70 private static BMByteSearch newlinePattern = null; 71 72 75 private byte[] readByte = new byte[1]; 76 77 80 private boolean atEOF = false; 81 82 85 private String [] rawHeaders = null; 86 87 90 private String [] garbageHeaders = null; 91 92 95 private Hashtable headers = null; 96 97 102 boolean lastPart = false; 103 104 118 protected 119 MultipartMimeInputStream(BMByteSearchStream source, BMByteSearch sep) 120 throws IOException , MimeEOFException 121 { 122 int rawPos=0, garbagePos=0; 123 int n; 124 byte[] lineBuf = new byte[2048]; 125 inputSource = source; 126 searchPattern = sep; 127 128 headers = new Hashtable (); 130 131 if (newlinePattern == null) { 133 newlinePattern = new BMByteSearch("\n"); 134 } 135 inputSource.setPattern(newlinePattern); 136 137 outer: while ((n = readAll(lineBuf)) > 0) { 142 if (lineBuf[n-1] == '\r') --n; if (n <= 0) break outer; String line = new String (bytesToChars(lineBuf,0,n)); 145 String [] newRaw = new String [rawPos + 1]; 146 for (int i=0; i<rawPos; i++) { 147 newRaw[i] = rawHeaders[i]; 148 rawHeaders[i] = null; 149 } 150 newRaw[rawPos++] = line; 151 rawHeaders = newRaw; newRaw = null; 152 try { 153 154 158 MimeHeader header = new ContentHeader(line); 160 161 if ((header.getValue() == null) 162 || (header.getHeaderType() == null)) 163 { 164 String [] newGarbage = new String [garbagePos + 1]; 167 for (int i=0; i<garbagePos; i++) { 168 newGarbage[i] = garbageHeaders[i]; 169 garbageHeaders[i] = null; 170 } 171 newGarbage[garbagePos++] = line; 172 garbageHeaders = newGarbage; newGarbage = null; 173 } else { 174 String name = header.getHeaderType().toLowerCase(); 175 MimeHeader[] hdrs =(MimeHeader[]) headers.get(name); 176 int num = (hdrs == null) ? 0 : hdrs.length; 177 MimeHeader[] newHdrs = new MimeHeader[num+1]; 178 for (int i=0; i<num; i++) { 179 newHdrs[i] = hdrs[i]; 180 hdrs[i] = null; 181 } 182 newHdrs[num] = header; 183 hdrs = null; 184 headers.put(name, newHdrs); 185 } 186 } catch (Exception e) { 187 throw new IOException ("Error while reading " + 188 "MultipartMimeInputStream: " + e.toString()); 189 } 190 } 191 lastPart = false; 195 inputSource.setPattern(searchPattern); 197 } 198 199 211 public 212 int read() 213 throws IOException 214 { 215 int len = read(readByte, 0, 1); 216 if (len != 1) return -1; 217 return ((int)readByte[0] + 0x100) & 0xff; 218 } 219 220 231 public 232 int read(byte[] buffer) 233 throws IOException 234 { 235 return(read(buffer, 0, buffer.length)); 236 } 237 238 250 public 251 int read(byte[] buffer, int offset, int length) 252 throws IOException 253 { 254 checkOpen(); 255 int ret = inputSource.readTo(buffer, offset, length); 256 switch (ret) { 257 case BMByteSearchStream.AT_PATTERN: 258 inputSource.skipPattern(); 259 if (inputSource.peekAheadString(2).equals("--")) lastPart=true; 260 inputSource.setPattern(newlinePattern); 261 inputSource.skipPattern(); 262 atEOF = true; 263 return(-1); 264 case BMByteSearchStream.EOF: 265 return(-1); 266 default: 267 if (ret < 0) return -1; 268 return(ret); 269 } 270 } 271 272 284 public 285 long skip(long num) 286 throws IOException 287 { 288 checkOpen(); 289 byte[] buf = new byte[1024]; 290 long count=0, n; 291 while (count < num) { 292 if (num - count > 1024) 293 n = this.read(buf, 0, 1024); 294 else 295 n = this.read(buf, 0, (int)(num - count)); 296 if (n < 0) break; 297 count += n; 298 } 299 return count; 300 } 301 302 311 public 312 int available() 313 throws IOException 314 { 315 checkOpen(); 316 return(inputSource.availableTo()); 317 } 319 320 327 public 328 void close() 329 throws IOException 330 { 331 if (!atEOF) { 332 inputSource.setPattern(searchPattern); 333 inputSource.skipPattern(); 334 if (inputSource.peekAheadString(2).equals("--")) lastPart=true; 335 inputSource.setPattern(newlinePattern); 336 inputSource.skipPattern(); 337 } 338 atEOF = true; 339 closed = true; 340 } 341 342 351 public 352 MimeHeader getHeader(String headerName) 353 { 354 MimeHeader[] hdrs = 355 (MimeHeader[]) headers.get(headerName.toLowerCase()); 356 if (hdrs == null) return null; 357 if (hdrs.length < 1) return null; 358 return(hdrs[hdrs.length - 1]); 359 } 360 361 369 public 370 MimeHeader[] getHeaders(String headerName) 371 { 372 MimeHeader[] hdrs = 373 (MimeHeader[]) headers.get(headerName.toLowerCase()); 374 if ((hdrs == null) || (hdrs.length < 1)) return null; 375 return hdrs; 376 } 377 378 385 public 386 String [] getRawHeaders() 387 { 388 return rawHeaders; 389 } 390 391 397 public 398 String [] getGarbageHeaders() 399 { 400 return garbageHeaders; 401 } 402 403 405 417 private 418 int readAll(byte[] buffer) 419 throws IOException , MimeEOFException 420 { 421 String la; 422 int pos = 0; 423 int len = buffer.length; 424 int n=0; 425 426 while (pos < len) { 427 switch (n = inputSource.readTo(buffer, pos, len - pos)) { 428 case BMByteSearchStream.EOF: 429 throw new MimeEOFException("EOF"); 430 case BMByteSearchStream.AT_PATTERN: 431 inputSource.skipPattern(); 432 if (inputSource.peekAheadString(2).equals("--")) 433 lastPart=true; 434 return pos; 435 default: 436 pos += n; 437 break; 438 } 439 } 440 inputSource.skipPattern(); 446 return pos; 447 } 448 449 460 private static final 461 char[] bytesToChars(byte[] buffer, int off, int len) 462 { 463 char[] cbuf = new char[len]; 464 int src, dst; 465 for (dst=0,src=off; dst < len; dst++,src++) { 466 cbuf[dst] = (char) (((int)(buffer[src]) + 0x100) & 0xff); 467 } 468 return cbuf; 469 } 470 471 479 private 480 void checkOpen() 481 throws IOException 482 { 483 if (!closed) return; 484 throw new IOException ("Operation on a closed stream."); 485 } 486 487 } 488 | Popular Tags |