You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2009/11/11 13:38:14 UTC

svn commit: r834853 [2/2] - in /james/hupa/trunk: ./ client/src/main/java/org/apache/hupa/client/mvp/ client/src/main/java/org/apache/hupa/client/mvp/place/ server/src/main/java/org/apache/hupa/server/guice/ server/src/main/java/org/apache/hupa/server/...

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/GetMessageDetailsHandler.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/GetMessageDetailsHandler.java?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/GetMessageDetailsHandler.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/handler/GetMessageDetailsHandler.java Wed Nov 11 12:38:13 2009
@@ -1,253 +1,337 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.hupa.server.handler;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-
-import javax.mail.Flags;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Multipart;
-import javax.mail.Part;
-import javax.mail.Flags.Flag;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeUtility;
-import javax.servlet.http.HttpSession;
-
-import net.customware.gwt.dispatch.server.ExecutionContext;
-import net.customware.gwt.dispatch.shared.ActionException;
-
-import org.apache.commons.logging.Log;
-import org.apache.hupa.server.IMAPStoreCache;
-import org.apache.hupa.shared.data.IMAPFolder;
-import org.apache.hupa.shared.data.MessageAttachment;
-import org.apache.hupa.shared.data.MessageDetails;
-import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.rpc.GetMessageDetails;
-import org.apache.hupa.shared.rpc.GetMessageDetailsResult;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.sun.mail.imap.IMAPStore;
-
-public class GetMessageDetailsHandler extends
-        AbstractSessionHandler<GetMessageDetails, GetMessageDetailsResult> {
-
-    @Inject
-    public GetMessageDetailsHandler(IMAPStoreCache cache, Log logger,
-            Provider<HttpSession> sProvider) {
-        super(cache, logger, sProvider);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.hupa.server.handler.AbstractSessionHandler#executeInternal
-     * (org.apache.hupa.shared.rpc.Session,
-     * net.customware.gwt.dispatch.server.ExecutionContext)
-     */
-    public GetMessageDetailsResult executeInternal(GetMessageDetails action,
-            ExecutionContext arg1) throws ActionException {
-        return new GetMessageDetailsResult(exposeMessage(getUser(), action.getFolder(), action.getUid()));
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
-     */
-    public Class<GetMessageDetails> getActionType() {
-        return GetMessageDetails.class;
-    }
-
-    protected MessageDetails exposeMessage(User user, IMAPFolder folder,
-            long uid) throws ActionException {
-        IMAPStore store = null;
-        com.sun.mail.imap.IMAPFolder f = null;
-        try {
-            store = cache.get(user);
-
-            f = (com.sun.mail.imap.IMAPFolder) store
-                    .getFolder(folder.getFullName());
-
-            if (f.isOpen() == false) {
-                f.open(com.sun.mail.imap.IMAPFolder.READ_WRITE);
-            }
-            
-            MimeMessage message = (MimeMessage) f.getMessageByUID(uid);
-
-            MessageDetails mDetails = mimeToDetails(message);
-
-            mDetails.setUid(uid);
-            if (mDetails.isHTML()) {
-            	mDetails.setText(changeHtmlLinks(mDetails.getText(), f.getFullName(), uid));
-            }
-            
-            f.setFlags(new Message[] { message }, new Flags(Flag.SEEN), true);
-
-            return mDetails;
-        } catch (Exception e) {
-            logger.error("Unable to expose msg for user " + user
-                    + " in folder " + folder + " with uid " + uid, e);
-            throw new ActionException("Unable to expose msg for user " + user
-                    + " in folder " + folder + " with uid " + uid);
-
-        } finally {
-            if (f != null && f.isOpen()) {
-                try {
-                    f.close(false);
-                } catch (MessagingException e) {
-                    // ignore on close
-                }
-            }
-        }
-    }
-
-	protected MessageDetails mimeToDetails(MimeMessage message)
-            throws IOException, MessagingException,
-            UnsupportedEncodingException {
-	    MessageDetails mDetails = new MessageDetails();
-
-	    
-	    Object con = message.getContent();
-
-	    StringBuffer sbPlain = new StringBuffer();
-	    ArrayList<MessageAttachment> attachmentList = new ArrayList<MessageAttachment>();
-
-	    boolean isHTML = handleParts(message, con, sbPlain, attachmentList);
-
-	    mDetails.setText(sbPlain.toString());
-
-	    mDetails.setIsHTML(isHTML);
-	    mDetails.setMessageAttachments(attachmentList);
-
-	    mDetails.setRawHeader(message.getAllHeaders().toString());
-	    return mDetails;
-    }
-	
-	// TODO: use constants for servlet paths to match DispatchServlet configuration (also in client side)
-	protected String changeHtmlLinks(String html, String folderName, long uuid) {
-		html = html.replaceAll("(img\\s+src=\")cid:([^\"]+\")", 
-				"$1/hupa/downloadAttachmentServlet?folder_name=" 
-				+ folderName + "&message_uuid=" + uuid + "&attachment_name=$2");
-		return html;
-	}
-
-    /**
-     * Handle the parts of the given message. The method will call itself recursively to handle all nested parts
-     * @param message the MimeMessage 
-     * @param con the current processing Content
-     * @param sbPlain the StringBuffer to fill with text
-     * @param attachmentList ArrayList with attachments
-     * @throws UnsupportedEncodingException
-     * @throws MessagingException
-     * @throws IOException
-     */
-    private boolean handleParts(MimeMessage message, Object con,
-            StringBuffer sbPlain,
-            ArrayList<MessageAttachment> attachmentList)
-            throws UnsupportedEncodingException, MessagingException,
-            IOException {
-    	boolean isHTML = false;
-        if (con instanceof String) {
-            System.out.println("sc: " + message.getContentType());
-            if (message.getContentType().startsWith("text/html")) {
-                isHTML = true;
-            } else {
-                isHTML = false;
-            }
-            sbPlain.append((String) con);
-
-        } else if (con instanceof Multipart) {
-
-            Multipart mp = (Multipart) con;
-            String multipartContentType = mp.getContentType().toLowerCase();
-            System.out.println("mc: " + multipartContentType);
-            
-            String text = null;
-
-            if (multipartContentType.startsWith("multipart/alternative")) {
-                isHTML = handleMultiPartAlternative(mp, sbPlain);
-            } else {
-                for (int i = 0; i < mp.getCount(); i++) {
-                    Part part = mp.getBodyPart(i);
-
-                    String contentType = part.getContentType().toLowerCase();
-                    System.out.println("c: " + contentType);
-
-                    if (text == null && contentType.startsWith("text/plain") ) {
-                        isHTML = false;
-                        text = (String)part.getContent();
-                    } else if (contentType.startsWith("text/html")) {
-                        isHTML = true;
-                        text = (String)part.getContent();
-                    } else if (contentType.startsWith("message/rfc822")) {
-                        // Extract the message and pass it
-                        MimeMessage msg = (MimeMessage) part.getDataHandler().getContent();
-                        isHTML =  handleParts(msg, msg.getContent(), sbPlain, attachmentList);
-                    } else {
-                        if (part.getFileName() != null) {
-                            MessageAttachment attachment = new MessageAttachment();
-                            attachment.setName(MimeUtility.decodeText(part
-                                    .getFileName()));
-                            attachment.setContentType(part.getContentType());
-                            attachment.setSize(part.getSize());
-
-                            attachmentList.add(attachment);
-                        } else {
-                            isHTML = handleParts(message, part.getContent(), sbPlain, attachmentList);
-                        }
-                    }
-
-                }
-                if (text != null)
-                	sbPlain.append(text);
-            }
-
-        }
-        return isHTML;
-    }
-    
-    private boolean handleMultiPartAlternative(Multipart mp, StringBuffer sbPlain) throws MessagingException, IOException {
-        String text = null;
-        boolean isHTML = false;
-        for (int i = 0; i < mp.getCount(); i++) {
-            Part part = mp.getBodyPart(i);
-            
-            String contentType = part.getContentType().toLowerCase();
-            System.out.println("m: " + contentType);
-
-            // we prefer html
-            if (text == null && contentType.startsWith("text/plain")) {
-                isHTML = false;
-                text = (String) part.getContent();
-            } else if (contentType.startsWith("text/html")) {
-                isHTML = true;
-                text = (String) part.getContent();
-            } 
-        }
-        sbPlain.append(text);
-        return isHTML;
-    }
-    
-}
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.server.handler;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import javax.mail.Flags;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
+import javax.mail.Flags.Flag;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeUtility;
+import javax.servlet.http.HttpSession;
+
+import net.customware.gwt.dispatch.server.ExecutionContext;
+import net.customware.gwt.dispatch.shared.ActionException;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.shared.SConsts;
+import org.apache.hupa.shared.data.IMAPFolder;
+import org.apache.hupa.shared.data.MessageAttachment;
+import org.apache.hupa.shared.data.MessageDetails;
+import org.apache.hupa.shared.data.User;
+import org.apache.hupa.shared.rpc.GetMessageDetails;
+import org.apache.hupa.shared.rpc.GetMessageDetailsResult;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.sun.mail.imap.IMAPStore;
+
+public class GetMessageDetailsHandler extends
+        AbstractSessionHandler<GetMessageDetails, GetMessageDetailsResult> {
+
+    @Inject
+    public GetMessageDetailsHandler(IMAPStoreCache cache, Log logger,
+            Provider<HttpSession> sProvider) {
+        super(cache, logger, sProvider);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.hupa.server.handler.AbstractSessionHandler#executeInternal
+     * (org.apache.hupa.shared.rpc.Session,
+     * net.customware.gwt.dispatch.server.ExecutionContext)
+     */
+    public GetMessageDetailsResult executeInternal(GetMessageDetails action,
+            ExecutionContext arg1) throws ActionException {
+        return new GetMessageDetailsResult(exposeMessage(getUser(), action.getFolder(), action.getUid()));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see net.customware.gwt.dispatch.server.ActionHandler#getActionType()
+     */
+    public Class<GetMessageDetails> getActionType() {
+        return GetMessageDetails.class;
+    }
+
+    protected MessageDetails exposeMessage(User user, IMAPFolder folder,
+            long uid) throws ActionException {
+        IMAPStore store = null;
+        com.sun.mail.imap.IMAPFolder f = null;
+        try {
+            store = cache.get(user);
+
+            f = (com.sun.mail.imap.IMAPFolder) store
+                    .getFolder(folder.getFullName());
+
+            if (f.isOpen() == false) {
+                f.open(com.sun.mail.imap.IMAPFolder.READ_WRITE);
+            }
+            
+            MimeMessage message = (MimeMessage) f.getMessageByUID(uid);
+
+            MessageDetails mDetails = mimeToDetails(message, f.getFullName(), uid);
+
+            mDetails.setUid(uid);
+            
+            f.setFlags(new Message[] { message }, new Flags(Flag.SEEN), true);
+
+            return mDetails;
+        } catch (Exception e) {
+            logger.error("Unable to expose msg for user " + user
+                    + " in folder " + folder + " with uid " + uid, e);
+            throw new ActionException("Unable to expose msg for user " + user
+                    + " in folder " + folder + " with uid " + uid);
+
+        } finally {
+            if (f != null && f.isOpen()) {
+                try {
+                    f.close(false);
+                } catch (MessagingException e) {
+                    // ignore on close
+                }
+            }
+        }
+    }
+
+	protected MessageDetails mimeToDetails(MimeMessage message, String folderName, long uid)
+            throws IOException, MessagingException,
+            UnsupportedEncodingException {
+	    MessageDetails mDetails = new MessageDetails();
+
+	    
+	    Object con = message.getContent();
+
+	    StringBuffer sbPlain = new StringBuffer();
+	    ArrayList<MessageAttachment> attachmentList = new ArrayList<MessageAttachment>();
+
+	    
+	    boolean isHTML = handleParts(message, con, sbPlain, attachmentList);
+
+        if (isHTML) {
+        	mDetails.setText(filterHtmlDocument(sbPlain.toString(), folderName, uid));
+        } else {
+        	mDetails.setText(txtDocumentToHtml(sbPlain.toString(), folderName, uid));
+        }
+
+	    mDetails.setMessageAttachments(attachmentList);
+
+	    mDetails.setRawHeader(message.getAllHeaders().toString());
+	    return mDetails;
+    }
+
+    /**
+     * Handle the parts of the given message. The method will call itself recursively to handle all nested parts
+     * @param message the MimeMessage 
+     * @param con the current processing Content
+     * @param sbPlain the StringBuffer to fill with text
+     * @param attachmentList ArrayList with attachments
+     * @throws UnsupportedEncodingException
+     * @throws MessagingException
+     * @throws IOException
+     */
+    private boolean handleParts(MimeMessage message, Object con,
+            StringBuffer sbPlain,
+            ArrayList<MessageAttachment> attachmentList)
+            throws UnsupportedEncodingException, MessagingException,
+            IOException {
+    	boolean isHTML = false;
+        if (con instanceof String) {
+            System.out.println("sc: " + message.getContentType());
+            if (message.getContentType().startsWith("text/html")) {
+                isHTML = true;
+            } else {
+                isHTML = false;
+            }
+            sbPlain.append((String) con);
+
+        } else if (con instanceof Multipart) {
+
+            Multipart mp = (Multipart) con;
+            String multipartContentType = mp.getContentType().toLowerCase();
+            System.out.println("mc: " + multipartContentType);
+            
+            String text = null;
+
+            if (multipartContentType.startsWith("multipart/alternative")) {
+                isHTML = handleMultiPartAlternative(mp, sbPlain);
+            } else {
+                for (int i = 0; i < mp.getCount(); i++) {
+                    Part part = mp.getBodyPart(i);
+
+                    String contentType = part.getContentType().toLowerCase();
+                    System.out.println("c: " + contentType);
+
+                    if (text == null && contentType.startsWith("text/plain") ) {
+                        isHTML = false;
+                        text = (String)part.getContent();
+                    } else if (contentType.startsWith("text/html")) {
+                        isHTML = true;
+                        text = (String)part.getContent();
+                    } else if (contentType.startsWith("message/rfc822")) {
+                        // Extract the message and pass it
+                        MimeMessage msg = (MimeMessage) part.getDataHandler().getContent();
+                        isHTML =  handleParts(msg, msg.getContent(), sbPlain, attachmentList);
+                    } else {
+                        if (part.getFileName() != null) {
+                            MessageAttachment attachment = new MessageAttachment();
+                            attachment.setName(MimeUtility.decodeText(part
+                                    .getFileName()));
+                            attachment.setContentType(part.getContentType());
+                            attachment.setSize(part.getSize());
+
+                            attachmentList.add(attachment);
+                        } else {
+                            isHTML = handleParts(message, part.getContent(), sbPlain, attachmentList);
+                        }
+                    }
+
+                }
+                if (text != null)
+                	sbPlain.append(text);
+            }
+
+        }
+        return isHTML;
+    }
+    
+    private boolean handleMultiPartAlternative(Multipart mp, StringBuffer sbPlain) throws MessagingException, IOException {
+        String text = null;
+        boolean isHTML = false;
+        for (int i = 0; i < mp.getCount(); i++) {
+            Part part = mp.getBodyPart(i);
+            
+            String contentType = part.getContentType().toLowerCase();
+            System.out.println("m: " + contentType);
+
+            // we prefer html
+            if (text == null && contentType.startsWith("text/plain")) {
+                isHTML = false;
+                text = (String) part.getContent();
+            } else if (contentType.startsWith("text/html")) {
+                isHTML = true;
+                text = (String) part.getContent();
+            } 
+        }
+        sbPlain.append(text);
+        return isHTML;
+    }
+    
+    
+    static String HTML_LINK_REGEXP =  "\\b?(https?://[\\w\\d:#@%/;$\\(\\)~_\\?\\+\\-=\\\\.&]*)\\b?";
+    static Pattern regex_http = Pattern.compile(HTML_LINK_REGEXP);
+    static String repl_http = "<a href=\"$1\">$1</a>";
+
+    static String EMAIL_REGEXP =  "\\b([A-z0-9._%\\+\\-]+@[A-z0-9\\.\\-]+\\.[A-z]{2,4})\\b";
+    static Pattern regex_email = Pattern.compile(EMAIL_REGEXP);
+    static String repl_email = "<a href=\"mailto:$1\">$1</a>";
+    
+    static Pattern regex_inlineImg = Pattern.compile("(?si)(<\\s*img\\s+.*?src=[\"'])cid:([^\"']+[\"'])");
+    static String repl_inlineImg = "$1" + SConsts.HUPA + SConsts.SERVLET_DOWNLOAD 
+                            + "?" + SConsts.PARAM_FOLDER + "=%%FOLDER%%" 
+                            + "&" + SConsts.PARAM_UID + "=%%UID%%" 
+                            + "&" + SConsts.PARAM_NAME + "=$2";
+
+    static Pattern regex_badTags = Pattern.compile("(?si)<(script|style|head).*?</\\1\\s*>");
+    static String repl_badTags = "";
+
+    static Pattern regex_unneededTags = Pattern.compile("(?si)(</?(html|body)[^>]*?>)");
+    static String repl_unneededTags = "";
+
+    static Pattern regex_badAttrs = Pattern.compile("(?si)(<)(\\w+)(\\s.+?)onClick=(\".+?\"|'.+?')(.*?</)(\\2)(\\s*>)");
+    static String repl_badAttrs = "$1$2$3 $5$6$7";
+    
+    static Pattern regex_orphandHttpLinks = Pattern.compile("(?si)(?!.*<a\\s?[^>]*?>.+</a\\s*>.*)(>[^<>]*)" + HTML_LINK_REGEXP + "([^<>]*<)");
+    static String repl_orphandHttpLinks = "$1<a href=\"$2\">$2</a>$3";
+    
+    static Pattern regex_existingHttpLinks = Pattern.compile("(?si)<a\\s[^>]*?href=[\"']?" + HTML_LINK_REGEXP + "[\"']?");
+    static String repl_existingHttpLinks = "<a onClick=\"openLink('$1');return false;\" href=\"$1\"";
+
+    static Pattern regex_orphandEmailLinks = Pattern.compile("(?si)(?!.*<a\\s?[^>]*?>.+</a\\s*>.*)<([A-z]+?)(.*?)>(.*[\\s>])" + EMAIL_REGEXP + "(.*)</\\1>");
+    static String repl_orphandEmailLinks = "<$1$2>$3<a href=\"mailto:$4\">$4</a>$5</$1>";
+
+    static Pattern regex_existingEmailLinks = Pattern.compile("(?si)<a\\s[^>]*?href=[\"']*mailto:[\"']?([^\"]+)[\"']?");
+    static String repl_existngEmailLinks = "<a onClick=\"mailTo('$1');return false;\" href=\"mailto:$1\"";
+    
+    protected String replaceAll(String txt, Pattern pattern, String repl) {
+        return pattern.matcher(txt).replaceAll(repl);
+    }
+
+    protected String txtDocumentToHtml(String txt, String folderName, long uuid) {
+        
+        if (txt == null || txt.length()==0)
+            return txt;
+
+        // escape html tags symbols 
+        txt = txt.replaceAll("<", "&lt;");
+        txt = txt.replaceAll(">", "&gt;");
+        
+        // enclose between <a> http links and emails
+        txt = replaceAll(txt, regex_http, repl_http);
+        txt = replaceAll(txt, regex_email, repl_email);
+        
+        // put break lines
+        txt = txt.replaceAll("\r", "").replaceAll("\n", "<br/>\n");
+        
+        txt = filterHtmlDocument(txt, folderName, uuid);
+
+        return txt;
+    }
+    
+    protected String filterHtmlDocument(String html, String folderName, long uuid) {
+        
+        if (html == null || html.length()==0)
+            return html;
+
+        // wrap the entire html document in a classed div
+        html = "<div class='hupa-email-content'>\n" + html + "\n</div>\n";
+        
+        // Replace in-line images links to use Hupa's download servlet
+        html = replaceAll(html, regex_inlineImg, repl_inlineImg).replaceAll("%%FOLDER%%",folderName).replaceAll("%%UID%%", String.valueOf(uuid));
+        // Remove head, script and style tags to avoid interferences with Hupa
+        html = replaceAll(html, regex_badTags, repl_badTags);
+        // Remove body and html tags
+        html = replaceAll(html, regex_unneededTags, repl_unneededTags);
+        // Remove all onClick attributes 
+        html = replaceAll(html, regex_badAttrs, repl_badAttrs);
+        // Add <a> tags to links which are not already into <a>
+        html = replaceAll(html, regex_orphandHttpLinks, repl_orphandHttpLinks);
+        // Add javascript method to <a> in order to open links in a different window
+        html = replaceAll(html, regex_existingHttpLinks, repl_existingHttpLinks);
+        // Add <a> tags to emails which are not already into <a>
+        html = replaceAll(html, regex_orphandEmailLinks, repl_orphandEmailLinks);
+        // Add a js method to mailto links in order to compose new mails inside hupa
+        html = replaceAll(html, regex_existingEmailLinks, repl_existngEmailLinks);
+        
+        return html;
+    }
+    
+}

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/DownloadAttachmentServlet.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/DownloadAttachmentServlet.java?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/DownloadAttachmentServlet.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/DownloadAttachmentServlet.java Wed Nov 11 12:38:13 2009
@@ -1,197 +1,198 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.hupa.server.servlet;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import javax.mail.Folder;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Multipart;
-import javax.mail.Part;
-import javax.mail.Store;
-import javax.mail.internet.MimeUtility;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.hupa.server.InMemoryIMAPStoreCache;
-import org.apache.hupa.shared.data.User;
-
-import com.google.inject.Inject;
-import com.sun.mail.imap.IMAPFolder;
-
-/**
- * Handle download of attachments
- * 
- *
- */
-public class DownloadAttachmentServlet extends HttpServlet {
-
-    /**
-     * 
-     */
-    private static final long serialVersionUID = 1245563204035792963L;
-    private InMemoryIMAPStoreCache cache;
-    private Log logger;
-
-    @Inject
-    public DownloadAttachmentServlet(InMemoryIMAPStoreCache cache, Log logger) {
-        this.cache = cache;
-        this.logger = logger;
-    }
-
-    @Override
-    protected void doPost(HttpServletRequest request,
-            HttpServletResponse response) throws ServletException, IOException {
-        doGet(request, response);
-    }
-
-    /**
-     * Handle to write back the requested attachment
-     */
-    @Override
-    protected void doGet(HttpServletRequest request,
-            HttpServletResponse response) throws ServletException, IOException {
-    	
-    	User user = (User) request.getSession().getAttribute("user");
-    	if (user == null)
-    		throw new ServletException("Invalid session");
-    	
-        String message_uuid = request.getParameter("message_uuid");
-        String attachmentName = request.getParameter("attachment_name");
-        String folderName = request.getParameter("folder_name");
-        response.setHeader("Content-disposition", "attachment; filename="
-                + attachmentName + "");
-        InputStream in = null;
-        OutputStream out = response.getOutputStream();
-
-        IMAPFolder folder = null;
-        try {
-            Store store = cache.get(user);
-            folder = (IMAPFolder) store.getFolder(folderName);
-            if (folder.isOpen() == false) {
-                folder.open(Folder.READ_ONLY);
-            }
-            Message m = folder.getMessageByUID(Long.parseLong(message_uuid));
-            
-            Object content = m.getContent();
-            Part part  = handleMultiPart(content, attachmentName);
-            if (part.getContentType()!=null)
-            	response.setContentType(part.getContentType());
-            else
-                response.setContentType("application/download");
-            
-            in = part.getInputStream();
-            if (in != null) {
-                byte[] buffer = new byte[4096];
-                int bytesRead;
-                int bytesComplete = 0;
-                while ((bytesRead = in.read(buffer)) != -1) {
-                    bytesComplete = bytesComplete + bytesRead;
-                    out.write(buffer, 0, bytesRead); // write
-                }
-                response.setContentLength(bytesComplete);
-            } else {
-                response.setContentLength(0);
-            }
-            
-            out.flush();
-            
-        } catch (Exception e) {
-            logger.error("Error while downloading attachment "
-                    + attachmentName + " of message " + message_uuid
-                    + " for user " + user.getName(), e);
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    // ignore on close
-                }
-            }
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    // ignore on close
-                }
-            }
-            if (folder != null) {
-                try {
-                    folder.close(false);
-                } catch (MessagingException e) {
-                    // ignore on close
-                }
-            }
-
-        }
-    }
-    
-    /**
-     * Loop over MuliPart and write the content to the Outputstream if a
-     * attachment with the given name was found.
-     * 
-     * @param out
-     *            Outputstream to write the content to
-     * @param content
-     *            Content which should checked for attachments
-     * @param attachmentName
-     *            The attachmentname or the unique id for the searched attachment
-     * @throws MessagingException
-     * @throws IOException
-     */
-    static protected Part handleMultiPart(Object content, String attachmentName)
-            throws MessagingException, IOException {
-        if (content instanceof Multipart) {
-            Multipart part = (Multipart) content;
-            for (int i = 0; i < part.getCount(); i++) {
-                Part bodyPart = part.getBodyPart(i);
-                String fileName = bodyPart.getFileName();
-                String[] contentId = bodyPart.getHeader("Content-ID");
-                if (bodyPart.isMimeType("multipart/*")) {
-                    Part p = handleMultiPart(bodyPart.getContent(), attachmentName);
-                    if (p != null)
-                    	return p;
-                } else {
-                	if (contentId != null) {
-                    	for (String id: contentId) {
-                    		id = id.replaceAll("^.*<(.+)>.*$", "$1");
-                    		if (attachmentName.equals(id))
-                    			return bodyPart;
-                    	}
-                    } 
-                	if (fileName != null){
-                        if (attachmentName.equalsIgnoreCase(MimeUtility.decodeText(fileName))) 
-                            return bodyPart;
-                    }
-                } 
-            }
-        } else {
-        	System.out.println("Unknown content: " + content.getClass().getName());
-        }
-        return null;
-    }
-
-}
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.server.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
+import javax.mail.Store;
+import javax.mail.internet.MimeUtility;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.InMemoryIMAPStoreCache;
+import org.apache.hupa.shared.SConsts;
+import org.apache.hupa.shared.data.User;
+
+import com.google.inject.Inject;
+import com.sun.mail.imap.IMAPFolder;
+
+/**
+ * Handle download of attachments
+ * 
+ *
+ */
+public class DownloadAttachmentServlet extends HttpServlet {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1245563204035792963L;
+    private InMemoryIMAPStoreCache cache;
+    private Log logger;
+
+    @Inject
+    public DownloadAttachmentServlet(InMemoryIMAPStoreCache cache, Log logger) {
+        this.cache = cache;
+        this.logger = logger;
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException {
+        doGet(request, response);
+    }
+
+    /**
+     * Handle to write back the requested attachment
+     */
+    @Override
+    protected void doGet(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException {
+    	
+    	User user = (User) request.getSession().getAttribute("user");
+    	if (user == null)
+    		throw new ServletException("Invalid session");
+    	
+        String message_uuid = request.getParameter(SConsts.PARAM_UID);
+        String attachmentName = request.getParameter(SConsts.PARAM_NAME);
+        String folderName = request.getParameter(SConsts.PARAM_FOLDER);
+        response.setHeader("Content-disposition", "attachment; filename="
+                + attachmentName + "");
+        InputStream in = null;
+        OutputStream out = response.getOutputStream();
+
+        IMAPFolder folder = null;
+        try {
+            Store store = cache.get(user);
+            folder = (IMAPFolder) store.getFolder(folderName);
+            if (folder.isOpen() == false) {
+                folder.open(Folder.READ_ONLY);
+            }
+            Message m = folder.getMessageByUID(Long.parseLong(message_uuid));
+            
+            Object content = m.getContent();
+            Part part  = handleMultiPart(content, attachmentName);
+            if (part.getContentType()!=null)
+            	response.setContentType(part.getContentType());
+            else
+                response.setContentType("application/download");
+            
+            in = part.getInputStream();
+            if (in != null) {
+                byte[] buffer = new byte[4096];
+                int bytesRead;
+                int bytesComplete = 0;
+                while ((bytesRead = in.read(buffer)) != -1) {
+                    bytesComplete = bytesComplete + bytesRead;
+                    out.write(buffer, 0, bytesRead); // write
+                }
+                response.setContentLength(bytesComplete);
+            } else {
+                response.setContentLength(0);
+            }
+            
+            out.flush();
+            
+        } catch (Exception e) {
+            logger.error("Error while downloading attachment "
+                    + attachmentName + " of message " + message_uuid
+                    + " for user " + user.getName(), e);
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                    // ignore on close
+                }
+            }
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    // ignore on close
+                }
+            }
+            if (folder != null) {
+                try {
+                    folder.close(false);
+                } catch (MessagingException e) {
+                    // ignore on close
+                }
+            }
+
+        }
+    }
+    
+    /**
+     * Loop over MuliPart and write the content to the Outputstream if a
+     * attachment with the given name was found.
+     * 
+     * @param out
+     *            Outputstream to write the content to
+     * @param content
+     *            Content which should checked for attachments
+     * @param attachmentName
+     *            The attachmentname or the unique id for the searched attachment
+     * @throws MessagingException
+     * @throws IOException
+     */
+    static protected Part handleMultiPart(Object content, String attachmentName)
+            throws MessagingException, IOException {
+        if (content instanceof Multipart) {
+            Multipart part = (Multipart) content;
+            for (int i = 0; i < part.getCount(); i++) {
+                Part bodyPart = part.getBodyPart(i);
+                String fileName = bodyPart.getFileName();
+                String[] contentId = bodyPart.getHeader("Content-ID");
+                if (bodyPart.isMimeType("multipart/*")) {
+                    Part p = handleMultiPart(bodyPart.getContent(), attachmentName);
+                    if (p != null)
+                    	return p;
+                } else {
+                	if (contentId != null) {
+                    	for (String id: contentId) {
+                    		id = id.replaceAll("^.*<(.+)>.*$", "$1");
+                    		if (attachmentName.equals(id))
+                    			return bodyPart;
+                    	}
+                    } 
+                	if (fileName != null){
+                        if (attachmentName.equalsIgnoreCase(MimeUtility.decodeText(fileName))) 
+                            return bodyPart;
+                    }
+                } 
+            }
+        } else {
+        	System.out.println("Unknown content: " + content.getClass().getName());
+        }
+        return null;
+    }
+
+}

