1 21 22 27 28 package javax.mail.internet; 29 30 import javax.mail.*; 31 import javax.activation.*; 32 import java.io.*; 33 import java.util.*; 34 import com.sun.mail.util.ASCIIUtility; 35 import com.sun.mail.util.LineOutputStream; 36 37 68 69 public class MimeBodyPart extends BodyPart implements MimePart { 70 71 private static boolean setDefaultTextCharset = true; 74 75 private static boolean setContentTypeFileName = true; 76 77 private static boolean encodeFileName = false; 78 private static boolean decodeFileName = false; 79 80 static boolean cacheMultipart = true; 84 static { 85 try { 86 String s = System.getProperty("mail.mime.setdefaulttextcharset"); 87 setDefaultTextCharset = s == null || !s.equalsIgnoreCase("false"); 89 90 s = System.getProperty("mail.mime.setcontenttypefilename"); 91 setContentTypeFileName = s == null || !s.equalsIgnoreCase("false"); 93 94 s = System.getProperty("mail.mime.encodefilename"); 95 encodeFileName = s != null && !s.equalsIgnoreCase("false"); 97 98 s = System.getProperty("mail.mime.decodefilename"); 99 decodeFileName = s != null && !s.equalsIgnoreCase("false"); 101 102 s = System.getProperty("mail.mime.cachemultipart"); 103 cacheMultipart = s == null || !s.equalsIgnoreCase("false"); 105 } catch (SecurityException sex) { 106 } 108 } 109 110 113 protected DataHandler dh; 114 115 118 protected byte[] content; 119 120 129 protected InputStream contentStream; 130 131 135 protected InternetHeaders headers; 136 137 142 public MimeBodyPart() { 143 super(); 144 headers = new InternetHeaders (); 145 } 146 147 162 public MimeBodyPart(InputStream is) throws MessagingException { 163 if (!(is instanceof ByteArrayInputStream) && 164 !(is instanceof BufferedInputStream) && 165 !(is instanceof SharedInputStream )) 166 is = new BufferedInputStream(is); 167 168 headers = new InternetHeaders (is); 169 170 if (is instanceof SharedInputStream ) { 171 SharedInputStream sis = (SharedInputStream )is; 172 contentStream = sis.newStream(sis.getPosition(), -1); 173 } else { 174 try { 175 content = ASCIIUtility.getBytes(is); 176 } catch (IOException ioex) { 177 throw new MessagingException("Error reading input stream", ioex); 178 } 179 } 180 181 } 182 183 192 public MimeBodyPart(InternetHeaders headers, byte[] content) 193 throws MessagingException { 194 super(); 195 this.headers = headers; 196 this.content = content; 197 } 198 199 215 public int getSize() throws MessagingException { 216 if (content != null) 217 return content.length; 218 if (contentStream != null) { 219 try { 220 int size = contentStream.available(); 221 if (size > 0) 224 return size; 225 } catch (IOException ex) { 226 } 228 } 229 return -1; 230 } 231 232 244 public int getLineCount() throws MessagingException { 245 return -1; 246 } 247 248 259 public String getContentType() throws MessagingException { 260 String s = getHeader("Content-Type", null); 261 if (s == null) 262 s = "text/plain"; 263 264 return s; 265 } 266 267 281 public boolean isMimeType(String mimeType) throws MessagingException { 282 return isMimeType(this, mimeType); 283 } 284 285 298 public String getDisposition() throws MessagingException { 299 return getDisposition(this); 300 } 301 302 312 public void setDisposition(String disposition) throws MessagingException { 313 setDisposition(this, disposition); 314 } 315 316 327 public String getEncoding() throws MessagingException { 328 return getEncoding(this); 329 } 330 331 339 public String getContentID() throws MessagingException { 340 return getHeader("Content-Id", null); 341 } 342 343 355 public void setContentID(String cid) throws MessagingException { 356 if (cid == null) 357 removeHeader("Content-ID"); 358 else 359 setHeader("Content-ID", cid); 360 } 361 362 370 public String getContentMD5() throws MessagingException { 371 return getHeader("Content-MD5", null); 372 } 373 374 382 public void setContentMD5(String md5) throws MessagingException { 383 setHeader("Content-MD5", md5); 384 } 385 386 395 public String [] getContentLanguage() throws MessagingException { 396 return getContentLanguage(this); 397 } 398 399 405 public void setContentLanguage(String [] languages) 406 throws MessagingException { 407 setContentLanguage(this, languages); 408 } 409 410 425 public String getDescription() throws MessagingException { 426 return getDescription(this); 427 } 428 429 454 public void setDescription(String description) throws MessagingException { 455 setDescription(description, null); 456 } 457 458 484 public void setDescription(String description, String charset) 485 throws MessagingException { 486 setDescription(this, description, charset); 487 } 488 489 508 public String getFileName() throws MessagingException { 509 return getFileName(this); 510 } 511 512 533 public void setFileName(String filename) throws MessagingException { 534 setFileName(this, filename); 535 } 536 537 552 public InputStream getInputStream() 553 throws IOException, MessagingException { 554 return getDataHandler().getInputStream(); 555 } 556 557 566 protected InputStream getContentStream() throws MessagingException { 567 if (contentStream != null) 568 return ((SharedInputStream )contentStream).newStream(0, -1); 569 if (content != null) 570 return new ByteArrayInputStream(content); 571 572 throw new MessagingException("No content"); 573 } 574 575 590 public InputStream getRawInputStream() throws MessagingException { 591 return getContentStream(); 592 } 593 594 601 public DataHandler getDataHandler() throws MessagingException { 602 if (dh == null) 603 dh = new DataHandler(new MimePartDataSource (this)); 604 return dh; 605 } 606 607 628 public Object getContent() throws IOException, MessagingException { 629 Object c = getDataHandler().getContent(); 630 if (cacheMultipart && 631 (c instanceof Multipart || c instanceof Message) && 632 !(dh instanceof CachedDataHandler) && 633 (content != null || contentStream != null)) { 634 dh = createCachedDataHandler(c, getContentType()); 635 } 636 return c; 637 } 638 639 649 public void setDataHandler(DataHandler dh) 650 throws MessagingException { 651 this.dh = dh; 652 MimeBodyPart.invalidateContentHeaders(this); 653 } 654 655 673 public void setContent(Object o, String type) 674 throws MessagingException { 675 if (o instanceof Multipart) { 676 setContent((Multipart)o); 677 } else { 678 setDataHandler(new DataHandler(o, type)); 679 } 680 } 681 682 701 public void setText(String text) throws MessagingException { 702 setText(text, null); 703 } 704 705 716 public void setText(String text, String charset) 717 throws MessagingException { 718 setText(this, text, charset, "plain"); 719 } 720 721 734 public void setText(String text, String charset, String subtype) 735 throws MessagingException { 736 setText(this, text, charset, subtype); 737 } 738 739 749 public void setContent(Multipart mp) throws MessagingException { 750 setDataHandler(new DataHandler(mp, mp.getContentType())); 751 mp.setParent(this); 752 } 753 754 766 public void attachFile(File file) throws IOException, MessagingException { 767 FileDataSource fds = new FileDataSource(file); 768 this.setDataHandler(new DataHandler(fds)); 769 this.setFileName(fds.getName()); 770 } 771 772 784 public void attachFile(String file) throws IOException, MessagingException { 785 File f = new File(file); 786 attachFile(f); 787 } 788 789 798 public void saveFile(File file) throws IOException, MessagingException { 799 OutputStream out = 800 new BufferedOutputStream(new FileOutputStream(file)); 801 InputStream in = this.getInputStream(); 802 try { 803 byte[] buf = new byte[8192]; 804 int len; 805 while ((len = in.read(buf)) > 0) 806 out.write(buf, 0, len); 807 } finally { 808 try { 810 if (in != null) 811 in.close(); 812 } catch (IOException ex) { } 813 try { 814 if (out != null) 815 out.close(); 816 } catch (IOException ex) { } 817 } 818 } 819 820 829 public void saveFile(String file) throws IOException, MessagingException { 830 File f = new File(file); 831 saveFile(f); 832 } 833 834 843 public void writeTo(OutputStream os) 844 throws IOException, MessagingException { 845 writeTo(this, os, null); 846 } 847 848 857 public String [] getHeader(String name) throws MessagingException { 858 return headers.getHeader(name); 859 } 860 861 873 public String getHeader(String name, String delimiter) 874 throws MessagingException { 875 return headers.getHeader(name, delimiter); 876 } 877 878 889 public void setHeader(String name, String value) 890 throws MessagingException { 891 headers.setHeader(name, value); 892 } 893 894 904 public void addHeader(String name, String value) 905 throws MessagingException { 906 headers.addHeader(name, value); 907 } 908 909 912 public void removeHeader(String name) throws MessagingException { 913 headers.removeHeader(name); 914 } 915 916 920 public Enumeration getAllHeaders() throws MessagingException { 921 return headers.getAllHeaders(); 922 } 923 924 928 public Enumeration getMatchingHeaders(String [] names) 929 throws MessagingException { 930 return headers.getMatchingHeaders(names); 931 } 932 933 937 public Enumeration getNonMatchingHeaders(String [] names) 938 throws MessagingException { 939 return headers.getNonMatchingHeaders(names); 940 } 941 942 945 public void addHeaderLine(String line) throws MessagingException { 946 headers.addHeaderLine(line); 947 } 948 949 954 public Enumeration getAllHeaderLines() throws MessagingException { 955 return headers.getAllHeaderLines(); 956 } 957 958 963 public Enumeration getMatchingHeaderLines(String [] names) 964 throws MessagingException { 965 return headers.getMatchingHeaderLines(names); 966 } 967 968 973 public Enumeration getNonMatchingHeaderLines(String [] names) 974 throws MessagingException { 975 return headers.getNonMatchingHeaderLines(names); 976 } 977 978 1000 protected void updateHeaders() throws MessagingException { 1001 updateHeaders(this); 1002 } 1003 1004 1009 static boolean isMimeType(MimePart part, String mimeType) 1010 throws MessagingException { 1011 try { 1013 ContentType ct = new ContentType (part.getContentType()); 1014 return ct.match(mimeType); 1015 } catch (ParseException ex) { 1016 return part.getContentType().equalsIgnoreCase(mimeType); 1017 } 1018 } 1019 1020 static void setText(MimePart part, String text, String charset, 1021 String subtype) throws MessagingException { 1022 if (charset == null) { 1023 if (MimeUtility.checkAscii(text) != MimeUtility.ALL_ASCII) 1024 charset = MimeUtility.getDefaultMIMECharset(); 1025 else 1026 charset = "us-ascii"; 1027 } 1028 part.setContent(text, "text/" + subtype + "; charset=" + 1030 MimeUtility.quote(charset, HeaderTokenizer.MIME)); 1031 } 1032 1033 static String getDisposition(MimePart part) throws MessagingException { 1034 String s = part.getHeader("Content-Disposition", null); 1035 1036 if (s == null) 1037 return null; 1038 1039 ContentDisposition cd = new ContentDisposition (s); 1040 return cd.getDisposition(); 1041 } 1042 1043 static void setDisposition(MimePart part, String disposition) 1044 throws MessagingException { 1045 if (disposition == null) 1046 part.removeHeader("Content-Disposition"); 1047 else { 1048 String s = part.getHeader("Content-Disposition", null); 1049 if (s != null) { 1050 1055 ContentDisposition cd = new ContentDisposition (s); 1056 cd.setDisposition(disposition); 1057 disposition = cd.toString(); 1058 } 1059 part.setHeader("Content-Disposition", disposition); 1060 } 1061 } 1062 1063 static String getDescription(MimePart part) 1064 throws MessagingException { 1065 String rawvalue = part.getHeader("Content-Description", null); 1066 1067 if (rawvalue == null) 1068 return null; 1069 1070 try { 1071 return MimeUtility.decodeText(MimeUtility.unfold(rawvalue)); 1072 } catch (UnsupportedEncodingException ex) { 1073 return rawvalue; 1074 } 1075 } 1076 1077 static void 1078 setDescription(MimePart part, String description, String charset) 1079 throws MessagingException { 1080 if (description == null) { 1081 part.removeHeader("Content-Description"); 1082 return; 1083 } 1084 1085 try { 1086 part.setHeader("Content-Description", MimeUtility.fold(21, 1087 MimeUtility.encodeText(description, charset, null))); 1088 } catch (UnsupportedEncodingException uex) { 1089 throw new MessagingException("Encoding error", uex); 1090 } 1091 } 1092 1093 static String getFileName(MimePart part) throws MessagingException { 1094 String filename = null; 1095 String s = part.getHeader("Content-Disposition", null); 1096 1097 if (s != null) { 1098 ContentDisposition cd = new ContentDisposition (s); 1100 filename = cd.getParameter("filename"); 1101 } 1102 if (filename == null) { 1103 s = part.getHeader("Content-Type", null); 1105 if (s != null) { 1106 try { 1107 ContentType ct = new ContentType (s); 1108 filename = ct.getParameter("name"); 1109 } catch (ParseException pex) { } } 1111 } 1112 if (decodeFileName && filename != null) { 1113 try { 1114 filename = MimeUtility.decodeText(filename); 1115 } catch (UnsupportedEncodingException ex) { 1116 throw new MessagingException("Can't decode filename", ex); 1117 } 1118 } 1119 return filename; 1120 } 1121 1122 static void setFileName(MimePart part, String name) 1123 throws MessagingException { 1124 if (encodeFileName && name != null) { 1125 try { 1126 name = MimeUtility.encodeText(name); 1127 } catch (UnsupportedEncodingException ex) { 1128 throw new MessagingException("Can't encode filename", ex); 1129 } 1130 } 1131 1132 String s = part.getHeader("Content-Disposition", null); 1134 ContentDisposition cd = 1135 new ContentDisposition (s == null ? Part.ATTACHMENT : s); 1136 cd.setParameter("filename", name); 1137 part.setHeader("Content-Disposition", cd.toString()); 1138 1139 1143 if (setContentTypeFileName) { 1144 s = part.getHeader("Content-Type", null); 1145 if (s != null) { 1146 try { 1147 ContentType cType = new ContentType (s); 1148 cType.setParameter("name", name); 1149 part.setHeader("Content-Type", cType.toString()); 1150 } catch (ParseException pex) { } } 1152 } 1153 } 1154 1155 static String [] getContentLanguage(MimePart part) 1156 throws MessagingException { 1157 String s = part.getHeader("Content-Language", null); 1158 1159 if (s == null) 1160 return null; 1161 1162 HeaderTokenizer h = new HeaderTokenizer (s, HeaderTokenizer.MIME); 1164 Vector v = new Vector(); 1165 1166 HeaderTokenizer.Token tk; 1167 int tkType; 1168 1169 while (true) { 1170 tk = h.next(); tkType = tk.getType(); 1172 if (tkType == HeaderTokenizer.Token.EOF) 1173 break; else if (tkType == HeaderTokenizer.Token.ATOM) 1175 v.addElement(tk.getValue()); 1176 else continue; 1178 } 1179 1180 if (v.size() == 0) 1181 return null; 1182 1183 String [] language = new String [v.size()]; 1184 v.copyInto(language); 1185 return language; 1186 } 1187 1188 static void setContentLanguage(MimePart part, String [] languages) 1189 throws MessagingException { 1190 StringBuffer sb = new StringBuffer (languages[0]); 1191 for (int i = 1; i < languages.length; i++) 1192 sb.append(',').append(languages[i]); 1193 part.setHeader("Content-Language", sb.toString()); 1194 } 1195 1196 static String getEncoding(MimePart part) throws MessagingException { 1197 String s = part.getHeader("Content-Transfer-Encoding", null); 1198 1199 if (s == null) 1200 return null; 1201 1202 s = s.trim(); if (s.equalsIgnoreCase("7bit") || s.equalsIgnoreCase("8bit") || 1206 s.equalsIgnoreCase("quoted-printable") || 1207 s.equalsIgnoreCase("binary") || 1208 s.equalsIgnoreCase("base64")) 1209 return s; 1210 1211 HeaderTokenizer h = new HeaderTokenizer (s, HeaderTokenizer.MIME); 1213 1214 HeaderTokenizer.Token tk; 1215 int tkType; 1216 1217 for (;;) { 1218 tk = h.next(); tkType = tk.getType(); 1220 if (tkType == HeaderTokenizer.Token.EOF) 1221 break; else if (tkType == HeaderTokenizer.Token.ATOM) 1223 return tk.getValue(); 1224 else continue; 1226 } 1227 return s; 1228 } 1229 1230 static void setEncoding(MimePart part, String encoding) 1231 throws MessagingException { 1232 part.setHeader("Content-Transfer-Encoding", encoding); 1233 } 1234 1235 static DataHandler createCachedDataHandler(Object o, String mimeType) { 1236 return new CachedDataHandler(o, mimeType); 1237 } 1238 1239 static void updateHeaders(MimePart part) throws MessagingException { 1240 DataHandler dh = part.getDataHandler(); 1241 if (dh == null) return; 1243 1244 try { 1245 String type = dh.getContentType(); 1246 boolean composite = false; 1247 boolean needCTHeader = part.getHeader("Content-Type") == null; 1248 1249 ContentType cType = new ContentType (type); 1250 if (cType.match("multipart/*")) { 1251 composite = true; 1253 Object o = dh.getContent(); 1254 if (o instanceof MimeMultipart ) 1255 ((MimeMultipart )o).updateHeaders(); 1256 else 1257 throw new MessagingException("MIME part of type \"" + 1258 type + "\" contains object of type " + 1259 o.getClass().getName() + " instead of MimeMultipart"); 1260 } else if (cType.match("message/rfc822")) { 1261 composite = true; 1262 } 1263 1264 if (!composite) { if (part.getHeader("Content-Transfer-Encoding") == null) 1268 setEncoding(part, MimeUtility.getEncoding(dh)); 1269 1270 if (needCTHeader && setDefaultTextCharset && 1271 cType.match("text/*") && 1272 cType.getParameter("charset") == null) { 1273 1283 String charset; 1284 String enc = part.getEncoding(); 1285 if (enc != null && enc.equalsIgnoreCase("7bit")) 1286 charset = "us-ascii"; 1287 else 1288 charset = MimeUtility.getDefaultMIMECharset(); 1289 cType.setParameter("charset", charset); 1290 type = cType.toString(); 1291 } 1292 } 1293 1294 1296 if (needCTHeader) { 1298 1304 String s = part.getHeader("Content-Disposition", null); 1305 if (s != null) { 1306 ContentDisposition cd = new ContentDisposition (s); 1308 String filename = cd.getParameter("filename"); 1309 if (filename != null) { 1310 cType.setParameter("name", filename); 1311 type = cType.toString(); 1312 } 1313 } 1314 1315 part.setHeader("Content-Type", type); 1316 } 1317 } catch (IOException ex) { 1318 throw new MessagingException("IOException updating headers", ex); 1319 } 1320 } 1321 1322 static void invalidateContentHeaders(MimePart part) 1323 throws MessagingException { 1324 part.removeHeader("Content-Type"); 1325 part.removeHeader("Content-Transfer-Encoding"); 1326 } 1327 1328 static void writeTo(MimePart part, OutputStream os, String [] ignoreList) 1329 throws IOException, MessagingException { 1330 1331 LineOutputStream los = null; 1333 if (os instanceof LineOutputStream) { 1334 los = (LineOutputStream) os; 1335 } else { 1336 los = new LineOutputStream(os); 1337 } 1338 1339 Enumeration hdrLines = part.getNonMatchingHeaderLines(ignoreList); 1341 while (hdrLines.hasMoreElements()) 1342 los.writeln((String )hdrLines.nextElement()); 1343 1344 los.writeln(); 1346 1347 os = MimeUtility.encode(os, part.getEncoding()); 1350 part.getDataHandler().writeTo(os); 1351 os.flush(); } 1353} 1354 1355 1359class CachedDataHandler extends DataHandler { 1360 public CachedDataHandler(Object o, String mimeType) { 1361 super(o, mimeType); 1362 } 1363} 1364 | Popular Tags |