001: // The contents of this file are subject to the Mozilla Public License Version
002: // 1.1
003: //(the "License"); you may not use this file except in compliance with the
004: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
005: //
006: //Software distributed under the License is distributed on an "AS IS" basis,
007: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
008: //for the specific language governing rights and
009: //limitations under the License.
010: //
011: //The Original Code is "The Columba Project"
012: //
013: //The Initial Developers of the Original Code are Frederik Dietz and Timo
014: // Stich.
015: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
016: //
017: //All Rights Reserved.
018: package org.columba.mail.gui.composer.command;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.nio.charset.Charset;
023: import java.nio.charset.UnsupportedCharsetException;
024: import java.text.DateFormat;
025: import java.util.Arrays;
026: import java.util.Iterator;
027:
028: import org.columba.api.command.ICommandReference;
029: import org.columba.api.command.IWorkerStatusController;
030: import org.columba.core.io.StreamUtils;
031: import org.columba.core.xml.XmlElement;
032: import org.columba.mail.command.MailFolderCommandReference;
033: import org.columba.mail.composer.MessageBuilderHelper;
034: import org.columba.mail.config.MailConfig;
035: import org.columba.mail.folder.IMailbox;
036: import org.columba.mail.gui.composer.ComposerModel;
037: import org.columba.mail.gui.composer.util.QuoteFilterInputStream;
038: import org.columba.mail.gui.util.AddressListRenderer;
039: import org.columba.mail.parser.text.HtmlParser;
040: import org.columba.mail.util.MailResourceLoader;
041: import org.columba.ristretto.coder.Base64DecoderInputStream;
042: import org.columba.ristretto.coder.CharsetDecoderInputStream;
043: import org.columba.ristretto.coder.QuotedPrintableDecoderInputStream;
044: import org.columba.ristretto.message.Address;
045: import org.columba.ristretto.message.BasicHeader;
046: import org.columba.ristretto.message.Header;
047: import org.columba.ristretto.message.InputStreamMimePart;
048: import org.columba.ristretto.message.MimeHeader;
049: import org.columba.ristretto.message.MimePart;
050: import org.columba.ristretto.message.MimeTree;
051:
052: /**
053: * Forward message inline, which is the same as replying to someone who is not
054: * the original sender.
055: *
056: * @author fdietz
057: */
058: public class ForwardInlineCommand extends ForwardCommand {
059:
060: protected final String[] headerfields = new String[] { "Subject",
061: "Date", "From", "To" };
062:
063: /**
064: * Constructor for ForwardInlineCommand.
065: *
066: * @param frameMediator
067: * @param references
068: */
069: public ForwardInlineCommand(ICommandReference reference) {
070: super (reference);
071: }
072:
073: public void execute(IWorkerStatusController worker)
074: throws Exception {
075: // create composer model
076: model = new ComposerModel();
077:
078: // get selected folder
079: IMailbox folder = (IMailbox) ((MailFolderCommandReference) getReference())
080: .getSourceFolder();
081:
082: // get first selected message
083: Object[] uids = ((MailFolderCommandReference) getReference())
084: .getUids();
085:
086: // ->set source reference in composermodel
087: // when replying this is the original sender's message
088: // you selected and replied to
089: MailFolderCommandReference ref = new MailFolderCommandReference(
090: folder, uids);
091: model.setSourceReference(ref);
092:
093: // setup to, references and account
094: initHeader(folder, uids);
095:
096: // get mimeparts
097: MimeTree mimePartTree = folder.getMimePartTree(uids[0]);
098:
099: XmlElement html = MailConfig.getInstance()
100: .getMainFrameOptionsConfig().getRoot().getElement(
101: "/options/html");
102:
103: // Which Bodypart shall be shown? (html/plain)
104: MimePart bodyPart = null;
105: Integer[] bodyPartAddress = null;
106: if (Boolean.valueOf(html.getAttribute("prefer")).booleanValue()) {
107: bodyPart = mimePartTree.getFirstTextPart("html");
108: } else {
109: bodyPart = mimePartTree.getFirstTextPart("plain");
110: }
111:
112: if (bodyPart != null) {
113: // setup charset and html
114: initMimeHeader(bodyPart);
115:
116: bodyPartAddress = bodyPart.getAddress();
117:
118: String quotedBodyText = createQuotedBody(bodyPart
119: .getHeader(), folder, uids, bodyPartAddress);
120:
121: /*
122: * *20040210, karlpeder* Remove html comments - they are not
123: * displayed properly in the composer
124: */
125: if (bodyPart.getHeader().getMimeType().getSubtype().equals(
126: "html")) {
127: quotedBodyText = HtmlParser
128: .removeComments(quotedBodyText);
129: }
130:
131: model.setBodyText(quotedBodyText);
132: }
133:
134: // add all attachments
135: MimeTree mt = folder.getMimePartTree(uids[0]);
136: Iterator it = mt.getAllLeafs().iterator();
137: while (it.hasNext()) {
138: MimePart mp = (MimePart) it.next();
139: Integer[] address = mp.getAddress();
140: // skip if bodypart (already added as quoted text)
141: if (Arrays.equals(address, bodyPartAddress))
142: continue;
143:
144: // add attachment
145: InputStream bodyStream = folder.getMimePartBodyStream(
146: uids[0], address);
147: int encoding = mp.getHeader().getContentTransferEncoding();
148:
149: switch (encoding) {
150: case MimeHeader.QUOTED_PRINTABLE:
151: bodyStream = new QuotedPrintableDecoderInputStream(
152: bodyStream);
153: break;
154:
155: case MimeHeader.BASE64:
156: bodyStream = new Base64DecoderInputStream(bodyStream);
157: break;
158: default:
159: }
160:
161: model.addMimePart(new InputStreamMimePart(mp.getHeader(),
162: bodyStream));
163: }
164:
165: }
166:
167: private void initMimeHeader(MimePart bodyPart) {
168: MimeHeader bodyHeader = bodyPart.getHeader();
169:
170: if (bodyHeader.getMimeType().getSubtype().equals("html")) {
171: model.setHtml(true);
172: } else {
173: model.setHtml(false);
174: }
175:
176: // Select the charset of the original message
177: String charset = bodyHeader.getContentParameter("charset");
178:
179: if (charset != null) {
180: try {
181: model.setCharset(Charset.forName(charset));
182: } catch (UnsupportedCharsetException e) {
183: // Stick with the default charset
184: }
185: }
186: }
187:
188: private void initHeader(IMailbox folder, Object[] uids)
189: throws Exception {
190: // get headerfields
191: Header header = folder.getHeaderFields(uids[0],
192: new String[] { "Subject" });
193:
194: BasicHeader rfcHeader = new BasicHeader(header);
195:
196: // set subject
197: model.setSubject(MessageBuilderHelper
198: .createForwardSubject(rfcHeader.getSubject()));
199: }
200:
201: protected String createQuotedBody(MimeHeader header,
202: IMailbox folder, Object[] uids, Integer[] address)
203: throws IOException, Exception {
204: InputStream bodyStream = folder.getMimePartBodyStream(uids[0],
205: address);
206:
207: // Do decoding stuff
208: switch (header.getContentTransferEncoding()) {
209: case MimeHeader.QUOTED_PRINTABLE: {
210: bodyStream = new QuotedPrintableDecoderInputStream(
211: bodyStream);
212: break;
213: }
214:
215: case MimeHeader.BASE64: {
216: bodyStream = new Base64DecoderInputStream(bodyStream);
217: }
218: }
219: String charset = header.getContentParameter("charset");
220: if (charset != null) {
221: bodyStream = new CharsetDecoderInputStream(bodyStream,
222: Charset.forName(charset));
223: }
224:
225: String quotedBody;
226: // Quote original message - different methods for text and html
227: if (model.isHtml()) {
228: // Html: Insertion of text before and after original message
229: // get necessary headerfields
230: BasicHeader rfcHeader = new BasicHeader(folder
231: .getHeaderFields(uids[0], headerfields));
232: String subject = rfcHeader.getSubject();
233: String date = DateFormat.getDateTimeInstance(
234: DateFormat.LONG, DateFormat.MEDIUM).format(
235: rfcHeader.getDate());
236: String from = AddressListRenderer.renderToHTMLWithLinks(
237: new Address[] { rfcHeader.getFrom() }).toString();
238: String to = AddressListRenderer.renderToHTMLWithLinks(
239: rfcHeader.getTo()).toString();
240:
241: // build "quoted" message
242: StringBuffer buf = new StringBuffer();
243: buf.append("<html><body><p>");
244: buf.append(MailResourceLoader.getString("dialog",
245: "composer", "original_message_start"));
246: buf.append("<br>"
247: + MailResourceLoader.getString("header", "header",
248: "subject") + ": " + subject);
249: buf.append("<br>"
250: + MailResourceLoader.getString("header", "header",
251: "date") + ": " + date);
252: buf.append("<br>"
253: + MailResourceLoader.getString("header", "header",
254: "from") + ": " + from);
255: buf.append("<br>"
256: + MailResourceLoader.getString("header", "header",
257: "to") + ": " + to);
258: buf.append("</p>");
259: buf.append(HtmlParser.removeComments( // comments are not displayed
260: // correctly in composer
261: HtmlParser
262: .getHtmlBody(StreamUtils
263: .readCharacterStream(bodyStream)
264: .toString())));
265: buf.append("<p>");
266: buf.append(MailResourceLoader.getString("dialog",
267: "composer", "original_message_end"));
268: buf.append("</p></body></html>");
269:
270: quotedBody = buf.toString();
271: } else {
272: BasicHeader rfcHeader = new BasicHeader(folder
273: .getHeaderFields(uids[0], headerfields));
274: String date = DateFormat.getDateTimeInstance(
275: DateFormat.LONG, DateFormat.MEDIUM).format(
276: rfcHeader.getDate());
277: String from = rfcHeader.getFrom().toString();
278:
279: // Text: Addition of > before each line
280: StringBuffer buf = StreamUtils
281: .readCharacterStream(new QuoteFilterInputStream(
282: bodyStream));
283:
284: buf.insert(0, ">\n");
285: buf.insert(0, "> Date: " + date + "\n");
286: buf.insert(0, "> From: " + from + "\n");
287:
288: quotedBody = buf.toString();
289: }
290:
291: bodyStream.close();
292: return quotedBody;
293: }
294: }
|