1 20 package org.jsmtpd.plugins.filters.snippets; 21 22 import java.io.BufferedReader ; 23 import java.io.ByteArrayInputStream ; 24 import java.io.ByteArrayOutputStream ; 25 import java.io.File ; 26 import java.io.FileReader ; 27 import java.io.IOException ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.Set ; 31 import java.util.regex.Matcher ; 32 import java.util.regex.Pattern ; 33 34 import javax.mail.MessagingException ; 35 import javax.mail.internet.MimeBodyPart ; 36 import javax.mail.internet.MimeMessage ; 37 import javax.mail.internet.MimeMultipart ; 38 import javax.mail.internet.MimePart ; 39 40 import org.apache.commons.logging.Log; 41 import org.apache.commons.logging.LogFactory; 42 import org.jsmtpd.core.common.PluginInitException; 43 import org.jsmtpd.core.common.filter.FilterTreeFailureException; 44 import org.jsmtpd.core.common.filter.FilterTreeSuccesException; 45 import org.jsmtpd.core.common.filter.IFilter; 46 import org.jsmtpd.core.mail.Email; 47 import org.jsmtpd.tools.ByteArrayTool; 48 49 59 public class ReplaceSnippetFilter implements IFilter { 60 61 protected static final int BUFFER_SIZE = 5 * 1024; protected static final String CR_LF = "\r\n"; 63 protected static final String SNIPPET_RE = "[A-Za-z0-9]+"; 64 private Log log = LogFactory.getLog(ReplaceSnippetFilter.class); 65 66 private String suffix; 67 private String prefix; 68 private String path; 69 private Pattern pattern; 70 private String encoding = "utf-8"; 71 72 public ReplaceSnippetFilter() { 73 } 74 75 public void setPath(String path) { 76 this.path = path; 77 } 78 79 public void setPrefix(String prefix) { 80 this.prefix = prefix; 81 } 82 83 public void setSuffix(String suffix) { 84 this.suffix = suffix; 85 } 86 87 public void initPlugin() throws PluginInitException { 88 pattern = Pattern.compile(prefix + "(" + SNIPPET_RE + ")" + suffix, Pattern.MULTILINE); 89 log.debug("Filter initialised with pattern " + pattern.pattern()); 90 } 91 92 public boolean doFilter(Email input) throws FilterTreeFailureException, FilterTreeSuccesException { 93 try { 94 MimeMessage part = new MimeMessage (null, new ByteArrayInputStream (input.getDataAsByte())); 95 replaceSnippets(input.getFrom().getUser(), part); 96 part.saveChanges(); 97 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 98 part.writeTo(bos); 99 input.setDataBuffer(ByteArrayTool.crlfFix(bos.toByteArray())); 100 } catch (Exception e) { 101 log.error("An error occured", e); 102 } 103 return true; 104 } 105 106 private boolean replaceSnippets(String user, MimePart part) throws MessagingException , IOException { 107 if (part.isMimeType("text/plain")) { 108 addToText(user, part); 109 return true; 110 } else if (part.isMimeType("text/html")) { 111 addToHTML(user, part); 112 return true; 113 } else if (part.isMimeType("multipart/mixed")) { 114 MimeMultipart multipart = (MimeMultipart ) part.getContent(); 115 MimeBodyPart firstPart = (MimeBodyPart ) multipart.getBodyPart(0); 116 boolean isFooterAttached = replaceSnippets(user, firstPart); 117 part.setContent(multipart); 119 return isFooterAttached; 120 } else if (part.isMimeType("multipart/alternative")) { 121 MimeMultipart multipart = (MimeMultipart ) part.getContent(); 122 int count = multipart.getCount(); 123 boolean isFooterAttached = false; 124 for (int index = 0; index < count; index++) { 125 MimeBodyPart mimeBodyPart = (MimeBodyPart ) multipart.getBodyPart(index); 126 isFooterAttached |= replaceSnippets(user, mimeBodyPart); 127 } 128 part.setContent(multipart); 130 return isFooterAttached; 131 } else { 132 log.error("Can't attach signature to mail "); 134 return false; 135 } 136 } 137 138 public String getPluginName() { 139 return "Replace Snippet Filter"; 140 } 141 142 public void shutdownPlugin() { 143 } 144 145 152 protected void addToHTML(String user, MimePart part) throws MessagingException , IOException { 153 String content = part.getContent().toString(); 154 part.setContent(replaceSnippets(user, content, "text/html"), part.getContentType()); 155 } 156 157 protected void addToText(String user, MimePart part) throws MessagingException , IOException { 158 String content = part.getContent().toString(); 159 part.setText(replaceSnippets(user, content, "text/plain"),encoding); 160 } 161 162 protected String replaceSnippets(String user, String content, String contentType) { 163 Matcher m = pattern.matcher(content); 164 Set <String > snippets = new HashSet <String >(); 165 while (m.find()) { 166 String match = m.group(1); 167 if (hasSnippet(user, match, contentType)) { 168 snippets.add(match); 169 } 170 } 171 172 Iterator <String > it = snippets.iterator(); 173 String newContent = content; 174 while (it.hasNext()) { 175 String match = it.next(); 176 String pattern = prefix + match + suffix; 177 String replace = getSnippet(user, match, contentType); 178 if (replace != null) { 179 newContent = Pattern.compile(pattern, Pattern.MULTILINE).matcher(newContent).replaceAll(replace); 180 } else { 181 log.error("Could not replace content for snippet" + match + " in " + contentType + " for user " + user); 182 return content; 183 } 184 } 185 return newContent; 186 } 187 188 public boolean hasSnippet(String user, String pattern, String contentType) { 189 190 if (pattern.contains("../")) 191 return false; 192 193 String snippetPath = getSnippetPath(user, pattern, contentType); 194 boolean result = new File (snippetPath).exists(); 195 if (!result) { 196 log.debug("Signature " + snippetPath + " not found"); 197 } 198 return result; 199 } 200 201 public String getSnippet(String user, String pattern, String contentType) { 202 StringBuffer content = new StringBuffer (); 203 try { 204 BufferedReader in = new BufferedReader (new FileReader (getSnippetPath(user, pattern, contentType))); 205 String str; 206 while ((str = in.readLine()) != null) { 207 content.append(str); 208 content.append(CR_LF); 209 } 210 in.close(); 211 } catch (IOException e) { 212 log.error("Error getting snippet content", e); 213 return null; 214 } 215 return content.toString(); 216 } 217 218 private String getSnippetPath(String user, String pattern, String contentType) { 219 String snippet = path + File.separator + user + File.separator + pattern; 220 if (contentType.equals("text/html")) 221 snippet = snippet + ".html"; 222 else 223 snippet = snippet + ".txt"; 224 return snippet; 225 } 226 227 public void setEncoding(String encoding) { 228 this.encoding = encoding; 229 } 230 231 } 232 | Popular Tags |