1 28 29 package com.caucho.vfs; 30 31 import com.caucho.util.ByteBuffer; 32 import com.caucho.util.CharBuffer; 33 34 import java.io.IOException ; 35 import java.util.HashMap ; 36 import java.util.Iterator ; 37 38 52 public class MultipartStream extends StreamImpl { 53 private ByteBuffer _boundary = new ByteBuffer(); 54 private byte []_boundaryBuffer; 55 private int _boundaryLength; 56 57 private ByteBuffer _peekBuffer = new ByteBuffer(); 58 private byte []_peek; 59 private int _peekOffset; 60 private int _peekLength; 61 62 private byte []_dummyBuffer = new byte[32]; 63 64 private ReadStream _is; 65 private ReadStream _readStream; 66 private boolean _isPartDone; 67 private boolean _isDone; 68 private boolean _isComplete; 69 private HashMap <String ,String > _headers = new HashMap <String ,String >(); 70 private CharBuffer _line = new CharBuffer(); 71 72 private String _defaultEncoding; 73 74 public MultipartStream() 75 throws IOException 76 { 77 _boundary = new ByteBuffer(); 78 } 79 80 public MultipartStream(ReadStream is, String boundary) 81 throws IOException 82 { 83 this(); 84 85 init(is, boundary); 86 } 87 88 91 public String getEncoding() 92 { 93 return _defaultEncoding; 94 } 95 96 99 public void setEncoding(String encoding) 100 { 101 _defaultEncoding = encoding; 102 } 103 104 111 public void init(ReadStream is, String headerBoundary) 112 throws IOException 113 { 114 _is = is; 115 116 _boundary.clear(); 117 _boundary.add("--"); 118 _boundary.add(headerBoundary); 119 120 _boundaryBuffer = _boundary.getBuffer(); 121 _boundaryLength = _boundary.getLength(); 122 123 _peekBuffer.setLength(_boundaryLength + 5); 124 _peek = _peekBuffer.getBuffer(); 125 _peekOffset = 0; 126 _peekLength = 0; 127 _peek[_peekLength++] = (byte) '\n'; 128 129 _isPartDone = false; 130 _isDone = false; 131 _isComplete = false; 132 133 while (read(_dummyBuffer, 0, _dummyBuffer.length) >= 0) { 134 } 135 136 _isPartDone = true; 137 } 138 139 142 public boolean isComplete() 143 { 144 return _isComplete; 145 } 146 147 151 public ReadStream openRead() 152 throws IOException 153 { 154 if (_isDone) 155 return null; 156 else if (_readStream == null) 157 _readStream = new ReadStream(this, null); 158 else if (! _isPartDone) { 159 int len; 160 while ((len = read(_dummyBuffer, 0, _dummyBuffer.length)) >= 0) { 161 } 162 163 if (_isDone) 164 return null; 165 } 166 167 _readStream.init(this, null); 168 169 _isPartDone = false; 170 171 if (scanHeaders()) { 172 String contentType = (String ) getAttribute("content-type"); 173 174 String charset = getAttributePart(contentType, "charset"); 175 176 if (charset != null) 177 _readStream.setEncoding(charset); 178 else if (_defaultEncoding != null) 179 _readStream.setEncoding(_defaultEncoding); 180 181 return _readStream; 182 } 183 else { 184 _isDone = true; 185 _readStream.close(); 186 return null; 187 } 188 } 189 190 193 public Object getAttribute(String key) 194 { 195 return _headers.get(key.toLowerCase()); 196 } 197 198 201 public Iterator getAttributeNames() 202 { 203 return _headers.keySet().iterator(); 204 } 205 206 210 private boolean scanHeaders() 211 throws IOException 212 { 213 int ch = read() ; 214 215 _headers.clear(); 216 while (ch > 0 && ch != '\n' && ch != '\r') { 217 _line.clear(); 218 219 _line.append((char) ch); 220 for (ch = read(); 221 ch >= 0 && ch != '\n' && ch != '\r'; 222 ch = read()) { 223 _line.append((char) ch); 224 } 225 226 if (ch == '\r') { 227 if ((ch = read()) == '\n') 228 ch = read(); 229 } else if (ch == '\n') 230 ch = read(); 231 232 int i = 0; 233 for (; i < _line.length() && _line.charAt(i) != ':'; i++) { 234 } 235 236 String key = null; 237 String value = null; 238 if (i < _line.length()) { 239 key = _line.substring(0, i).trim().toLowerCase(); 240 value = _line.substring(i + 1).trim(); 241 242 _headers.put(key, value); 243 } 244 } 245 246 if (ch == '\r') { 247 if ((ch = read()) != '\n') { 248 _peek[0] = (byte) ch; 249 _peekOffset = 0; 250 _peekLength = 1; 251 } 252 } 253 254 return true; 255 } 256 257 public boolean canRead() 258 { 259 return true; 260 } 261 262 265 public int getAvailable() 266 throws IOException 267 { 268 if (_isPartDone) 269 return 0; 270 else if (_peekOffset < _peekLength) 271 return _peekLength - _peekOffset; 272 else { 273 int ch = read(); 274 if (ch < 0) 275 return 0; 276 _peekOffset = 0; 277 _peekLength = 1; 278 _peek[0] = (byte) ch; 279 280 return 1; 281 } 282 } 283 284 287 public int read(byte []buffer, int offset, int length) throws IOException 288 { 289 int b = -1; 290 291 if (_isPartDone) 292 return -1; 293 294 int i = 0; 295 while (_peekOffset + 1 < _peekLength && length > 0) { 297 buffer[offset + i++] = _peek[_peekOffset++]; 298 length--; 299 } 300 301 while (i < length && (b = read()) >= 0) { 302 boolean hasCr = false; 303 304 if (b == '\r') { 305 hasCr = true; 306 b = read(); 307 308 if (b != '\n') { 310 buffer[offset + i++] = (byte) '\r'; 311 _peek[0] = (byte) b; 312 _peekOffset = 0; 313 _peekLength = 1; 314 continue; 315 } 316 } 317 else if (b != '\n') { 318 buffer[offset + i++] = (byte) b; 319 continue; 320 } 321 322 int j; 323 for (j = 0; 324 j < _boundaryLength && (b = read()) >= 0 && _boundaryBuffer[j] == b; 325 j++) { 326 } 327 328 if (j == _boundaryLength) { 329 _isPartDone = true; 330 if ((b = read()) == '-') { 331 if ((b = read()) == '-') { 332 _isDone = true; 333 _isComplete = true; 334 } 335 } 336 337 for (; b > 0 && b != '\r' && b != '\n'; b = read()) { 338 } 339 if (b == '\r' && (b = read()) != '\n') { 340 _peek[0] = (byte) b; 341 _peekOffset = 0; 342 _peekLength = 1; 343 } 344 345 return i > 0 ? i : -1; 346 } 347 348 _peekLength = 0; 349 if (hasCr && i + 1 < length) { 350 buffer[offset + i++] = (byte) '\r'; 351 buffer[offset + i++] = (byte) '\n'; 352 } 353 else if (hasCr) { 354 buffer[offset + i++] = (byte) '\r'; 355 _peek[_peekLength++] = (byte) '\n'; 356 } 357 else { 358 buffer[offset + i++] = (byte) '\n'; 359 } 360 361 int k = 0; 362 while (k < j && i + 1 < length) 363 buffer[offset + i++] = _boundaryBuffer[k++]; 364 365 while (k < j) 366 _peek[_peekLength++] = _boundaryBuffer[k++]; 367 368 _peek[_peekLength++] = (byte) b; 369 _peekOffset = 0; 370 } 371 372 if (i <= 0) { 373 _isPartDone = true; 374 if (b < 0) 375 _isDone = true; 376 return -1; 377 } 378 else { 379 return i; 380 } 381 } 382 383 386 private int read() 387 throws IOException 388 { 389 if (_peekOffset < _peekLength) 390 return _peek[_peekOffset++] & 0xff; 391 else 392 return _is.read(); 393 } 394 395 private static String getAttributePart(String attr, String name) 396 { 397 if (attr == null) 398 return null; 399 400 int length = attr.length(); 401 int i = attr.indexOf(name); 402 if (i < 0) 403 return null; 404 405 for (i += name.length(); i < length && attr.charAt(i) != '='; i++) { 406 } 407 408 for (i++; i < length && attr.charAt(i) == ' '; i++) { 409 } 410 411 CharBuffer value = CharBuffer.allocate(); 412 if (i < length && attr.charAt(i) == '\'') { 413 for (i++; i < length && attr.charAt(i) != '\''; i++) 414 value.append(attr.charAt(i)); 415 } 416 else if (i < length && attr.charAt(i) == '"') { 417 for (i++; i < length && attr.charAt(i) != '"'; i++) 418 value.append(attr.charAt(i)); 419 } 420 else if (i < length) { 421 char ch; 422 for (; i < length && (ch = attr.charAt(i)) != ' ' && ch != ';'; i++) 423 value.append(ch); 424 } 425 426 return value.close(); 427 } 428 } 429 | Popular Tags |