Modified: james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java (original)
+++ james/hupa/trunk/server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java Wed Nov 11 12:38:13 2009
@@ -31,6 +31,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.hupa.server.InMemoryIMAPStoreCache;
+import org.apache.hupa.shared.SConsts;
 import org.apache.hupa.shared.data.User;
 
 import com.google.inject.Inject;
@@ -60,14 +61,14 @@
 
         User user = (User) request.getSession().getAttribute("user");
 
-        String message_uid = (String) request.getParameter("uid");
-        String folder = (String) request.getParameter("folder");
+        String message_uuid = request.getParameter(SConsts.PARAM_UID);
+        String folderName = request.getParameter(SConsts.PARAM_FOLDER);
         
         try {
-            long uid = Long.parseLong(message_uid);
+            long uid = Long.parseLong(message_uuid);
 
             IMAPStore store = cache.get(user);
-            IMAPFolder f = (IMAPFolder) store.getFolder(folder);
+            IMAPFolder f = (IMAPFolder) store.getFolder(folderName);
             if (f.isOpen() == false) {
                 f.open(Folder.READ_ONLY);
             }
@@ -84,8 +85,9 @@
                 f.close(false);
             }
         } catch (Exception e) {
-            logger.error("Unable to get raw content of msg for user " + user + " in folder " + folder + " with uid " + message_uid, e);
-            throw new ServletException("Unable to get raw content of msg for user " + user + " in folder " + folder + " with uid " + message_uid);
+        	String msg = "Unable to get raw content of msg for user " + user + " in folder " + folderName + " with uid " + message_uuid;
+            logger.error(msg, e);
+            throw new ServletException(msg);
         }
     }
 

