OSDN Git Service

CVS最新版の全ファイルを追加
[spring-ext/ozacc-mail.git] / src / java / com / ozacc / mail / fetch / impl / sk_jp / CorrectedContentTypeDataSourceUTF7Support.java
1 /*\r
2  * @(#) $Id: CorrectedContentTypeDataSourceUTF7Support.java,v 1.1.2.1 2004/09/29 00:57:59 otsuka Exp $\r
3  * $Revision: 1.1.2.1 $\r
4  * Copyright (c) 2000 Shin Kinoshita All Rights Reserved.\r
5  */\r
6 package com.ozacc.mail.fetch.impl.sk_jp;\r
7 \r
8 import java.io.ByteArrayInputStream;\r
9 import java.io.ByteArrayOutputStream;\r
10 import java.io.IOException;\r
11 import java.io.InputStream;\r
12 \r
13 import javax.activation.DataSource;\r
14 import javax.mail.MessageAware;\r
15 import javax.mail.MessagingException;\r
16 import javax.mail.Part;\r
17 import javax.mail.internet.ContentType;\r
18 import javax.mail.internet.MimeBodyPart;\r
19 import javax.mail.internet.MimeMessage;\r
20 import javax.mail.internet.ParseException;\r
21 \r
22 import com.ozacc.mail.fetch.impl.sk_jp.io.ByteToCharUTF7;\r
23 \r
24 /**\r
25  * Content-Type:の不適合をISO-2022-JPに補正します。\r
26  * さらにcharset=UTF-7の場合にUTF-16のストリームに変換してgetContent()を\r
27  * 無理やり成功させます。<BR>\r
28  * また、未知のTES(Content-Transfer-Encoding:)だった場合に、"7bit"\r
29  * と見なしてボディを取得します。\r
30  * 使用方法は<PRE>\r
31  * Object o = new DataHandler(\r
32  *               new CorrectedContentTypeDataSourceUTF7Support(part, charset)\r
33  *            ).getContent();\r
34  * </PRE><P>のようになります。</P><P>\r
35  * スレッドセーフではありませんので利用者側で排他制御を行ってください。\r
36  * </P>\r
37  * @author Shin\r
38  * @version $Revision: 1.1.2.1 $ $Date: 2004/09/29 00:57:59 $\r
39  */\r
40 class CorrectedContentTypeDataSourceUTF7Support extends CorrectedContentTypeDataSource {\r
41 \r
42         private boolean utf7 = false;\r
43 \r
44         public CorrectedContentTypeDataSourceUTF7Support() {}\r
45 \r
46         public CorrectedContentTypeDataSourceUTF7Support(DataSource dataSource, String defaultCharset) {\r
47                 super(dataSource, defaultCharset);\r
48         }\r
49 \r
50         public CorrectedContentTypeDataSourceUTF7Support(Part part, String defaultCharset)\r
51                                                                                                                                                                                 throws MessagingException {\r
52                 super(part, defaultCharset);\r
53         }\r
54 \r
55         public void setDataSource(DataSource newSource) {\r
56                 super.setDataSource(newSource);\r
57                 utf7 = false;\r
58         }\r
59 \r
60         public void setDefaultCharset(String defaultCharset) {\r
61                 super.setDefaultCharset(defaultCharset);\r
62                 utf7 = false;\r
63         }\r
64 \r
65         public String getContentType() {\r
66                 try {\r
67                         ContentType contentType = new ContentType(super.getContentType());\r
68                         String specifiedCharset = contentType.getParameter("charset");\r
69                         if ("UTF-7".equalsIgnoreCase(specifiedCharset)) {\r
70                                 // UTF-7コンバータが存在しない為、\r
71                                 // 独自フィルタストリームを用いる。\r
72                                 contentType.setParameter("charset", "UTF-16");\r
73                                 utf7 = true;\r
74                         }\r
75                         return contentType.toString();\r
76                 } catch (ParseException e) {\r
77                         throw new InternalError();\r
78                 }\r
79         }\r
80 \r
81         public InputStream getInputStream() throws IOException {\r
82                 InputStream in = null;\r
83                 if (isInvalidEncodingAsMultipart()) {\r
84                         // multipart/*でありながら、不正なTransfer-Encodingだった場合\r
85                         // 2001/09/01 JPhone(SH07)の送信する画像付きメイルが、\r
86                         // Content-Type: multipart/mixed\r
87                         // Content-Transfer-Encoding: base64\r
88                         // 等というメッセージを送る場合があり、JavaMailが\r
89                         // これをデコードできない問題を回避。\r
90                         // multipart/*の場合のContent-Transfer-Encodingは、\r
91                         // "7bit""8bit""binary"に限られる。\r
92                         // それ以外の場合は生ストリームを返すようにしておく。\r
93                         in = getRawInputStream();\r
94                 }\r
95                 if (in == null) {\r
96                         try {\r
97                                 in = super.getInputStream();\r
98                         } catch (IOException e) {\r
99                                 // ここでのIOExceptionはエンコーディング不良の可能性が高い。\r
100                                 // 生InputStreamを得てリトライ\r
101                                 in = getRawInputStream();\r
102                                 if (in == null)\r
103                                         throw e;\r
104                         }\r
105                 }\r
106                 if (!utf7) {\r
107                         return in;\r
108                 }\r
109                 ByteArrayOutputStream out = new ByteArrayOutputStream();\r
110                 int c;\r
111 \r
112                 while ((c = in.read()) != -1) {\r
113                         out.write(c);\r
114                 }\r
115 \r
116                 ByteToCharUTF7 btc = new ByteToCharUTF7();\r
117                 byte[] bytes = out.toByteArray();\r
118                 char[] chars = new char[bytes.length];\r
119 \r
120                 // Bug fixed. Thanx to MOHI.\r
121                 // http://www.sk-jp.com/cgi-bin/treebbs.cgi?all=1220&s=1220\r
122                 int len = btc.convert(bytes, 0, bytes.length, chars, 0, chars.length);\r
123                 char[] w = new char[len];\r
124                 System.arraycopy(chars, 0, w, 0, len);\r
125                 String string = new String(w);\r
126                 return new ByteArrayInputStream(string.getBytes("UTF-16"));\r
127         }\r
128 \r
129         // Transfer-Encodingにしたがったデコードを行う前のストリームを得ます。\r
130         // sourceがMessageAwareでない場合はnullが返されます。\r
131         private InputStream getRawInputStream() throws IOException {\r
132                 if (!(source instanceof MessageAware)) {\r
133                         return null;\r
134                 }\r
135                 Part part = ((MessageAware)source).getMessageContext().getPart();\r
136                 try {\r
137                         if (part instanceof MimeMessage) {\r
138                                 return ((MimeMessage)part).getRawInputStream();\r
139                         } else if (part instanceof MimeBodyPart) {\r
140                                 return ((MimeBodyPart)part).getRawInputStream();\r
141                         } else {\r
142                                 return null;\r
143                         }\r
144                 } catch (MessagingException mex) {\r
145                         throw new IOException(mex.toString());\r
146                 }\r
147         }\r
148 \r
149         // 不正なContent-Transfer-Encodingの場合にtrueを返します。\r
150         private boolean isInvalidEncodingAsMultipart() {\r
151                 try {\r
152                         if (!new ContentType(getContentType()).match("multipart/*")) {\r
153                                 return false;\r
154                         }\r
155                         if (!(source instanceof MessageAware)) {\r
156                                 return false;\r
157                         }\r
158                         Part part = ((MessageAware)source).getMessageContext().getPart();\r
159                         String encoding = ((javax.mail.internet.MimePart)part).getEncoding();\r
160                         if ("7bit".equalsIgnoreCase(encoding) || "8bit".equalsIgnoreCase(encoding)\r
161                                         || "binary".equalsIgnoreCase(encoding)) {\r
162                                 return false;\r
163                         }\r
164                 } catch (Exception e) {\r
165                         // この場合も不正だ、と。\r
166                 }\r
167                 return true;\r
168         }\r
169 \r
170 }