| 1 package com.protomatter.util; 2 3 52 53 import java.io.*; 54 import java.util.*; 55 import java.text.*; 56 57 69 public class MIMEMessage 70 implements Serializable 71 { 72 private Vector attachments; 73 private String boundary; 74 private static String CRLF = "\r\n"; 75 76 79 public MIMEMessage() 80 { 81 attachments = new Vector(); 82 boundary = "--------------74329329-84328432-279-4382"; } 84 85 88 public String getContentType() 89 { 90 return "MULTIPART/MIXED; BOUNDARY=\"" + boundary + "\""; 91 } 92 93 96 public void addAttachment(MIMEAttachment a) 97 { 98 attachments.addElement(a); 99 } 100 101 104 public void removeAttachment(MIMEAttachment a) 105 { 106 attachments.removeElement(a); 107 } 108 109 112 public Enumeration getAttachments() 113 { 114 return attachments.elements(); 115 } 116 117 120 public String getBoundary() 121 { 122 return boundary; 123 } 124 125 128 public void setBoundary(String boundary) 129 { 130 this.boundary = boundary; 131 } 132 133 136 public String toString() 137 { 138 StringWriter sw = new StringWriter(); 139 PrintWriter pw = new PrintWriter(sw); 140 write(pw); 141 pw.flush(); 142 return sw.toString(); 143 } 144 145 148 public void write(PrintWriter w) 149 { 150 Enumeration e = getAttachments(); 151 while (e.hasMoreElements()) 152 { 153 MIMEAttachment a = (MIMEAttachment)e.nextElement(); 154 w.print("--"); 155 w.print(boundary); 156 w.print(CRLF); 157 a.write(w); 158 w.print(CRLF); 159 } 160 w.print("--"); 161 w.print(boundary); 162 w.print("--"); 163 w.print(CRLF); 164 } 165 166 171 public static MIMEMessage parse(InputStream s) 172 throws MIMEException 173 { 174 byte[] data = null; 175 try 176 { 177 data = readInputStreamFully(s); 178 } 179 catch (Exception x) 180 { 181 throw new MIMEException(MessageFormat.format( 182 UtilResources.getResourceString(MessageConstants.MIME_EXCEPTION_IN_INPUT), 183 new Object [] { x.toString() })); 184 } 185 return parse(data); 186 } 187 188 191 public static MIMEMessage parse(byte data[]) 192 throws MIMEException 193 { 194 try 195 { 196 MIMEMessage message = new MIMEMessage(); 197 198 int index = 0; 202 int endIndex = data.length -1; 203 204 try 209 { 210 while (Character.isWhitespace((char)data[index])) ++index; 211 while (Character.isWhitespace((char)data[endIndex])) --endIndex; 212 endIndex++; 213 } 214 catch (Exception x) 215 { 216 throw new MIMEException(UtilResources.getResourceString(MessageConstants.MIME_ALL_WHITESPACE)); 217 } 218 219 Vector v = new Vector(2); 222 v.addElement(new Integer (index)); 223 v.addElement(new Integer (endIndex)); 224 225 String sep = null; 227 try 228 { 229 sep = readLine(data, v); 230 } 231 catch (Exception x) 232 { 233 throw new MIMEException(MessageFormat.format( 234 UtilResources.getResourceString(MessageConstants.MIME_EXCEPTION_IN_SEPARATOR), 235 new Object [] { x.toString() })); 236 } 237 if (sep == null) 238 { 239 throw new MIMEException(UtilResources.getResourceString(MessageConstants.MIME_SEPARATOR_NOT_FOUND)); 240 } 241 242 try 243 { 244 while (index < endIndex) 245 { 246 String line = "x"; 248 Hashtable headers = new Hashtable(); 249 line = readLine(data, v); 250 while (!line.equals("")) { 252 int cIndex = line.indexOf(":"); 254 if (cIndex != -1) { 256 headers.put(line.substring(0, cIndex), line.substring(cIndex +2)); 257 } 258 line = readLine(data, v); 259 } 260 261 StringBuffer info = new StringBuffer (); byte[] content = readBody(sep, data, info, v); 264 265 if (content != null) 267 { 268 MIMEAttachment a = new MIMEAttachment(); 269 a.setHeaders(headers); String encoding = a.getHeader("Content-Transfer-Encoding"); 272 if (encoding != null && encoding.equalsIgnoreCase("BASE64")) 273 { 274 byte[] c = Base64.decode(removeWhitespace(content)); 275 a.setContent(c); 276 a.setBinary(isBinaryContent(c)); 277 } 278 else 279 { 280 a.setContent(content); 281 a.setBinary(isBinaryContent(content)); 282 } 283 message.addAttachment(a); } 285 else 286 { 287 return message; 288 } 289 index = getIndex(v); 290 } 291 } 292 catch (Exception x) 293 { 294 ; } 296 return message; 297 } 298 catch (Exception x) 299 { 300 throw new MIMEException(MessageFormat.format( 301 UtilResources.getResourceString(MessageConstants.MIME_EXCEPTION_IN_PARSE), 302 new Object [] { x.toString() })); 303 } 304 } 305 306 private static final int getIndex(Vector v) 308 { 309 return ((Integer )v.firstElement()).intValue(); 310 } 311 private static final int getEndIndex(Vector v) 312 { 313 return ((Integer )v.elementAt(1)).intValue(); 314 } 315 private static final void setIndex(Vector v, int i) 316 { 317 v.setElementAt(new Integer (i), 0); 318 } 319 private static final void setEndIndex(Vector v, int i) 320 { 321 v.setElementAt(new Integer (i), 1); 322 } 323 324 private final static String readLine(byte[] data, Vector v) 329 throws Exception  330 { 331 int index = getIndex(v); 332 int endIndex = getEndIndex(v); 333 if (index == endIndex) return new String (); 334 int c; 335 ByteArrayOutputStream b = new ByteArrayOutputStream(); 336 while (index < endIndex) 337 { 338 c = (int)data[index]; 339 if (isLF(c)) { 341 index++; 342 setIndex(v, index); 343 return new String (b.toByteArray()); 344 } 345 if (isCR(c)) { 347 index++; 348 if (isLF((int)data[index])) ++index; 349 setIndex(v, index); 350 return new String (b.toByteArray()); 351 } 352 b.write(c); 353 index++; 354 } 355 setIndex(v, index); 356 return new String (b.toByteArray()); 357 } 358 359 362 public static boolean isBinaryContent(byte[] data) 363 { 364 return isBinaryContent(data, 0, data.length); 365 } 366 367 370 public static boolean isBinaryContent(byte[] data, int start, int len) 371 { 372 byte[] d = data; 373 for (int i=start; i<len; i++) 374 { 375 if (((int)d[i]) < 0) 376 return true; 377 } 378 return false; 379 } 380 381 private final static byte[] readBody(String sep, byte data[], StringBuffer info, Vector v) 395 throws MIMEException 396 { 397 int index = getIndex(v); 398 int endIndex = getEndIndex(v); 399 int sepLen = sep.length(); 400 ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 401 402 boolean isBinary = false; 404 info.insert(0, "ascii"); 405 info.setLength(5); 406 407 while (index < endIndex) 408 { 409 if ((int)data[index] < 0 && !isBinary) { 412 info.insert(0, "binary"); 413 info.setLength(6); 414 isBinary = true; 415 } 416 417 if ( isCR((int)data[index]) && isLF((int)data[index +1]) || 419 isLF((int)data[index]) && !isCRLF((int)data[index +1]) ) 420 { 421 int skip = 0; 422 if (isLF((int)data[index +1])) 423 skip = 2; 424 else 425 skip = 1; 426 427 439 String sepTry = null; 441 sepTry = new String (data, index + skip, sepLen); 442 443 if (sepTry.equals(sep)) 445 { 446 if ( ((index + skip + sepLen) == endIndex) || 449 ((index + skip + sepLen + 2) == endIndex) ) 450 { 451 setIndex(v, endIndex); 452 return buffer.toByteArray(); 453 } 454 455 if ( isCR((int)data[skip + index + sepLen]) && isLF((int)data[skip + index + sepLen +1]) || 459 isLF((int)data[skip + index + sepLen]) && !isCRLF((int)data[skip + index + sepLen +1]) ) 460 { 461 if (isLF((int)data[index + sepLen +1])) 463 setIndex(v, index + sepLen + 2); 464 else 465 setIndex(v, index + sepLen + 1); 466 return buffer.toByteArray(); 467 } 468 sepTry = null; 469 buffer.write(data, index, skip); 470 index += skip; 471 } 472 473 else 476 { 477 buffer.write(data, index, skip); 478 index += skip; 479 } 480 } 481 else 482 { 483 buffer.write((int)data[index++]); 484 } 485 } 486 487 setIndex(v, index); 489 return buffer.toByteArray(); 490 } 491 492 private static byte[] readInputStreamFully(InputStream is) 497 throws IOException 498 { 499 ByteArrayOutputStream b = new ByteArrayOutputStream(); 500 { 501 int i = 0; 502 while ((i = is.read()) != -1) 503 b.write(i); 504 } 505 return b.toByteArray(); 506 } 507 508 private final static boolean isCR(int i) 510 { 511 return (i == 13); 512 } 513 514 private final static boolean isLF(int i) 516 { 517 return (i == 10); 518 } 519 520 private final static boolean isCRLF(int i) 522 { 523 return ((i == 10) || (i == 13)); 524 } 525 526 private final static byte[] removeWhitespace(byte[] data) 527 { 528 byte[] d = data; 529 ByteArrayOutputStream out = new ByteArrayOutputStream(); 530 for (int i=0; i<d.length; i++) 531 { 532 if (!Character.isWhitespace((char)d[i])) 533 out.write(d[i]); 534 } 535 return out.toByteArray(); 536 } 537 538 public static void main(String args[]) 539 { 540 if (args.length == 0) 541 { 542 System.out.println("Usage: MIMEMessage parse filename"); 543 System.out.println(" or MIMEMessage create file1..fileN"); 544 System.exit(0); 545 } 546 547 try 548 { 549 String cmd = args[0]; 550 if (cmd.equalsIgnoreCase("parse")) 551 { 552 BufferedInputStream in = new BufferedInputStream( 553 new FileInputStream(new File(args[1]))); 554 long time = System.currentTimeMillis(); 555 MIMEMessage m = MIMEMessage.parse(in); 556 time = System.currentTimeMillis() - time; 557 System.err.println("Parse took " + time + "ms"); 558 System.err.println(""); 559 Enumeration e = m.getAttachments(); 560 while (e.hasMoreElements()) 561 { 562 MIMEAttachment a = (MIMEAttachment)e.nextElement(); 563 System.err.println("Attachment:"); 564 System.err.println(" Headers:"); 565 Enumeration h = a.getHeaderNames(); 566 while (h.hasMoreElements()) 567 { 568 String header = (String )h.nextElement(); 569 System.err.println(" " + header + ": " + a.getHeader(header)); 570 } 571 System.err.println(" Info:"); 572 System.err.println(" Content length: " + a.getContent().length); 573 System.err.println(" Binary: " + a.isBinary()); 574 System.err.println(""); 575 } 576 System.out.println(m); 577 } 578 else 579 { 580 System.err.println("Creating new MIMEMessage"); 581 MIMEMessage m = new MIMEMessage(); 582 for (int i=1; i<args.length; i++) 583 { 584 String file = args[i]; 585 String type = "unknown"; 586 587 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 588 BufferedInputStream in = new BufferedInputStream( 589 new FileInputStream(new File(file))); 590 byte[] buffer = new byte[8192]; 591 int read = 0; 592 while ((read = in.read(buffer)) != -1) 593 bout.write(buffer, 0, read); 594 595 byte[] data = bout.toByteArray(); 596 boolean binary = isBinaryContent(data); 597 MIMEAttachment a = new MIMEAttachment(type, file, 598 data, binary); 599 System.err.println("binary = " + binary); 600 m.addAttachment(a); 601 } 602 603 System.out.println(m); 604 } 605 } 606 catch (Exception x) 607 { 608 x.printStackTrace(); 609 } 610 } 611 } 612 | Popular Tags |