Modified: james/hupa/trunk/server/src/main/resources/mime/0.msg
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/resources/mime/0.msg?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/resources/mime/0.msg (original)
+++ james/hupa/trunk/server/src/main/resources/mime/0.msg Wed Nov 11 12:38:13 2009
@@ -4,6 +4,14 @@
 
 This is a demo message without any content-type and date in the headers.
 This content has to be rendered as normal text without any format.
-These are a bunch of  html tags:
 
+Links and emails have to be enclosed in links
+
+http://www.google.com
+Mail: nobody@localhost.com
+
+Html tags have to be escaped
+
+<a href="http://www.google.com">google</a>
 <a> <b> <div> <pre> </pre> 
+

Modified: james/hupa/trunk/server/src/main/resources/mime/2.msg
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/main/resources/mime/2.msg?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/server/src/main/resources/mime/2.msg (original)
+++ james/hupa/trunk/server/src/main/resources/mime/2.msg Wed Nov 11 12:38:13 2009
@@ -35,6 +35,16 @@
 Content-Type: text/html; charset=ISO-8859-1
 Content-Transfer-Encoding: quoted-printable
 
+<html>
+<head>
+</head>
+<body>
+ <script language="whatever">
+  var whatever = 1;
+ </script>
+ <style>
+ .aClass{}
+ </style>
 Thanks a lot! I will give it a shot tonight.<br><br><br><br>=
 Cheers,<br>Donald<br><br><br><br><br><div class=3D"gmail_quote">On Thu, Oc=
 t 15, 2009 at 11:35 AM, Pe=F1a <span dir=3D"ltr">&lt;<a h=
