1 package SnowMailClient.model.folders; 2 3 import snow.utils.storage.*; 4 import snow.utils.gui.*; 5 import SnowMailClient.model.*; 6 import SnowMailClient.Language.Language; 7 import SnowMailClient.crypto.*; 8 import SnowMailClient.SnowMailClientApp; 9 import SnowMailClient.SpamFilter.*; 10 11 import java.awt.*; 12 import java.awt.event.*; 13 import javax.swing.*; 14 import javax.swing.tree.*; 15 import java.io.*; 16 import java.util.*; 17 import java.security.*; 18 import java.security.spec.*; 19 import javax.crypto.spec.*; 20 import javax.crypto.*; 21 22 27 public final class FolderTreeNode extends DefaultMutableTreeNode { 29 boolean systemFolder = false; 30 31 private MailFolder mailFolder; 33 34 private static final String folder_File_Name = "content.mailFolder"; 35 36 37 public FolderTreeNode( String name, DefaultMutableTreeNode parent ) throws Exception 38 { 39 super(name); 40 if(parent!=null) 41 { 42 parent.add(this); 43 } 44 45 File folderFile = new File( getFolderFullPath()); 47 if(folderFile.exists()) 48 { 49 if(!folderFile.isDirectory()) 50 { 51 throw new Exception (Language.translate("Folder % is not a directory", folderFile.getAbsolutePath())); 52 } 53 } 54 else 55 { 56 if(!folderFile.mkdirs()) 57 { 58 throw new Exception (Language.translate("Cannot create folder %",folderFile.getAbsolutePath())); 59 } 60 } 61 62 parseChilds(); 63 64 } 65 66 70 public Vector<FolderTreeNode> getFirstlevelChilds() 71 { 72 Vector<FolderTreeNode> flc = new Vector<FolderTreeNode>(); 73 for(int i=0; i<getChildCount(); i++) 74 { 75 flc.addElement(getFolderChildAt(i)); 76 } 77 return flc; 78 } 79 80 private void parseChilds() throws Exception 81 { 82 File thisFolder = new File(getFolderFullPath()); 83 File[] dirs = thisFolder.listFiles( new FileFilter() 84 { 85 public boolean accept(File pathname) 86 { 87 return pathname.isDirectory(); 88 } 89 } ); 90 91 for(File ci: dirs) 92 { 93 new FolderTreeNode(ci.getName(), this); 94 } 95 } 96 97 public boolean hasChild(String name) 98 { 99 return new File(getFolderFullPath(), name).exists(); 100 } 101 102 104 public FolderTreeNode getChild(String name) 105 { 106 File folderToSearch = new File(this.getFolderFile(), name); 107 109 for(FolderTreeNode childNode: getFirstlevelChilds()) 110 { 111 if(childNode.getFolderFile().equals(folderToSearch)) return childNode; 113 } 114 return null; 115 } 116 117 public FolderTreeNode getFolderChildAt(int i) 118 { 119 return (FolderTreeNode) this.getChildAt(i); 120 } 121 122 public String getFolderName() 123 { 124 return (String ) this.getUserObject(); 125 } 126 127 public FolderTreeNode getParentNode() 128 { 129 return (FolderTreeNode) this.getParent(); 130 } 131 132 public String getFolderFullPath() 133 { 134 FolderTreeNode parent = (FolderTreeNode) getParent(); 135 if(parent!=null) 136 { 137 return parent.getFolderFullPath() 138 + System.getProperty("file.separator","\\") 139 + this.getFolderName(); 140 } 141 return this.getFolderName(); 142 } 143 144 145 147 public void searchMailMessagesContaining(String search, final SearchResults result, boolean recurse) throws Exception 148 { 149 MailFolder folder = this.getMailFolder(); 152 for(int i=0; i<folder.getRowCount(); i++) 153 { 154 final MailMessage mess = folder.getMessageAt(i); 155 if(folder.hitForTextSearch(i, search, null)) { 157 EventQueue.invokeLater(new Runnable () { public void run() { 160 result.addHit(new SearchHit(mess, FolderTreeNode.this)); 161 SnowMailClientApp.getInstance().getSearchPanel().updateTree(); 162 }}); 163 } 164 176 } 177 178 if(recurse) 181 { 182 for(FolderTreeNode childNode: getFirstlevelChilds()) 183 { 184 childNode.searchMailMessagesContaining(search, result, recurse); 185 } 186 } 187 } 188 189 public int getTotalNumberOfFoldersIncludingThis() 190 { 191 int n = 1; for(FolderTreeNode childNode: getFirstlevelChilds()) 193 { 194 n += childNode.getTotalNumberOfFoldersIncludingThis(); 195 } 196 return n; 197 } 198 199 public void analyseAllMailsToTrainSPAMFilter(WordStatistic stat, ProgressModalDialog progress, boolean recurse) throws Exception 200 { 201 MailFolder folder = this.getMailFolder(); 203 204 progress.setProgressComment( ""+folder.getFolderName() 205 +", "+Language.translate("Total words count")+"="+stat.getNumberOfWords()); 206 progress.incrementProgress(1); 207 208 for(MailMessage mess: folder.getAllMessages()) 209 { 210 if(progress.wasCancelled()) 211 { 212 throw new Exception (Language.translate("Training cancelled")); 213 } 214 stat.addMessageToStat( mess ); 215 } 216 217 if(recurse) 220 { 221 for(FolderTreeNode childNode: getFirstlevelChilds()) 222 { 223 childNode.analyseAllMailsToTrainSPAMFilter(stat, progress, recurse); 224 } 225 } 226 } 227 228 public void calculateSPAMNoteForEachMailRecurse(WordStatistic stat, ProgressModalDialog progress, boolean recurse) throws Exception 229 { 230 MailFolder folder = this.getMailFolder(); 231 233 progress.setProgressComment( ""+folder.getFolderName()); 234 progress.incrementProgress(1); 235 236 for(MailMessage mess: folder.getAllMessages()) 237 { 238 if(progress.wasCancelled()) 239 { 240 throw new Exception (Language.translate("SPAM Analysis cancelled")); 241 } 242 243 245 SpamResult sr = stat.calculateSpamProbability( mess ); 246 double p = sr.getProbability(); 247 mess.setSPAMProbability(p); 248 249 boolean isSpam = stat.isSpam(p); 250 if(isSpam && mess.getIsHAM()) 251 { 252 stat.result_false_positives++; 253 System.out.println("False positive in "+this.getFolderFullPath()); 254 stat.addFalsePositive(this.getFolderName()+ " "+mess.getFromAddress().toString()); 255 } 256 if(isSpam && mess.getIsSPAM()) stat.result_detected_spams++; 257 258 260 Header header = mess.getHeader(); 261 p = stat.calculateSpamProbability(header).getProbability(); 262 263 isSpam = stat.isSpam(p); 264 if(isSpam && mess.getIsHAM()) 265 { 266 stat.result_false_positives_header++; 267 stat.addFalsePositive(this.getFolderName()+ " "+mess.getFromAddress().toString()+" (Header detection only)"); 268 } 269 if(isSpam && mess.getIsSPAM()) stat.result_detected_spams_header++; 270 271 } 272 273 if(recurse) 276 { 277 for(FolderTreeNode childNode: getFirstlevelChilds()) 278 { 279 childNode.calculateSPAMNoteForEachMailRecurse(stat, progress, recurse); 280 } 281 } 282 } 283 284 286 public File getFolderFile() { return new File( getFolderFullPath() ); } 287 288 public void removeThisFolder() throws Exception 289 { 290 if(this.getParent()==null) throw new Exception ("Cannot remove root folder"); 291 if(systemFolder) throw new Exception ("System folder "+getFolderName()+" cannot be removed"); 292 File thisFolder = getFolderFile(); 293 File[] files = thisFolder.listFiles(); 294 if(files.length>0) 295 { 296 File mailFolderFile = new File(getFolderFile(), folder_File_Name); 298 if(mailFolderFile.exists()) 299 { 300 if(files.length>1) 301 { 302 throw new Exception ("Folder "+thisFolder+" is not empty, it has extra files."); 303 } 304 else 305 { 306 MailFolder mf = this.getMailFolder(); 307 if(mf.getRowCount()>0) 308 { 309 throw new Exception ("Folder "+getFolderName()+" is not empty."); 310 } 311 else 312 { 313 mailFolderFile.delete(); 315 } 316 } 317 } 318 else 319 { 320 throw new Exception ("Folder "+thisFolder+" is not empty, it has extra files."); 321 } 322 } 323 324 if(!thisFolder.delete()) 325 { 326 throw new Exception ("Folder "+getFolderName()+" was not deleted successfully"); 327 } 328 329 removeAllChildren(); 330 removeFromParent(); 331 332 } 333 334 336 public void rename(String newName) throws Exception 337 { 338 if(this.getParent()==null) throw new Exception (Language.translate("Cannot rename root folder")); 339 if(systemFolder) 340 { 341 throw new Exception (Language.translate("System folder % cannot be renamed", getFolderName())); 342 } 343 344 File thisFolderFile = getFolderFile(); 346 File parentFile = thisFolderFile.getParentFile(); 347 348 File newFolderParentFile = new File(parentFile, newName); 349 File newFolderContentFile = new File(newFolderParentFile, folder_File_Name); 350 351 if(newFolderContentFile.exists()) 352 { 353 throw new Exception (Language.translate("Cannot rename folder, the destination folder already exists.")); 354 } 355 356 if(!newFolderParentFile.exists()) 357 { 358 if(!newFolderParentFile.mkdirs()) 359 { 360 throw new Exception (Language.translate("Cannot create folder directory %",newFolderParentFile.getAbsolutePath())); 361 } 362 } 363 364 MailFolder mf = getMailFolder(); 366 mf.setContentHasChanged(false); this.setUserObject(newName); 369 saveMailFolder(false); 372 File oldMailFolderFile = new File(thisFolderFile, "content.mailFolder"); 374 if(oldMailFolderFile.exists() && !oldMailFolderFile.delete()) 375 { 376 throw new Exception ("Cannot delete the old folder "+oldMailFolderFile.getAbsolutePath()); 377 } 378 } 379 380 public void setIsSystemFolder(boolean is) 381 { 382 systemFolder = is; 383 } 384 385 public boolean isSystemFolder() { return systemFolder; } 386 387 390 public boolean isMailFolderOpened() 391 { 392 return (mailFolder!=null); 393 } 394 395 401 public MailFolder getMailFolder() throws Exception 402 { 403 if(mailFolder!=null) return mailFolder; 404 405 mailFolder = new MailFolder(this); 406 407 File mailFolderFile = new File(getFolderFile(), "content.mailFolder"); 409 if(!mailFolderFile.exists()) 410 { 411 415 FileCipherManager.getInstance().encipherVectorWithHeadToFile( 418 new Vector<Object >(), new Vector<Object >(), 419 mailFolder.getVectorRepresentation(), 420 mailFolderFile, 421 SecretKeyManager.getInstance().getActualKey()); 422 } 423 424 try 426 { 427 try 428 { 429 Vector<Object > v = FileCipherManager.getInstance().decipherVectorFromFile_ASK_KEY_IF_NEEDED( 430 mailFolderFile, 431 SnowMailClientApp.getInstance(), 432 Language.translate("Folder Password"), 433 Language.translate("Enter the passphrase to decipher the folder %",this.getFolderName()) 434 ); 435 mailFolder.createFromVectorRepresentation( v ); 436 } 437 catch(EOFException eofex) 438 { 439 throw eofex; 442 } 443 catch(Exception ee) 444 { 445 System.out.println("Error: cannot read "+mailFolderFile+"\n error="+ee.getMessage()); 446 System.out.println("Trying old version 0"); 447 try 449 { 450 Vector<Object > v = FileUtils.loadVectorFromFile(mailFolderFile); 451 mailFolder.createFromVectorRepresentation( v ); 452 } 453 catch(Exception eee) 454 { 455 ee.printStackTrace(); 457 throw eee; 458 } 459 } 460 } 461 catch(OutOfMemoryError e) 462 { 463 throw new Exception ("Canot read mail folder from file "+mailFolderFile.getAbsolutePath() 464 +"\nBecause of an out of memory error. Restart Snowmail with more memory (-Xmx512m)."); 465 } 466 catch(Exception e) 467 { 468 throw new Exception ("Canot read mail folder from file "+mailFolderFile.getAbsolutePath() 469 +"\nException message="+e.getMessage()); 470 } 471 catch(Error e) 472 { 473 throw new Exception ("Canot read mail folder from file "+mailFolderFile.getAbsolutePath() 474 +"\nError message="+e.getMessage()); 475 } 476 477 return mailFolder; 478 } 479 480 483 public void saveMailFolder(boolean close) throws Exception 484 { 485 if(mailFolder==null) return; 486 487 489 if(mailFolder.hasContentChanged()) 490 { 491 File mailFolderFile = new File(getFolderFile(), "content.mailFolder"); 492 FileCipherManager.getInstance().encipherVectorWithHeadToFile( 494 new Vector<Object >(), 495 new Vector<Object >(), 496 mailFolder.getVectorRepresentation(), 497 mailFolderFile, SecretKeyManager.getInstance().getActualKey()); 498 499 mailFolder.setContentWasStored(); 500 } 501 502 if(close) 503 { 504 505 mailFolder.notifyMailFolderListener_of_FolderClosed(); 506 mailFolder = null; 507 } 509 } 510 511 512 } | Popular Tags |