1 28 29 package com.caucho.web.webmail; 30 31 import com.caucho.util.ByteBuffer; 32 import com.caucho.util.CharBuffer; 33 import com.caucho.vfs.ReadStream; 34 import com.caucho.vfs.StreamImpl; 35 36 import java.io.IOException ; 37 import java.util.HashMap ; 38 import java.util.Iterator ; 39 40 54 public class MboxStream extends StreamImpl { 55 private byte []boundaryBuffer = "From ".getBytes(); 56 private int boundaryLength = 5; 57 58 private ByteBuffer peekBuffer = new ByteBuffer(); 59 private byte []peek; 60 private int peekOffset; 61 private int peekLength; 62 63 private byte []dummyBuffer = new byte[32]; 64 65 private ReadStream is; 66 private ReadStream readStream; 67 private boolean isPartDone; 68 private boolean isDone; 69 private HashMap headers = new HashMap (); 70 private CharBuffer line = new CharBuffer(); 71 72 private String defaultEncoding; 73 74 public MboxStream() 75 throws IOException 76 { 77 } 78 79 public MboxStream(ReadStream is) 80 throws IOException 81 { 82 this(); 83 84 init(is); 85 } 86 87 90 public String getEncoding() 91 { 92 return defaultEncoding; 93 } 94 95 98 public void setEncoding(String encoding) 99 { 100 this.defaultEncoding = encoding; 101 } 102 103 110 public void init(ReadStream is) 111 throws IOException 112 { 113 this.is = is; 114 115 peekBuffer.setLength(boundaryLength + 5); 116 peek = peekBuffer.getBuffer(); 117 peekOffset = 0; 118 peekLength = 0; 119 peek[peekLength++] = (byte) '\n'; 120 121 isPartDone = false; 122 isDone = false; 123 124 while (read(dummyBuffer, 0, dummyBuffer.length) >= 0) { 125 } 126 127 isPartDone = true; 128 } 129 130 134 public ReadStream openRead() 135 throws IOException 136 { 137 if (isDone) 138 return null; 139 else if (readStream == null) 140 readStream = new ReadStream(this, null); 141 else if (! isPartDone) { 142 int len; 143 while ((len = read(dummyBuffer, 0, dummyBuffer.length)) >= 0) { 144 } 145 146 if (isDone) 147 return null; 148 } 149 150 readStream.init(this, null); 151 152 isPartDone = false; 153 154 if (scanHeaders()) { 155 String contentType = (String ) getAttribute("content-type"); 156 157 String charset = getAttributePart(contentType, "charset"); 158 159 if (charset != null) 160 readStream.setEncoding(charset); 161 else if (defaultEncoding != null) 162 readStream.setEncoding(defaultEncoding); 163 164 return readStream; 165 } 166 else { 167 isDone = true; 168 readStream.close(); 169 return null; 170 } 171 } 172 173 176 public Object getAttribute(String key) 177 { 178 return headers.get(key.toLowerCase()); 179 } 180 181 184 public Iterator getAttributeNames() 185 { 186 return headers.keySet().iterator(); 187 } 188 189 193 private boolean scanHeaders() 194 throws IOException 195 { 196 int ch = read() ; 197 198 headers.clear(); 199 while (ch > 0 && ch != '\n' && ch != '\r') { 200 line.clear(); 201 202 line.append((char) ch); 203 for (ch = read(); 204 ch >= 0 && ch != '\n' && ch != '\r'; 205 ch = read()) { 206 line.append((char) ch); 207 } 208 209 if (ch == '\r') { 210 if ((ch = read()) == '\n') 211 ch = read(); 212 } else if (ch == '\n') 213 ch = read(); 214 215 int i = 0; 216 for (; i < line.length() && line.charAt(i) != ':'; i++) { 217 } 218 219 String key = null; 220 String value = null; 221 if (i < line.length()) { 222 key = line.substring(0, i).trim().toLowerCase(); 223 value = line.substring(i + 1).trim(); 224 225 headers.put(key, value); 226 } 227 } 228 229 if (ch == '\r') { 230 if ((ch = read()) != '\n') { 231 peek[0] = (byte) ch; 232 peekOffset = 0; 233 peekLength = 1; 234 } 235 } 236 237 return true; 238 } 239 240 public boolean canRead() 241 { 242 return true; 243 } 244 245 248 public int read(byte []buffer, int offset, int length) throws IOException 249 { 250 int b = -1; 251 252 if (isPartDone) 253 return -1; 254 255 int i = 0; 256 while (i < length && (b = read()) >= 0) { 257 boolean hasCr = false; 258 259 if (b == '\r') { 260 hasCr = true; 261 b = read(); 262 263 if (b != '\n') { 265 buffer[offset + i++] = (byte) '\r'; 266 peek[0] = (byte) b; 267 peekOffset = 0; 268 peekLength = 1; 269 continue; 270 } 271 } 272 else if (b != '\n') { 273 buffer[offset + i++] = (byte) b; 274 continue; 275 } 276 277 int j; 278 for (j = 0; 279 j < boundaryLength && (b = read()) >= 0 && boundaryBuffer[j] == b; 280 j++) { 281 } 282 283 if (j == boundaryLength) { 284 isPartDone = true; 285 286 while ((b = read()) >= 0 && b != '\r' && b != '\n') { 287 } 288 289 return 1; 290 } 291 292 peekLength = 0; 293 if (hasCr && i + 1 < length) { 294 buffer[offset + i++] = (byte) '\r'; 295 buffer[offset + i++] = (byte) '\n'; 296 } 297 else if (hasCr) { 298 buffer[offset + i++] = (byte) '\r'; 299 peek[peekLength++] = (byte) '\n'; 300 } 301 else { 302 buffer[offset + i++] = (byte) '\n'; 303 } 304 305 int k = 0; 306 while (k < j && i + 1 < length) 307 buffer[offset + i++] = boundaryBuffer[k++]; 308 309 while (k < j) 310 peek[peekLength++] = boundaryBuffer[k++]; 311 312 peek[peekLength++] = (byte) b; 313 peekOffset = 0; 314 } 315 316 if (i <= 0) { 317 isPartDone = true; 318 if (b < 0) 319 isDone = true; 320 return -1; 321 } 322 else { 323 return i; 324 } 325 } 326 327 330 private int read() 331 throws IOException 332 { 333 if (peekOffset < peekLength) 334 return peek[peekOffset++] & 0xff; 335 else 336 return is.read(); 337 } 338 339 private static String getAttributePart(String attr, String name) 340 { 341 if (attr == null) 342 return null; 343 344 int length = attr.length(); 345 int i = attr.indexOf(name); 346 if (i < 0) 347 return null; 348 349 for (i += name.length(); i < length && attr.charAt(i) != '='; i++) { 350 } 351 352 for (i++; i < length && attr.charAt(i) == ' '; i++) { 353 } 354 355 CharBuffer value = CharBuffer.allocate(); 356 if (i < length && attr.charAt(i) == '\'') { 357 for (i++; i < length && attr.charAt(i) != '\''; i++) 358 value.append(attr.charAt(i)); 359 } 360 else if (i < length && attr.charAt(i) == '"') { 361 for (i++; i < length && attr.charAt(i) != '"'; i++) 362 value.append(attr.charAt(i)); 363 } 364 else if (i < length) { 365 char ch; 366 for (; i < length && (ch = attr.charAt(i)) != ' ' && ch != ';'; i++) 367 value.append(ch); 368 } 369 370 return value.close(); 371 } 372 } 373 | Popular Tags |