@@ -46,6 +56,14 @@
 <br>
 Regards<br>
 Manolo<br>
+
+Web Page: <a href="http://code.google.com/intl/es/webtoolkit/">GWT</a><br/>
+Email Address: <a href="mailto:donald@example.com">donald@example.com</a>
 </blockquote></div><br>
+</body>
+ <script language="whatever">
+  var whatever = 1;
+ </script>
+</html>
 
 --000e0cd1fd7203f7ae0475f6134e--

Modified: james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java (original)
+++ james/hupa/trunk/server/src/test/java/org/apache/hupa/server/handler/GetMessageDetailsHandlerTest.java Wed Nov 11 12:38:13 2009
@@ -25,6 +25,7 @@
 
 import org.apache.hupa.server.mock.MockIMAPFolder;
 import org.apache.hupa.server.mock.MockIMAPStore;
+import org.apache.hupa.shared.SConsts;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.MessageDetails;
 
@@ -32,26 +33,155 @@
 	
 	GetMessageDetailsHandler handler = new GetMessageDetailsHandler(storeCache, logger, httpSessionProvider);
 
+	public void testRegexHtml() {
+        String txt, res;
+        txt = "<!'https://www.aaa.1:#@%/;$()~_?+-=\\.&<br/>";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_http, "");
+        assertEquals("<!'<br/>", res);
+    }
+
+    public void testRegexEmail() {
+        String txt, res;
+        txt = "!aBcD091_%55-+.aa@abc01-01.dd-a.aBc+";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_email, "");
+        assertEquals("!+", res);
+    }
+
+    public void testRegexInlineImg() {
+        String txt, res;
+        txt = ".. <img\nsrc=\"cid:abcd\"\nwhatever=/>click</a\n> ..";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_inlineImg, GetMessageDetailsHandler.repl_inlineImg);
+        assertEquals(".. <img\nsrc=\"hupa/downloadAttachmentServlet?folder=%%FOLDER%%&uid=%%UID%%&name=abcd\"\nwhatever=/>click</a\n> ..", res);
+    }
+    
+    public void testRegexBadTags() {
+        String txt, res;
+        txt = "<html><head>h<tag></head><body>.<style>..</style>.<script type=>//</script></body>.</html>";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_badTags, GetMessageDetailsHandler.repl_badTags);
+        res = handler.replaceAll(res, GetMessageDetailsHandler.regex_unneededTags, GetMessageDetailsHandler.repl_unneededTags);
+        assertEquals("...", res);
+    }
+    
+    public void testRegexHtmlLinks() {
+        String txt, res;
+        txt = ".. <a href=\"http://whatever\">..</a> ..";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_existingHttpLinks, GetMessageDetailsHandler.repl_existingHttpLinks);
+        assertEquals(".. <a onClick=\"openLink('http://whatever');return false;\" href=\"http://whatever\">..</a> ..", res);
+
+        txt = "-- <div> .. <img src=\"http://whatever\"/> .. </div>";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_orphandHttpLinks, GetMessageDetailsHandler.repl_orphandHttpLinks);
+        assertEquals(txt, res);
+        
+        txt = "-- <div> .. \"http://whatever\" .. </div>";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_orphandHttpLinks, GetMessageDetailsHandler.repl_orphandHttpLinks);
+        assertEquals("-- <div> .. \"<a href=\"http://whatever\">http://whatever</a>\" .. </div>", res);
+
+        res = handler.replaceAll(res, GetMessageDetailsHandler.regex_existingHttpLinks, GetMessageDetailsHandler.repl_existingHttpLinks);
+        assertEquals("-- <div> .. \"<a onClick=\"openLink('http://whatever');return false;\" href=\"http://whatever\">http://whatever</a>\" .. </div>", res);
+        
+    }
+    
+    public void testRegexEmailLinks() {
+        String txt, res;
+        txt = ".. <a href=\"mailTo:someone@somedomain.com\">..</a> ..";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_existingEmailLinks, GetMessageDetailsHandler.repl_existngEmailLinks);
+        assertEquals(".. <a onClick=\"mailTo('someone@somedomain.com');return false;\" href=\"mailto:someone@somedomain.com\">..</a> ..", res);
+        
+        txt = "-- <div> .. someone@somedomain.com .. </div>";
+        res = handler.replaceAll(txt, GetMessageDetailsHandler.regex_orphandEmailLinks, GetMessageDetailsHandler.repl_orphandEmailLinks);
+        assertEquals("-- <div> .. <a href=\"mailto:someone@somedomain.com\">someone@somedomain.com</a> .. </div>", res);
+
+        res = handler.replaceAll(res, GetMessageDetailsHandler.regex_existingEmailLinks, GetMessageDetailsHandler.repl_existngEmailLinks);
+        assertEquals("-- <div> .. <a onClick=\"mailTo('someone@somedomain.com');return false;\" href=\"mailto:someone@somedomain.com\">someone@somedomain.com</a> .. </div>", res);
+        
+    }
+
+    public void testHtmlIsWrapped() throws Exception {
+        
+        String html = handler.filterHtmlDocument("whatever", "foldername", 111l);
+        assertEquals("<div class='hupa-email-content'>\nwhatever\n</div>\n", html);
+        
+        html = handler.txtDocumentToHtml("whatever", "foldername", 111l);
+        assertEquals("<div class='hupa-email-content'>\nwhatever\n</div>\n", html);
+    }
+    
+	public void testTextDocumentToHtml() throws Exception {
+
+		String msg = "...\nhttp://www.example.com/path/action.do;s=1;a=2?p=abcd\n...";
+    	String res = handler.txtDocumentToHtml(msg, "aFolder", 9999l);
+    	assertNotSame(msg, res);
+    	assertTrue(res.contains("onClick=\"openLink('http://"));
+    	
+    	msg = "...\nnobody@subdomain.the-domain.org\n...";
+    	res = handler.txtDocumentToHtml(msg, "aFolder", 9999l);
+    	assertNotSame(msg, res);
+    	assertTrue(res.contains("onClick=\"mailTo('nobody@"));
+    	
+    	res = handler.txtDocumentToHtml("", "aFolder", 9999l);
+    	assertTrue(res.length()==0);
+    	
+    }
+
+	public void testFilterHtmlDocument() throws Exception {
+
+		String msg = "<div>...\nhttp://whatever\n...</div>";
+    	String res = handler.txtDocumentToHtml(msg, "aFolder", 9999l);
+    	assertNotSame(msg, res);
+    	assertTrue(res.contains("onClick=\"openLink('http://whatever"));
+		
+		msg = "...\n<a\nhref=https://www.example.com/path/action.do;s=1;a=2?p=abcd\n...";
+		res = handler.filterHtmlDocument(msg, "aFolder", 9999l);
+		assertNotSame(msg, res);
+		assertTrue(res.contains("onClick=\"openLink('https://"));
+
+		msg = "...\n<a\nhref=mailTo:nobody@subdomain.the-domain.org\n...";
+		res = handler.filterHtmlDocument(msg, "aFolder", 9999l);
+		assertNotSame(msg, res);
+		assertTrue(res.contains("onClick=\"mailTo('nobody@"));
+
+		msg = "...\n...<img   \n   src=\"cid:1.1934304663@web28309.mail.ukl.yahoo.com\" width=200\n....";
+		res = handler.filterHtmlDocument(msg, "aFolder", 9999l);
+		assertNotSame(msg, res);
+		assertEquals("<div class='hupa-email-content'>\n...\n...<img   \n   src=\"" + 
+				SConsts.HUPA + SConsts.SERVLET_DOWNLOAD + "?" 
+				+ SConsts.PARAM_FOLDER + "=aFolder&" 
+				+ SConsts.PARAM_UID + "=9999&"
+		        + SConsts.PARAM_NAME + "=1.1934304663@web28309.mail.ukl.yahoo.com\" width=200\n....\n</div>\n", res);
+		
+		msg = "\n\n.... <Script \ntype=\"whatever\"\n>\nalert('hello');\n</script > ---\n\n";
+		res = handler.filterHtmlDocument(msg, "aFolder", 9999l);
+		assertNotSame(msg, res);
+
+		msg = "\n\n.... <a \nid=\"whatever\"\nonclick=\"alert('hello');\"\n</a > ---\n\n";
+		res = handler.filterHtmlDocument(msg, "aFolder", 9999l);
+		assertNotSame(msg, res);
+
+		msg = "\n\n.... <style \ntype=\"whatever\"\n>\n.a{};\n</Style > ---\n\n";
+		res = handler.filterHtmlDocument(msg, "aFolder", 9999l);
+		assertNotSame(msg, res);
+		
+        res = handler.filterHtmlDocument("", "aFolder", 9999l);
+	    assertTrue(res.length()==0);
+
+	}
+
 	private MessageDetails loadMessageDetails(String msgFile) throws Exception {
-        return handler.mimeToDetails(loadMessage(msgFile));
+        return handler.mimeToDetails(loadMessage(msgFile), "theFolder", 9999l);
     }
 	
     public void testMessageDetails_textPlain() throws Exception {
     	MessageDetails details = loadMessageDetails("0.msg");
-    	assertFalse(details.isHTML());
-    	assertTrue(details.getText().length() > 0);
+    	assertTrue(details.getText().contains("demo message"));
     }
 
     public void testMessageDetails_multiparMixed() throws Exception {
     	MessageDetails details = loadMessageDetails("1.msg");
-    	assertFalse(details.isHTML());
     	assertEquals(1, details.getMessageAttachments().size());
-    	assertTrue(details.getText().length() > 0);
+        assertTrue(details.getText().contains("Regards"));
     }
 
     public void testMessageDetails_multiparAlternative() throws Exception {
     	MessageDetails details = loadMessageDetails("2.msg");
-    	assertTrue(details.isHTML());
     	assertEquals(0, details.getMessageAttachments().size());
     	assertTrue(details.getText().length() > 0);
     }
