1 package org.columba.mail.gui.message.filter; 19 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.util.ArrayList ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 26 import javax.swing.SwingUtilities ; 27 28 import org.columba.core.io.StreamUtils; 29 import org.columba.core.logging.Logging; 30 import org.columba.mail.command.IMailFolderCommandReference; 31 import org.columba.mail.command.MailFolderCommandReference; 32 import org.columba.mail.config.AccountItem; 33 import org.columba.mail.config.MailConfig; 34 import org.columba.mail.config.SecurityItem; 35 import org.columba.mail.folder.IMailbox; 36 import org.columba.mail.gui.frame.MailFrameMediator; 37 import org.columba.mail.gui.message.IMessageController; 38 import org.columba.mail.gui.message.viewer.SecurityStatusViewer; 39 import org.columba.mail.message.ColumbaMessage; 40 import org.columba.mail.pgp.JSCFController; 41 import org.columba.mail.pgp.PGPPassChecker; 42 import org.columba.mail.util.MailResourceLoader; 43 import org.columba.ristretto.io.CharSequenceSource; 44 import org.columba.ristretto.io.Source; 45 import org.columba.ristretto.message.MimeHeader; 46 import org.columba.ristretto.message.MimePart; 47 import org.columba.ristretto.message.MimeTree; 48 import org.columba.ristretto.message.MimeType; 49 import org.columba.ristretto.parser.BodyParser; 50 import org.columba.ristretto.parser.HeaderParser; 51 import org.columba.ristretto.parser.ParserException; 52 import org.waffel.jscf.JSCFConnection; 53 import org.waffel.jscf.JSCFException; 54 import org.waffel.jscf.JSCFResultSet; 55 import org.waffel.jscf.JSCFStatement; 56 57 69 public class PGPMessageFilter extends AbstractFilter { 70 71 private static final java.util.logging.Logger LOG = java.util.logging.Logger 72 .getLogger("org.columba.mail.gui.message.filter"); 73 74 private MimeTree mimePartTree; 75 76 private int pgpMode = SecurityStatusViewer.NOOP; 77 78 private String pgpMessage = ""; 79 80 private ColumbaMessage message; 81 82 private List listeners; 83 84 public PGPMessageFilter(MailFrameMediator mediator, 85 IMessageController messageController) { 86 super(mediator, messageController); 87 88 listeners = new ArrayList (); 89 } 90 91 public void addSecurityStatusListener(SecurityStatusListener l) { 92 listeners.add(l); 93 } 94 95 public void fireSecurityStatusEvent(SecurityStatusEvent ev) { 96 final SecurityStatusEvent event = ev; 97 98 Iterator it = listeners.iterator(); 99 while (it.hasNext()) { 100 final SecurityStatusListener l = (SecurityStatusListener) it.next(); 101 Runnable doWorkRunnable = new Runnable () { 102 public void run() { 103 l.statusUpdate(event); 104 105 } 106 }; 107 SwingUtilities.invokeLater(doWorkRunnable); 108 109 } 110 } 111 112 116 public IMailFolderCommandReference filter(IMailbox folder, Object uid) 117 throws Exception { 118 119 mimePartTree = folder.getMimePartTree(uid); 120 121 if (mimePartTree == null) 124 return null; 125 126 MimeType firstPartMimeType = mimePartTree.getRootMimeNode().getHeader() 136 .getMimeType(); 137 138 AccountItem defAccount = MailConfig.getInstance().getAccountList() 139 .getDefaultAccount(); 140 141 boolean pgpActive = false; 142 143 if (defAccount != null) { 144 SecurityItem pgpItem = defAccount.getPGPItem(); 145 LOG.fine("pgp activated: " + pgpItem.get("enabled")); 146 pgpActive = new Boolean ((pgpItem.get("enabled"))).booleanValue(); 147 } 148 149 IMailFolderCommandReference result = null; 150 LOG.fine("pgp is true"); 151 if (firstPartMimeType.getSubtype().equals("signed")) { 152 result = verify(folder, uid, pgpActive); 153 154 } else if (firstPartMimeType.getSubtype().equals("encrypted")) { 155 LOG.fine("Mimepart type encrypted found"); 156 result = decrypt(folder, uid, pgpActive); 157 158 } else { 159 pgpMode = SecurityStatusViewer.NOOP; 160 } 161 162 fireSecurityStatusEvent(new SecurityStatusEvent(this, pgpMessage, 164 pgpMode)); 165 166 return result; 167 } 168 169 179 private IMailFolderCommandReference decrypt(IMailbox folder, Object uid, 180 boolean pgpActive) throws Exception , IOException { 181 InputStream decryptedStream = null; 182 LOG.fine("start decrypting"); 183 if (!pgpActive) { 184 pgpMessage = ""; 185 pgpMode = SecurityStatusViewer.NO_KEY; 186 } else { 187 188 189 MimePart encryptedMultipart = mimePartTree.getRootMimeNode(); 190 191 InputStream encryptedPart = folder.getMimePartBodyStream(uid, 193 encryptedMultipart.getChild(1).getAddress()); 194 195 try { 196 JSCFController controller = JSCFController.getInstance(); 197 JSCFConnection con = controller.getConnection(); 198 LOG.fine("new JSCConnection"); 199 JSCFStatement stmt = con.createStatement(); 200 LOG.fine("new Statement"); 201 PGPPassChecker passCheck = PGPPassChecker.getInstance(); 202 boolean check = passCheck.checkPassphrase(con); 203 LOG.fine("after pass check, check is " + check); 204 if (!check) { 205 pgpMode = SecurityStatusViewer.DECRYPTION_FAILURE; 206 pgpMessage = "wrong passphrase"; 208 return null; 209 } 210 LOG.fine("encrypted is != null?: " + (encryptedPart != null)); 211 JSCFResultSet res = stmt.executeDecrypt(encryptedPart); 212 LOG.fine("after calling decrypting"); 213 if (res.isError()) { 214 LOG.fine("the result set contains errors "); 215 pgpMode = SecurityStatusViewer.DECRYPTION_FAILURE; 216 pgpMessage = StreamUtils.readCharacterStream( 217 res.getErrorStream()).toString(); 218 LOG.fine("error message: " + pgpMessage); 219 decryptedStream = res.getResultStream(); 220 } else { 222 decryptedStream = res.getResultStream(); 223 pgpMode = SecurityStatusViewer.DECRYPTION_SUCCESS; 224 } 225 } catch (JSCFException e) { 226 e.printStackTrace(); 227 LOG.severe(e.getMessage()); 228 pgpMode = SecurityStatusViewer.DECRYPTION_FAILURE; 229 pgpMessage = e.getMessage(); 230 231 decryptedStream = encryptedPart; 233 } 234 } 235 try { 236 LOG.fine("decrypted Stream is: " + decryptedStream); 237 CharSequence decryptedBodyPart = ""; 238 if (pgpActive) { 240 decryptedBodyPart = StreamUtils 243 .readCharacterStream(decryptedStream); 244 if (decryptedBodyPart.length() == 0) { 246 LOG 247 .fine("decrypted body part has a 0 length ... fixing it"); 248 decryptedBodyPart = new StringBuffer ( 249 "Content-Type: text/plain; charset=\"ISO-8859-15\"\n\n"); 250 } 251 } 252 else { 254 decryptedBodyPart = new StringBuffer ( 255 "Content-Type: text/plain; charset=\"ISO-8859-15\"\n\n" 256 + MailResourceLoader.getString("menu", 257 "mainframe", 258 "security_decrypt_encrypted") + "\n"); 259 } 260 LOG.fine("the decrypted Body part: " + decryptedBodyPart); 261 message = new ColumbaMessage(folder.getAllHeaderFields(uid)); 263 264 Source decryptedSource = new CharSequenceSource(decryptedBodyPart); 265 MimeHeader mimeHeader = new MimeHeader(HeaderParser 266 .parse(decryptedSource)); 267 mimePartTree = new MimeTree(BodyParser.parseMimePart(mimeHeader, 268 decryptedSource)); 269 message.setMimePartTree(mimePartTree); 270 271 InputStream messageSourceStream = folder 272 .getMessageSourceStream(uid); 273 message.setSource(new CharSequenceSource(StreamUtils 274 .readCharacterStream(messageSourceStream))); 275 messageSourceStream.close(); 276 277 return filter(folder, uid, message); 279 } catch (ParserException e) { 281 e.printStackTrace(); 282 283 } catch (IOException e) { 284 e.printStackTrace(); 285 286 } 287 288 292 return null; 293 } 294 295 305 private MailFolderCommandReference verify(IMailbox folder, Object uid, 306 boolean pgpActive) throws Exception , IOException { 307 if (!pgpActive) { 308 pgpMessage = ""; 309 pgpMode = SecurityStatusViewer.NO_KEY; 310 return null; 311 } 312 MimePart signedMultipart = mimePartTree.getRootMimeNode(); 313 314 InputStream signedPart = folder.getMimePartSourceStream(uid, 316 signedMultipart.getChild(0).getAddress()); 317 318 InputStream signature = folder.getMimePartBodyStream(uid, 320 signedMultipart.getChild(1).getAddress()); 321 322 try { 323 JSCFController controller = JSCFController.getInstance(); 324 JSCFConnection con = controller.getConnection(); 325 JSCFStatement stmt = con.createStatement(); 326 String micalg = signedMultipart.getHeader().getContentParameter( 327 "micalg").substring(4); 328 JSCFResultSet res = stmt.executeVerify(signedPart, signature, 329 micalg); 330 if (res.isError()) { 331 pgpMode = SecurityStatusViewer.VERIFICATION_FAILURE; 332 pgpMessage = StreamUtils.readCharacterStream( 333 res.getErrorStream()).toString(); 334 } else { 335 pgpMode = SecurityStatusViewer.VERIFICATION_SUCCESS; 336 pgpMessage = StreamUtils.readCharacterStream( 337 res.getResultStream()).toString(); 338 } 339 340 } catch (JSCFException e) { 341 342 if (Logging.DEBUG) 343 e.printStackTrace(); 344 345 pgpMode = SecurityStatusViewer.VERIFICATION_FAILURE; 346 pgpMessage = e.getMessage(); 347 350 pgpMode = SecurityStatusViewer.VERIFICATION_FAILURE; 351 } 352 353 signedPart.close(); 354 signature.close(); 355 356 return null; 357 } 358 359 } | Popular Tags |