@@ -62,23 +192,21 @@
     	assertTrue(from.contains("\u00AE"));
     	
     	MessageDetails details = loadMessageDetails("3.msg");
-    	assertTrue(details.isHTML());
     	assertEquals(0, details.getMessageAttachments().size());
     	assertTrue(details.getText().length() > 0);
     }
 
     public void testMessageDetails_textHtml() throws Exception {
     	MessageDetails details = loadMessageDetails("4.msg");
-    	assertTrue(details.isHTML());
     	assertTrue(details.getText().length() > 0);
     }
     
     public void testMessageDetails_multiparMixed_multipartAlternative() throws Exception {
     	MessageDetails details = loadMessageDetails("6.msg");
-    	assertTrue(details.isHTML());
     	assertEquals(1, details.getMessageAttachments().size());
     	assertTrue(details.getText().length() > 0);
     }
+    
 
     public void testMessageDetails_html_with_inline_images() throws Exception {
     	
@@ -89,12 +217,24 @@
     	MimeMessage msg = loadMessage("7.msg");
     	serverfolder.addMessages(new Message[]{msg});
 
-        
         IMAPFolder clientfolder = new IMAPFolder("WHATEVER");
         MessageDetails details = handler.exposeMessage(user, clientfolder, 0);
-    	assertTrue(details.isHTML());
-        assertTrue(details.getText().contains("img src=\"/hupa/downloadAttachmentServlet?folder_name=WHATEVER&message_uuid=0&attachment_name=1.1934304663@web28309.mail.ukl.yahoo.com\""));
+        assertTrue(details.getText().contains("img src=\"" + 
+        		SConsts.HUPA + SConsts.SERVLET_DOWNLOAD + "?" +
+        		SConsts.PARAM_FOLDER + "=WHATEVER&" + 
+        		SConsts.PARAM_UID + "=0&" + 
+        		SConsts.PARAM_NAME + "=1.1934304663@web28309.mail.ukl.yahoo.com\""));
     	
     }
-    
+
+    public void testMessageDetails_links() throws Exception {
+    	MessageDetails details = loadMessageDetails("2.msg");
+
+    	String html = handler.filterHtmlDocument(details.getText(), "foldername", 111l);
+    	assertFalse(html.contains("<script>"));
+    	assertFalse(html.contains("<style>"));
+    	assertTrue(html.contains("<a onClick=\"openLink('http://code.google.com/intl/es/webtoolkit/');return false;\" href=\"http://code.google.com/intl/es/webtoolkit/\""));
+    	assertTrue(html.contains("<a onClick=\"mailTo('donald@example.com');return false;\" href=\"mailto:donald@example.com\""));
+    }
+
 }

Added: james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/SConsts.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/SConsts.java?rev=834853&view=auto
==============================================================================
--- james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/SConsts.java (added)
+++ james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/SConsts.java Wed Nov 11 12:38:13 2009
@@ -0,0 +1,15 @@
+package org.apache.hupa.shared;
+
+public class SConsts {
+	public static final String HUPA = "hupa/";
+	public static final String SERVLET_DISPATCH = "dispatch";
+	public static final String SERVLET_DOWNLOAD = "downloadAttachmentServlet";
+	public static final String SERVLET_UPLOAD = "uploadAttachmentServlet";
+	public static final String SERVLET_SOURCE = "messageSourceServlet";
+
+	
+	public static final String PARAM_NAME = "name";
+	public static final String PARAM_FOLDER = "folder";
+	public static final String PARAM_UID = "uid";
+
+}
\ No newline at end of file

Modified: james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/data/MessageDetails.java
URL: http://svn.apache.org/viewvc/james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/data/MessageDetails.java?rev=834853&r1=834852&r2=834853&view=diff
==============================================================================
--- james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/data/MessageDetails.java (original)
+++ james/hupa/trunk/shared/src/main/java/org/apache/hupa/shared/data/MessageDetails.java Wed Nov 11 12:38:13 2009
@@ -1,138 +1,118 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.hupa.shared.data;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-
-public class MessageDetails implements Serializable{
-    /**
-     * 
-     */
-    private static final long serialVersionUID = 7611536915564919521L;
-    private boolean isHTML;
-    private String text;
-    private ArrayList<MessageAttachment> aList;
-    private long uid;
-    private String raw;
-
-    public String toString() {
-        return "uid=" + String.valueOf(getUid()) +
-        " isHTML=" + isHTML +
-        " text.length=" + (text != null ? text.length() : 0) + 
-        " raw.length=" + (raw != null ? raw.length() : 0) + 
-        " attachments=" + (aList != null ? aList.size() : 0); 
-    }
-    
-    
-    public long getUid() {
-        return uid;
-    }
-
-    public void setUid(long uid) {
-        this.uid = uid;
-    }
-    
-    /**
-     * Set a raw String representation of the header
-     * 
-     * @param raw
-     */
-    public void setRawHeader(String raw) {
-        this.raw = raw;
-    }
-
-    /**
-     * Return a raw String representation of the header
-     * 
-     * @return raw
-     */
-    public String getRawHeader() {
-        return raw;
-    }
-    
-    /**
-     * Set if the count is plain/html
-     * 
-     * @param isHTML
-     */
-    public void setIsHTML(boolean isHTML) {
-        this.isHTML = isHTML;
-    }
-
-    /**
-     * Return if the content is plain/html or plain/text
-     * 
-     * @return isHTML
-     */
-    public boolean isHTML() {
-        return isHTML;
-    }
-
-    /**
-     * Set the body text of the content
-     * 
-     * @param text
-     */
-    public void setText(String text) {
-        this.text = text;
-    }
-
-    /**
-     * Return the body text of the content
-     * @return
-     */
-    public String getText() {
-        return text;
-    }
-
-    /**
-     * Set the attachments 
-     * 
-     * @param aList
-     */
-    public void setMessageAttachments(ArrayList<MessageAttachment> aList) {
-        this.aList = aList;
-    }
-
-    /**
-     * Return the attachments 
-     * 
-     * @return aList
-     */
-    public ArrayList<MessageAttachment> getMessageAttachments() {
-        return aList;
-    }
-
-
-    public boolean equals(Object obj) {
-        if (obj instanceof MessageDetails) {
-            if (((MessageDetails)obj).getUid() == getUid()) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    public int hashCode() {
-        Long l = new Long(getUid());
-        return l.intValue() * 16;
-    }
-}
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.shared.data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+public class MessageDetails implements Serializable{
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 7611536915564919521L;
+    private String text;
+    private ArrayList<MessageAttachment> aList;
+    private long uid;
+    private String raw;
+
+    public String toString() {
+        return "uid=" + String.valueOf(getUid()) +
+        " text.length=" + (text != null ? text.length() : 0) + 
+        " raw.length=" + (raw != null ? raw.length() : 0) + 
+        " attachments=" + (aList != null ? aList.size() : 0); 
+    }
+    
+    
+    public long getUid() {
+        return uid;
+    }
+
+    public void setUid(long uid) {
+        this.uid = uid;
+    }
+    
+    /**
+     * Set a raw String representation of the header
+     * 
+     * @param raw
+     */
+    public void setRawHeader(String raw) {
+        this.raw = raw;
+    }
+
+    /**
+     * Return a raw String representation of the header
+     * 
+     * @return raw
+     */
+    public String getRawHeader() {
+        return raw;
+    }
+    
+    /**
+     * Set the body text of the content
+     * 
+     * @param text
+     */
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    /**
+     * Return the body text of the content
+     * @return
+     */
+    public String getText() {
+        return text;
+    }
+
+    /**
+     * Set the attachments 
+     * 
+     * @param aList
+     */
+    public void setMessageAttachments(ArrayList<MessageAttachment> aList) {
+        this.aList = aList;
+    }
+
+    /**
+     * Return the attachments 
+     * 
+     * @return aList
+     */
+    public ArrayList<MessageAttachment> getMessageAttachments() {
+        return aList;
+    }
+
+
+    public boolean equals(Object obj) {
+        if (obj instanceof MessageDetails) {
+            if (((MessageDetails)obj).getUid() == getUid()) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    public int hashCode() {
+        Long l = new Long(getUid());
+        return l.intValue() * 16;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org