From dbkr at freenetproject.org Thu Apr 10 20:32:14 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Thu, 10 Apr 2008 20:32:14 +0000 (UTC) Subject: [Freemail] r19153 - trunk/apps/Freemail/src/freemail Message-ID: <20080410203214.784CC479A91@freenetproject.org> Author: dbkr Date: 2008-04-10 20:32:14 +0000 (Thu, 10 Apr 2008) New Revision: 19153 Modified: trunk/apps/Freemail/src/freemail/FreemailCli.java Log: Move the comment to the block it actually relates to Modified: trunk/apps/Freemail/src/freemail/FreemailCli.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-10 18:43:01 UTC (rev 19152) +++ trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-10 20:32:14 UTC (rev 19153) @@ -150,7 +150,6 @@ getGlobalDataDir().mkdir(); } - // start a SingleAccountWatcher for each account cfg.register("datadir", new Freemail(), Freemail.DATADIR); if (!getDataDir().exists()) { System.out.println("Starting Freemail for the first time."); @@ -168,6 +167,7 @@ } } + // start a SingleAccountWatcher for each account File[] files = getDataDir().listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].getName().equals(".") || files[i].getName().equals("..")) From dbkr at freenetproject.org Thu Apr 10 20:50:00 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Thu, 10 Apr 2008 20:50:00 +0000 (UTC) Subject: [Freemail] r19154 - trunk/apps/Freemail/src/freemail Message-ID: <20080410205000.EDBCD479CEE@freenetproject.org> Author: dbkr Date: 2008-04-10 20:50:00 +0000 (Thu, 10 Apr 2008) New Revision: 19154 Modified: trunk/apps/Freemail/src/freemail/RTSLog.java Log: Detect time travel Modified: trunk/apps/Freemail/src/freemail/RTSLog.java =================================================================== --- trunk/apps/Freemail/src/freemail/RTSLog.java 2008-04-10 20:32:14 UTC (rev 19153) +++ trunk/apps/Freemail/src/freemail/RTSLog.java 2008-04-10 20:50:00 UTC (rev 19154) @@ -28,6 +28,7 @@ import java.util.Enumeration; import java.io.File; +import freemail.utils.Logger; import freemail.utils.PropsFile; import freemail.utils.DateStringFactory; @@ -66,6 +67,12 @@ this.logfile.put("birth", birth_s); } else { birth = DateStringFactory.DateFromKeyString(birth_s); + if (birth.after(new Date())) { + Logger.error(this, "RTS log was created in the future! Resetting to now"); + birth = new Date(); + birth_s = DateStringFactory.getOffsetKeyString(0); + this.logfile.put("birth", birth_s); + } } if (day.before(birth)) return true; From dbkr at freenetproject.org Thu Apr 10 20:51:11 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Thu, 10 Apr 2008 20:51:11 +0000 (UTC) Subject: [Freemail] r19155 - trunk/apps/Freemail/src/freemail Message-ID: <20080410205111.B6EB3479D1C@freenetproject.org> Author: dbkr Date: 2008-04-10 20:51:11 +0000 (Thu, 10 Apr 2008) New Revision: 19155 Modified: trunk/apps/Freemail/src/freemail/MailHeaderFilter.java Log: Indeed, accesses to a simpledateformat should be synchronised, apparently Modified: trunk/apps/Freemail/src/freemail/MailHeaderFilter.java =================================================================== --- trunk/apps/Freemail/src/freemail/MailHeaderFilter.java 2008-04-10 20:50:00 UTC (rev 19154) +++ trunk/apps/Freemail/src/freemail/MailHeaderFilter.java 2008-04-10 20:51:11 UTC (rev 19155) @@ -44,9 +44,6 @@ private static final SimpleDateFormat sdf; private static final TimeZone gmt; - // TODO: according to javadoc, SimpleDateFormat objects are not synchronized, - // should this be taken into account? - static { sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); gmt = TimeZone.getTimeZone("GMT"); @@ -116,7 +113,9 @@ Date d = null; try { - d = sdf.parse(val); + synchronized(sdf) { + d = sdf.parse(val); + } } catch (ParseException pe) { // ...the compiler whinges unless we catch this exception... Logger.normal(this,"Warning: couldn't parse date: "+val+" (caught exception)"); @@ -129,7 +128,11 @@ Logger.normal(this,"Warning: couldn't parse date: "+val+" (got null)"); return null; } - return sdf.format(d); + String strDate; + synchronized(sdf) { + strDate = sdf.format(d); + } + return strDate; } else if (name.equalsIgnoreCase("User-Agent")) { // might as well hide this return null; From dbkr at freenetproject.org Thu Apr 10 20:51:51 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Thu, 10 Apr 2008 20:51:51 +0000 (UTC) Subject: [Freemail] r19156 - trunk/apps/Freemail/src/freemail Message-ID: <20080410205151.3F3AB479D24@freenetproject.org> Author: dbkr Date: 2008-04-10 20:51:51 +0000 (Thu, 10 Apr 2008) New Revision: 19156 Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java Log: All the logging Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-10 20:51:11 UTC (rev 19155) +++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-10 20:51:51 UTC (rev 19156) @@ -292,6 +292,8 @@ * @return true for success */ private boolean init() throws OutboundContactFatalException, ConnectionTerminatedException { + Logger.normal(this, "Initialising Outbound Contact "+address.toString()); + // try to fetch get all necessary info. will fetch mailsite / generate new keys if necessary String initialslot = this.getInitialSlot(); SSKKeyPair commssk = this.getCommKeyPair(); @@ -337,8 +339,9 @@ byte[] sig = null; try { sig = sigcipher.processBlock(hash, 0, hash.length); - } catch (InvalidCipherTextException e) { - e.printStackTrace(); + } catch (InvalidCipherTextException icte) { + Logger.error(this, "Failed to RSA encrypt hash: "+icte.getMessage()); + icte.printStackTrace(); return false; } @@ -371,8 +374,9 @@ byte[] encrypted_aes_params = null; try { encrypted_aes_params = enccipher.processBlock(aes_iv_and_key, 0, aes_iv_and_key.length); - } catch (InvalidCipherTextException e) { - e.printStackTrace(); + } catch (InvalidCipherTextException icte) { + Logger.error(this, "Failed to perform asymmertic encryption on RTS symmetric key: "+icte.getMessage()); + icte.printStackTrace(); return false; } @@ -389,6 +393,7 @@ try { aescipher.doFinal(encmsg, offset); } catch (InvalidCipherTextException icte) { + Logger.error(this, "Failed to perform symmertic encryption on RTS data: "+icte.getMessage()); icte.printStackTrace(); return false; } @@ -407,6 +412,9 @@ // and since that's been successfully inserted to that key, we can // throw away the symmetric key this.contactfile.remove("aesparams"); + + Logger.normal(this, "Succesfully initialised Outbound Contact"); + return true; } From dbkr at freenetproject.org Thu Apr 10 22:11:02 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Thu, 10 Apr 2008 22:11:02 +0000 (UTC) Subject: [Freemail] r19157 - trunk/apps/Freemail/src/freemail Message-ID: <20080410221102.2368B479839@freenetproject.org> Author: dbkr Date: 2008-04-10 22:11:01 +0000 (Thu, 10 Apr 2008) New Revision: 19157 Modified: trunk/apps/Freemail/src/freemail/Freemail.java trunk/apps/Freemail/src/freemail/FreemailCli.java trunk/apps/Freemail/src/freemail/FreemailPlugin.java Log: Sort out horrendous code duplication in bootstrap classes. Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-10 20:51:51 UTC (rev 19156) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-10 22:11:01 UTC (rev 19157) @@ -22,25 +22,77 @@ package freemail; import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; + import freemail.fcp.FCPConnection; +import freemail.fcp.FCPContext; +import freemail.imap.IMAPListener; +import freemail.smtp.SMTPListener; +import freemail.utils.Logger; import freemail.config.ConfigClient; +import freemail.config.Configurator; -public class Freemail implements ConfigClient { +public abstract class Freemail implements ConfigClient { public static final int VER_MAJOR = 0; public static final int VER_MINOR = 1; public static final int BUILD_NO = 9; public static final String VERSION_TAG = "Pet Shop"; - protected static final String TEMPDIRNAME = "temp"; + private static final String TEMPDIRNAME = "temp"; protected static final String DATADIR = "data"; - protected static final String GLOBALDATADIR = "globaldata"; - protected static final String ACKDIR = "delayedacks"; + private static final String GLOBALDATADIR = "globaldata"; + private static final String ACKDIR = "delayedacks"; protected static final String CFGFILE = "globalconfig"; private static File datadir; private static File globaldatadir; private static File tempdir; protected static FCPConnection fcpconn = null; + private Thread fcpThread; + private ArrayList /* of Thread */ singleAccountWatcherThreadList = new ArrayList(); + private Thread messageSenderThread; + private Thread smtpThread; + private Thread ackInserterThread; + private Thread imapThread; + + private ArrayList singleAccountWatcherList = new ArrayList(); + private MessageSender sender; + private SMTPListener smtpl; + private AckProcrastinator ackinserter; + private IMAPListener imapl; + + protected final Configurator configurator; + + protected Freemail(String cfgfile) { + configurator = new Configurator(new File(cfgfile)); + + configurator.register("loglevel", new Logger(), "normal|error"); + + configurator.register("datadir", this, Freemail.DATADIR); + if (!getDataDir().exists()) { + if (!getDataDir().mkdir()) { + Logger.error(this,"Freemail: Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + return; + } + } + + configurator.register("globaldatadir", this, GLOBALDATADIR); + if (!getGlobalDataDir().exists()) { + if (!getGlobalDataDir().mkdir()) { + Logger.error(this,"Freemail: Couldn't create global data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + } + } + + configurator.register("tempdir", this, Freemail.TEMPDIRNAME); + if (!getTempDir().exists()) { + if (!Freemail.getTempDir().mkdir()) { + Logger.error(this,"Freemail: Couldn't create temporary directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + return; + } + } + } + public static File getTempDir() { return Freemail.tempdir; } @@ -66,4 +118,122 @@ Freemail.globaldatadir = new File(val); } } + + protected void startFcp(boolean daemon) { + FCPContext fcpctx = new FCPContext(); + configurator.register("fcp_host", fcpctx, "localhost"); + configurator.register("fcp_port", fcpctx, "9481"); + + Freemail.fcpconn = new FCPConnection(fcpctx); + fcpThread = new Thread(fcpconn, "Freemail FCP Connection"); + fcpThread.setDaemon(true); + fcpThread.start(); + } + + protected void startServers(boolean daemon) { + // start the SMTP Listener + smtpl = new SMTPListener(sender, configurator); + smtpThread = new Thread(smtpl, "Freemail SMTP Listener"); + smtpThread.setDaemon(daemon); + smtpThread.start(); + + // start the IMAP listener + imapl = new IMAPListener(configurator); + imapThread = new Thread(imapl, "Freemail IMAP Listener"); + imapThread.setDaemon(daemon); + imapThread.start(); + } + + protected void startWorkers(boolean daemon) { + System.out.println("This is Freemail version "+VER_MAJOR+"."+VER_MINOR+" build #"+BUILD_NO+" ("+VERSION_TAG+")"); + System.out.println("Freemail is released under the terms of the GNU Lesser General Public License. Freemail is provided WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see the LICENSE file included with this distribution."); + System.out.println(""); + + // start a SingleAccountWatcher for each account + File[] files = getDataDir().listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].getName().equals(".") || files[i].getName().equals("..")) + continue; + if (!files[i].isDirectory()) continue; + + String invalid=AccountManager.validateUsername(files[i].getName()); + if(!invalid.equals("")) { + Logger.error(this,"Account name "+files[i].getName()+" contains invalid chars (\""+invalid+"\"), you may get problems accessing the account."); + } + + SingleAccountWatcher saw = new SingleAccountWatcher(files[i]); + singleAccountWatcherList.add(saw); + Thread t = new Thread(saw, "Freemail Account Watcher for "+files[i].getName()); + t.setDaemon(daemon); + t.start(); + singleAccountWatcherThreadList.add(t); + } + + // and a sender thread + sender = new MessageSender(getDataDir()); + messageSenderThread = new Thread(sender, "Freemail Message sender"); + messageSenderThread.setDaemon(daemon); + messageSenderThread.start(); + + // start the delayed ACK inserter + File ackdir = new File(getGlobalDataDir(), ACKDIR); + AckProcrastinator.setAckDir(ackdir); + ackinserter = new AckProcrastinator(); + ackInserterThread = new Thread(ackinserter, "Freemail Delayed ACK Inserter"); + ackInserterThread.setDaemon(daemon); + ackInserterThread.start(); + } + + public void terminate() { + Iterator it = singleAccountWatcherList.iterator(); + while(it.hasNext()) { + ((SingleAccountWatcher)it.next()).kill(); + it.remove(); + } + + sender.kill(); + ackinserter.kill(); + smtpl.kill(); + imapl.kill(); + // now kill the FCP thread - that's what all the other threads will be waiting on + fcpconn.kill(); + + // now clean up all the threads + boolean cleanedUp = false; + while (!cleanedUp) { + try { + it = singleAccountWatcherThreadList.iterator(); + while(it.hasNext()) { + ((Thread)it.next()).join(); + it.remove(); + } + + if (messageSenderThread != null) { + messageSenderThread.join(); + messageSenderThread = null; + } + if (ackInserterThread != null) { + ackInserterThread.join(); + ackInserterThread = null; + } + if (smtpThread != null) { + smtpThread.join(); + smtpl.joinClientThreads(); + smtpThread = null; + } + if (imapThread != null) { + imapThread.join(); + imapl.joinClientThreads(); + imapThread = null; + } + if (fcpThread != null) { + fcpThread.join(); + fcpThread = null; + } + } catch (InterruptedException ie) { + + } + cleanedUp = true; + } + } } Modified: trunk/apps/Freemail/src/freemail/FreemailCli.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-10 20:51:51 UTC (rev 19156) +++ trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-10 22:11:01 UTC (rev 19157) @@ -21,33 +21,22 @@ package freemail; -import java.io.File; import java.io.IOException; -//import java.util.ArrayList; -//import java.util.Iterator; import freemail.Freemail; -import freemail.fcp.FCPContext; -import freemail.fcp.FCPConnection; -import freemail.imap.IMAPListener; -import freemail.smtp.SMTPListener; -import freemail.utils.Logger; -import freemail.config.Configurator; -//import freemail.config.ConfigClient; -public abstract class FreemailCli extends Freemail { +public class FreemailCli extends Freemail { + public FreemailCli(String cfgfile) { + super(cfgfile); + } + public static void main(String[] args) { - String cfgfile = CFGFILE; - String action = ""; String account = null; String newpasswd = null; String alias = null; - - System.out.println("This is Freemail version "+VER_MAJOR+"."+VER_MINOR+" build #"+BUILD_NO+" ("+VERSION_TAG+")"); - System.out.println("Freemail is released under the terms of the GNU Lesser General Public License. Freemail is provided WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see the LICENSE file included with this distribution."); - System.out.println(""); - + String cfgfile = CFGFILE; + for (int i = 0; i < args.length; i++) { if (args[i].equals("--newaccount")) { action = args[i]; @@ -89,20 +78,9 @@ } } - Configurator cfg = new Configurator(new File(cfgfile)); + FreemailCli freemail = new FreemailCli(cfgfile); + freemail.startFcp(false); - cfg.register("loglevel", new Logger(), "normal|error"); - - FCPContext fcpctx = new FCPContext(); - - cfg.register("fcp_host", fcpctx, "localhost"); - cfg.register("fcp_port", fcpctx, "9481"); - - Freemail.fcpconn = new FCPConnection(fcpctx); - Thread fcpthread = new Thread(fcpconn); - fcpthread.setDaemon(true); - fcpthread.start(); - if (action.equals("--newaccount")) { try { AccountManager.Create(account); @@ -144,68 +122,8 @@ } return; } - - cfg.register("globaldatadir", new Freemail(), GLOBALDATADIR); - if (!getGlobalDataDir().exists()) { - getGlobalDataDir().mkdir(); - } - - cfg.register("datadir", new Freemail(), Freemail.DATADIR); - if (!getDataDir().exists()) { - System.out.println("Starting Freemail for the first time."); - System.out.println("You will probably want to add an account by running Freemail with arguments --newaccount "); - if (!getDataDir().mkdir()) { - System.out.println("Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - System.exit(1); - } - } - cfg.register("tempdir", new Freemail(), Freemail.TEMPDIRNAME); - if (!getTempDir().exists()) { - if (!getTempDir().mkdir()) { - System.out.println("Couldn't create temporary directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - System.exit(1); - } - } - - // start a SingleAccountWatcher for each account - File[] files = getDataDir().listFiles(); - for (int i = 0; i < files.length; i++) { - if (files[i].getName().equals(".") || files[i].getName().equals("..")) - continue; - if (!files[i].isDirectory()) continue; - - if(!AccountManager.validateUsername(files[i].getName()).equals("")) { - System.out.println("Account name "+files[i].getName()+" contains invalid chars, you may get problems accessing the account."); - } - - Thread t = new Thread(new SingleAccountWatcher(files[i]), "Account Watcher for "+files[i].getName()); - t.setDaemon(true); - t.start(); - } - - // and a sender thread - MessageSender sender = new MessageSender(getDataDir()); - Thread senderthread = new Thread(sender, "Message sender"); - senderthread.setDaemon(true); - senderthread.start(); - - // start the SMTP Listener - SMTPListener smtpl = new SMTPListener(sender, cfg); - Thread smtpthread = new Thread(smtpl, "SMTP Listener"); - smtpthread.setDaemon(true); - smtpthread.start(); - - // start the delayed ACK inserter - File ackdir = new File(getGlobalDataDir(), ACKDIR); - AckProcrastinator.setAckDir(ackdir); - AckProcrastinator ackinserter = new AckProcrastinator(); - Thread ackinsthread = new Thread(ackinserter, "Delayed ACK Inserter"); - ackinsthread.setDaemon(true); - ackinsthread.start(); - - - // start the IMAP listener - IMAPListener imapl = new IMAPListener(cfg); - imapl.run(); + + freemail.startServers(false); + freemail.startWorkers(false); } } Modified: trunk/apps/Freemail/src/freemail/FreemailPlugin.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-10 20:51:51 UTC (rev 19156) +++ trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-10 22:11:01 UTC (rev 19157) @@ -24,18 +24,7 @@ import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; - -import freemail.Freemail; -import freemail.fcp.FCPContext; -import freemail.fcp.FCPConnection; -import freemail.imap.IMAPListener; -import freemail.smtp.SMTPListener; -import freemail.config.Configurator; -import freemail.utils.Logger; - import freenet.pluginmanager.FredPlugin; import freenet.pluginmanager.FredPluginHTTP; import freenet.pluginmanager.FredPluginThreadless; @@ -48,168 +37,29 @@ // returns rather than just continuing to run for the lifetime of the plugin. public class FreemailPlugin extends Freemail implements FredPlugin, FredPluginHTTP, FredPluginThreadless { - private static PluginRespirator pr; - private ArrayList singleAccountWatcherList = new ArrayList(); - private MessageSender sender; - private SMTPListener smtpl; - private AckProcrastinator ackinserter; - private IMAPListener imapl; + private PluginRespirator pluginResp; - private Thread fcpThread; - private ArrayList /* of Thread */ singleAccountWatcherThreadList = new ArrayList(); - private Thread messageSenderThread; - private Thread smtpThread; - private Thread ackInserterThread; - private Thread imapThread; + public FreemailPlugin() { + super(CFGFILE); + } public void runPlugin(PluginRespirator pr) { - FreemailPlugin.pr = pr; - String cfgfile = CFGFILE; - Configurator cfg = new Configurator(new File(cfgfile)); - FCPContext fcpctx = new FCPContext(); - - cfg.register("loglevel", new Logger(), "normal|error"); - - Logger.normal(this, "This is the Freemail plugin version "+VER_MAJOR+"."+VER_MINOR+" build #"+BUILD_NO+" ("+VERSION_TAG+")"); + pluginResp = pr; - cfg.register("fcp_host", fcpctx, "localhost"); - cfg.register("fcp_port", fcpctx, "9481"); - - Freemail.fcpconn = new FCPConnection(fcpctx); - fcpThread = new Thread(fcpconn, "Freemail FCP Connection"); - fcpThread.setDaemon(true); - fcpThread.start(); - cfg.register("globaldatadir", new Freemail(), GLOBALDATADIR); - if (!getGlobalDataDir().exists()) { - if(!getGlobalDataDir().mkdir()) { - Logger.error(this,"Freemail plugin: Couldn't create global data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - return; - } - } - cfg.register("datadir", new Freemail(), Freemail.DATADIR); - if (!getDataDir().exists()) { - if (!getDataDir().mkdir()) { - Logger.error(this,"Freemail plugin: Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - return; - } - } - cfg.register("tempdir", new Freemail(), Freemail.TEMPDIRNAME); - if (!getTempDir().exists()) { - if (!Freemail.getTempDir().mkdir()) { - Logger.error(this,"Freemail plugin: Couldn't create temporary directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - return; - } - } - File[] files = getDataDir().listFiles(); - for (int i = 0; i < files.length; i++) { - if (files[i].getName().equals(".") || files[i].getName().equals("..")) - continue; - if (!files[i].isDirectory()) continue; - - String invalid=AccountManager.validateUsername(files[i].getName()); - if(!invalid.equals("")) { - Logger.error(this,"Account name "+files[i].getName()+" contains invalid chars (\""+invalid+"\"), you may get problems accessing the account."); - } - - SingleAccountWatcher saw = new SingleAccountWatcher(files[i]); - singleAccountWatcherList.add(saw); - Thread t = new Thread(saw, "Freemail Account Watcher for "+files[i].getName()); - t.setDaemon(true); - t.start(); - singleAccountWatcherThreadList.add(t); - } - - // and a sender thread - sender = new MessageSender(getDataDir()); - messageSenderThread = new Thread(sender, "Freemail Message sender"); - messageSenderThread.setDaemon(true); - messageSenderThread.start(); - - // start the SMTP Listener - smtpl = new SMTPListener(sender, cfg); - smtpThread = new Thread(smtpl, "Freemail SMTP Listener"); - smtpThread.setDaemon(true); - smtpThread.start(); - - // start the delayed ACK inserter - File ackdir = new File(getGlobalDataDir(), ACKDIR); - AckProcrastinator.setAckDir(ackdir); - ackinserter = new AckProcrastinator(); - ackInserterThread = new Thread(ackinserter, "Freemail Delayed ACK Inserter"); - ackInserterThread.setDaemon(true); - ackInserterThread.start(); - - // start the IMAP listener - imapl = new IMAPListener(cfg); - imapThread = new Thread(imapl, "Freemail IMAP Listener"); - imapThread.setDaemon(true); - imapThread.start(); + startFcp(true); + startServers(true); + startWorkers(true); } - public void terminate() { - Iterator it = singleAccountWatcherList.iterator(); - while(it.hasNext()) { - ((SingleAccountWatcher)it.next()).kill(); - it.remove(); - } - - sender.kill(); - ackinserter.kill(); - smtpl.kill(); - imapl.kill(); - // now kill the FCP thread - that's what all the other threads will be waiting on - fcpconn.kill(); - - // now clean up all the threads - boolean cleanedUp = false; - while (!cleanedUp) { - try { - it = singleAccountWatcherThreadList.iterator(); - while(it.hasNext()) { - ((Thread)it.next()).join(); - it.remove(); - } - - if (messageSenderThread != null) { - messageSenderThread.join(); - messageSenderThread = null; - } - if (ackInserterThread != null) { - ackInserterThread.join(); - ackInserterThread = null; - } - if (smtpThread != null) { - smtpThread.join(); - smtpl.joinClientThreads(); - smtpThread = null; - } - if (imapThread != null) { - imapThread.join(); - imapl.joinClientThreads(); - imapThread = null; - } - if (fcpThread != null) { - fcpThread.join(); - fcpThread = null; - } - } catch (InterruptedException ie) { - - } - cleanedUp = true; - } - - return; - } - public String handleHTTPGet(HTTPRequest request) throws PluginHTTPException { - HTMLNode pageNode = pr.getPageMaker().getPageNode("Freemail plugin", false, null); - HTMLNode contentNode = pr.getPageMaker().getContentNode(pageNode); + HTMLNode pageNode = pluginResp.getPageMaker().getPageNode("Freemail plugin", false, null); + HTMLNode contentNode = pluginResp.getPageMaker().getContentNode(pageNode); HTMLNode addBox = contentNode.addChild("div", "class", "infobox"); addBox.addChild("div", "class", "infobox-header", "Add account"); HTMLNode boxContent = addBox.addChild("div", "class", "infobox-content"); - HTMLNode form = pr.addFormChild(boxContent, "", "addAccountForm"); + HTMLNode form = pluginResp.addFormChild(boxContent, "", "addAccountForm"); HTMLNode table = form.addChild("table", "class", "plugintable"); HTMLNode tableRowName = table.addChild("tr"); @@ -229,8 +79,8 @@ } public String handleHTTPPost(HTTPRequest request) throws PluginHTTPException { - HTMLNode pageNode = pr.getPageMaker().getPageNode("Freemail plugin", false, null); - HTMLNode contentNode = pr.getPageMaker().getContentNode(pageNode); + HTMLNode pageNode = pluginResp.getPageMaker().getPageNode("Freemail plugin", false, null); + HTMLNode contentNode = pluginResp.getPageMaker().getContentNode(pageNode); String add = request.getPartAsString("add", 100); String name = request.getPartAsString("name", 100); @@ -295,5 +145,4 @@ public String handleHTTPPut(HTTPRequest request) throws PluginHTTPException { return null; } - } From alexlehm at freenetproject.org Sat Apr 12 14:12:34 2008 From: alexlehm at freenetproject.org (alexlehm at freenetproject.org) Date: Sat, 12 Apr 2008 14:12:34 +0000 (UTC) Subject: [Freemail] r19231 - trunk/apps/Freemail/src/freemail Message-ID: <20080412141234.B8EE04791BF@freenetproject.org> Author: alexlehm Date: 2008-04-12 14:12:34 +0000 (Sat, 12 Apr 2008) New Revision: 19231 Modified: trunk/apps/Freemail/src/freemail/Freemail.java trunk/apps/Freemail/src/freemail/FreemailCli.java trunk/apps/Freemail/src/freemail/FreemailPlugin.java Log: 0002262: NPE when sending mail (https://bugs.freenetproject.org/view.php?id=2262) change call order of startWorkers and startServers Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-12 14:01:07 UTC (rev 19230) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-12 14:12:34 UTC (rev 19231) @@ -130,6 +130,8 @@ fcpThread.start(); } + // note that this relies on sender being initialized + // (so startWorkers has to be called before) protected void startServers(boolean daemon) { // start the SMTP Listener smtpl = new SMTPListener(sender, configurator); Modified: trunk/apps/Freemail/src/freemail/FreemailCli.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-12 14:01:07 UTC (rev 19230) +++ trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-12 14:12:34 UTC (rev 19231) @@ -123,7 +123,7 @@ return; } + freemail.startWorkers(false); freemail.startServers(false); - freemail.startWorkers(false); } } Modified: trunk/apps/Freemail/src/freemail/FreemailPlugin.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-12 14:01:07 UTC (rev 19230) +++ trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-12 14:12:34 UTC (rev 19231) @@ -47,8 +47,8 @@ pluginResp = pr; startFcp(true); + startWorkers(true); startServers(true); - startWorkers(true); } public String handleHTTPGet(HTTPRequest request) throws PluginHTTPException { From dbkr at freenetproject.org Sat Apr 12 14:40:09 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sat, 12 Apr 2008 14:40:09 +0000 (UTC) Subject: [Freemail] r19233 - trunk/apps/Freemail/src/freemail Message-ID: <20080412144009.73684479194@freenetproject.org> Author: dbkr Date: 2008-04-12 14:40:09 +0000 (Sat, 12 Apr 2008) New Revision: 19233 Modified: trunk/apps/Freemail/src/freemail/Freemail.java trunk/apps/Freemail/src/freemail/FreemailCli.java trunk/apps/Freemail/src/freemail/FreemailPlugin.java Log: Fix my shonky object initialisation that caused 2262. Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-12 14:16:52 UTC (rev 19232) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-12 14:40:09 UTC (rev 19233) @@ -22,6 +22,7 @@ package freemail; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; @@ -56,15 +57,15 @@ private Thread ackInserterThread; private Thread imapThread; - private ArrayList singleAccountWatcherList = new ArrayList(); - private MessageSender sender; - private SMTPListener smtpl; - private AckProcrastinator ackinserter; - private IMAPListener imapl; + private final ArrayList singleAccountWatcherList = new ArrayList(); + private final MessageSender sender; + private final SMTPListener smtpl; + private final AckProcrastinator ackinserter; + private final IMAPListener imapl; protected final Configurator configurator; - protected Freemail(String cfgfile) { + protected Freemail(String cfgfile) throws IOException { configurator = new Configurator(new File(cfgfile)); configurator.register("loglevel", new Logger(), "normal|error"); @@ -73,7 +74,7 @@ if (!getDataDir().exists()) { if (!getDataDir().mkdir()) { Logger.error(this,"Freemail: Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - return; + throw new IOException("Couldn't create data dir"); } } @@ -81,6 +82,7 @@ if (!getGlobalDataDir().exists()) { if (!getGlobalDataDir().mkdir()) { Logger.error(this,"Freemail: Couldn't create global data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + throw new IOException("Couldn't create data dir"); } } @@ -88,9 +90,25 @@ if (!getTempDir().exists()) { if (!Freemail.getTempDir().mkdir()) { Logger.error(this,"Freemail: Couldn't create temporary directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - return; + throw new IOException("Couldn't create data dir"); } } + + FCPContext fcpctx = new FCPContext(); + configurator.register("fcp_host", fcpctx, "localhost"); + configurator.register("fcp_port", fcpctx, "9481"); + + Freemail.fcpconn = new FCPConnection(fcpctx); + + sender = new MessageSender(getDataDir()); + + File ackdir = new File(getGlobalDataDir(), ACKDIR); + AckProcrastinator.setAckDir(ackdir); + ackinserter = new AckProcrastinator(); + + + imapl = new IMAPListener(configurator); + smtpl = new SMTPListener(sender, configurator); } public static File getTempDir() { @@ -120,11 +138,6 @@ } protected void startFcp(boolean daemon) { - FCPContext fcpctx = new FCPContext(); - configurator.register("fcp_host", fcpctx, "localhost"); - configurator.register("fcp_port", fcpctx, "9481"); - - Freemail.fcpconn = new FCPConnection(fcpctx); fcpThread = new Thread(fcpconn, "Freemail FCP Connection"); fcpThread.setDaemon(true); fcpThread.start(); @@ -134,13 +147,12 @@ // (so startWorkers has to be called before) protected void startServers(boolean daemon) { // start the SMTP Listener - smtpl = new SMTPListener(sender, configurator); + smtpThread = new Thread(smtpl, "Freemail SMTP Listener"); smtpThread.setDaemon(daemon); smtpThread.start(); // start the IMAP listener - imapl = new IMAPListener(configurator); imapThread = new Thread(imapl, "Freemail IMAP Listener"); imapThread.setDaemon(daemon); imapThread.start(); @@ -171,16 +183,12 @@ singleAccountWatcherThreadList.add(t); } - // and a sender thread - sender = new MessageSender(getDataDir()); + // start the sender thread messageSenderThread = new Thread(sender, "Freemail Message sender"); messageSenderThread.setDaemon(daemon); messageSenderThread.start(); // start the delayed ACK inserter - File ackdir = new File(getGlobalDataDir(), ACKDIR); - AckProcrastinator.setAckDir(ackdir); - ackinserter = new AckProcrastinator(); ackInserterThread = new Thread(ackinserter, "Freemail Delayed ACK Inserter"); ackInserterThread.setDaemon(daemon); ackInserterThread.start(); Modified: trunk/apps/Freemail/src/freemail/FreemailCli.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-12 14:16:52 UTC (rev 19232) +++ trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-12 14:40:09 UTC (rev 19233) @@ -24,9 +24,10 @@ import java.io.IOException; import freemail.Freemail; +import freemail.utils.Logger; public class FreemailCli extends Freemail { - public FreemailCli(String cfgfile) { + public FreemailCli(String cfgfile) throws IOException { super(cfgfile); } @@ -78,7 +79,14 @@ } } - FreemailCli freemail = new FreemailCli(cfgfile); + + FreemailCli freemail; + try { + freemail = new FreemailCli(cfgfile); + } catch(IOException ioe) { + Logger.error(FreemailCli.class, "Failed to start Freemail: "+ioe.getMessage()); + return; + } freemail.startFcp(false); if (action.equals("--newaccount")) { Modified: trunk/apps/Freemail/src/freemail/FreemailPlugin.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-12 14:16:52 UTC (rev 19232) +++ trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-12 14:40:09 UTC (rev 19233) @@ -39,7 +39,7 @@ FredPluginThreadless { private PluginRespirator pluginResp; - public FreemailPlugin() { + public FreemailPlugin() throws IOException { super(CFGFILE); } From dbkr at freenetproject.org Sat Apr 12 22:33:19 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sat, 12 Apr 2008 22:33:19 +0000 (UTC) Subject: [Freemail] r19254 - trunk/apps/Freemail/src/freemail Message-ID: <20080412223319.17F164014AE@freenetproject.org> Author: dbkr Date: 2008-04-12 22:33:18 +0000 (Sat, 12 Apr 2008) New Revision: 19254 Modified: trunk/apps/Freemail/src/freemail/MailHeaderFilter.java Log: Whitelist header filter Modified: trunk/apps/Freemail/src/freemail/MailHeaderFilter.java =================================================================== --- trunk/apps/Freemail/src/freemail/MailHeaderFilter.java 2008-04-12 18:52:08 UTC (rev 19253) +++ trunk/apps/Freemail/src/freemail/MailHeaderFilter.java 2008-04-12 22:33:18 UTC (rev 19254) @@ -34,6 +34,8 @@ import java.util.TimeZone; import java.text.ParseException; import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import freemail.utils.Logger; @@ -43,6 +45,7 @@ private boolean foundEnd; private static final SimpleDateFormat sdf; private static final TimeZone gmt; + private static final Pattern messageIdPattern = Pattern.compile("]*)>?"); static { sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); @@ -104,8 +107,7 @@ } private String filterHeader(String name, String val) { - // simple blacklist filter for now - // a whitelist filter is probably excessive + // Whitelist filter if (name.equalsIgnoreCase("Date")) { // the norm is to put the sender's local time here, with the sender's local time offset // at the end. Rather than giving away what time zone we're in, parse the date in @@ -133,14 +135,40 @@ strDate = sdf.format(d); } return strDate; - } else if (name.equalsIgnoreCase("User-Agent")) { - // might as well hide this + } else if (name.equalsIgnoreCase("Message-ID")) { + // We want to keep message-ids for in-reply-to and hence message threading to work, but we need to make sure the + // mail client hasn't put in a real hostname, as some have been known to. + Matcher m = messageIdPattern.matcher(val); + if (!m.matches() || m.groupCount() < 2) { + // couldn't make any sense of it, so just drop it + return null; + } else { + if (m.group(2).endsWith("freemail")) { + // okay, the hostname part ends with freemail, so it's a fake Freemail domain and not a real one + return val; + } else { + // It's something else, so just replace it with 'freemail', although this might not actually be any more + // useful than dropping it, since the mail client will be looking for the unmangled header. + return "<"+m.group(1)+"@freemail>"; + } + + } + } else if (name.equalsIgnoreCase("From")) { + return val; + } else if (name.equalsIgnoreCase("To")) { + return val; + } else if (name.equalsIgnoreCase("Subject")) { + return val; + } else if (name.equalsIgnoreCase("MIME-Version")) { + return val; + } else if (name.equalsIgnoreCase("Content-Type")) { + return val; + } else if (name.equalsIgnoreCase("Content-Transfer-Encoding")) { + return val; + } else if (name.equalsIgnoreCase("In-Reply-To")) { + return val; + } else { return null; - } else if (name.equalsIgnoreCase("Received")) { - // may give away local address - return null; - } else { - return val; } } } From dbkr at freenetproject.org Sun Apr 13 21:39:22 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 13 Apr 2008 21:39:22 +0000 (UTC) Subject: [Freemail] r19272 - in trunk/apps/Freemail/src/freemail: . fcp imap smtp utils Message-ID: <20080413213922.E92AA4790AC@freenetproject.org> Author: dbkr Date: 2008-04-13 21:39:22 +0000 (Sun, 13 Apr 2008) New Revision: 19272 Modified: trunk/apps/Freemail/src/freemail/AckProcrastinator.java trunk/apps/Freemail/src/freemail/Freemail.java trunk/apps/Freemail/src/freemail/InboundContact.java trunk/apps/Freemail/src/freemail/MailLog.java trunk/apps/Freemail/src/freemail/MailMessage.java trunk/apps/Freemail/src/freemail/MailSite.java trunk/apps/Freemail/src/freemail/MessageBank.java trunk/apps/Freemail/src/freemail/MessageSender.java trunk/apps/Freemail/src/freemail/NIMContact.java trunk/apps/Freemail/src/freemail/OutboundContact.java trunk/apps/Freemail/src/freemail/RTSFetcher.java trunk/apps/Freemail/src/freemail/RTSLog.java trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java trunk/apps/Freemail/src/freemail/SlotManager.java trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java trunk/apps/Freemail/src/freemail/imap/IMAPMessageFlags.java trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java trunk/apps/Freemail/src/freemail/utils/DateStringFactory.java Log: Some fixes from FindBugs Modified: trunk/apps/Freemail/src/freemail/AckProcrastinator.java =================================================================== --- trunk/apps/Freemail/src/freemail/AckProcrastinator.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/AckProcrastinator.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -52,13 +52,11 @@ private static final int RANDOM_ACK_SIZE = 512; private static File ackdir; - private static Random rnd; + private static Random rnd = new Random(); - public AckProcrastinator() { - rnd = new Random(); - File ackdir = getAckDir(); - if (!ackdir.exists()) { - ackdir.mkdir(); + public AckProcrastinator() throws IOException { + if (!ackdir.exists() && !ackdir.mkdir()) { + throw new IOException("Coudn't create ACK dir!"); } } Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -45,7 +45,7 @@ private static final String GLOBALDATADIR = "globaldata"; private static final String ACKDIR = "delayedacks"; protected static final String CFGFILE = "globalconfig"; - private static File datadir; + private File datadir; private static File globaldatadir; private static File tempdir; protected static FCPConnection fcpconn = null; @@ -72,27 +72,21 @@ configurator.register("loglevel", new Logger(), "normal|error"); configurator.register("datadir", this, Freemail.DEFAULT_DATADIR); - if (!getDataDir().exists()) { - if (!getDataDir().mkdir()) { - Logger.error(this,"Freemail: Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - throw new IOException("Couldn't create data dir"); - } + if (!datadir.exists() && !datadir.mkdir()) { + Logger.error(this,"Freemail: Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + throw new IOException("Couldn't create data dir"); } configurator.register("globaldatadir", this, GLOBALDATADIR); - if (!getGlobalDataDir().exists()) { - if (!getGlobalDataDir().mkdir()) { - Logger.error(this,"Freemail: Couldn't create global data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - throw new IOException("Couldn't create data dir"); - } + if (!globaldatadir.exists() && !globaldatadir.mkdir()) { + Logger.error(this,"Freemail: Couldn't create global data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + throw new IOException("Couldn't create data dir"); } configurator.register("tempdir", this, Freemail.TEMPDIRNAME); - if (!getTempDir().exists()) { - if (!Freemail.getTempDir().mkdir()) { - Logger.error(this,"Freemail: Couldn't create temporary directory. Please ensure that the user you are running Freemail as has write access to its working directory"); - throw new IOException("Couldn't create data dir"); - } + if (!tempdir.exists() && !tempdir.mkdir()) { + Logger.error(this,"Freemail: Couldn't create temporary directory. Please ensure that the user you are running Freemail as has write access to its working directory"); + throw new IOException("Couldn't create data dir"); } FCPContext fcpctx = new FCPContext(); @@ -105,7 +99,7 @@ sender = new MessageSender(accountManager); - File ackdir = new File(getGlobalDataDir(), ACKDIR); + File ackdir = new File(globaldatadir, ACKDIR); AckProcrastinator.setAckDir(ackdir); ackinserter = new AckProcrastinator(); @@ -118,14 +112,6 @@ return Freemail.tempdir; } - protected static File getGlobalDataDir() { - return globaldatadir; - } - - public static File getDataDir() { - return datadir; - } - public static FCPConnection getFCPConnection() { return Freemail.fcpconn; } @@ -136,11 +122,11 @@ public void setConfigProp(String key, String val) { if (key.equalsIgnoreCase("datadir")) { - Freemail.datadir = new File(val); + datadir = new File(val); } else if (key.equalsIgnoreCase("tempdir")) { - Freemail.tempdir = new File(val); + tempdir = new File(val); } else if (key.equalsIgnoreCase("globaldatadir")) { - Freemail.globaldatadir = new File(val); + globaldatadir = new File(val); } } Modified: trunk/apps/Freemail/src/freemail/InboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/InboundContact.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/InboundContact.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -244,7 +244,7 @@ } - private class MessageLog { + private static class MessageLog { private static final String LOGFILE = "log"; private final File logfile; @@ -263,7 +263,10 @@ String line; while ( (line = br.readLine()) != null) { int curid = Integer.parseInt(line); - if (curid == targetid) return true; + if (curid == targetid) { + br.close(); + return true; + } } br.close(); Modified: trunk/apps/Freemail/src/freemail/MailLog.java =================================================================== --- trunk/apps/Freemail/src/freemail/MailLog.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/MailLog.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -69,6 +69,7 @@ this.messages.put(new Integer(thisnum), parts[1]); } + br.close(); frdr.close(); } catch (IOException ioe) { return; @@ -120,6 +121,7 @@ pw.flush(); try { + pw.close(); fos.close(); } catch (IOException ioe) { return; Modified: trunk/apps/Freemail/src/freemail/MailMessage.java =================================================================== --- trunk/apps/Freemail/src/freemail/MailMessage.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/MailMessage.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -315,7 +315,7 @@ this.file.renameTo(new File(this.file.getParentFile(), newname)); } - private class MailMessageHeader { + private static class MailMessageHeader { public String name; public String val; Modified: trunk/apps/Freemail/src/freemail/MailSite.java =================================================================== --- trunk/apps/Freemail/src/freemail/MailSite.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/MailSite.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -68,7 +68,7 @@ return buf.toString(); } - public int Publish() { + public int publish() { byte[] mailpage; String mailsite_s = this.getMailPage(); if (mailsite_s == null) { @@ -95,7 +95,7 @@ int actualslot = -1; try { - actualslot = cli.SlotInsert(mailpage, key, minslot, "/"+MAILPAGE); + actualslot = cli.slotInsert(mailpage, key, minslot, "/"+MAILPAGE); } catch (ConnectionTerminatedException cte) { return -1; } Modified: trunk/apps/Freemail/src/freemail/MessageBank.java =================================================================== --- trunk/apps/Freemail/src/freemail/MessageBank.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/MessageBank.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -246,7 +246,7 @@ } } - private class MessageFileNameFilter implements FilenameFilter { + private static class MessageFileNameFilter implements FilenameFilter { public boolean accept(File dir, String name) { if (name.startsWith(".")) return false; if (!name.matches("[0-9]+(,.*)?")) return false; @@ -255,7 +255,7 @@ } // compare to filenames by number leading up to "," - private class UIDComparator implements Comparator { + private static class UIDComparator implements Comparator { public final int compare ( Object a, Object b ) { int ia=Integer.parseInt(((File)a).getName().split(",",2)[0]); int ib=Integer.parseInt(((File)b).getName().split(",",2)[0]); Modified: trunk/apps/Freemail/src/freemail/MessageSender.java =================================================================== --- trunk/apps/Freemail/src/freemail/MessageSender.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/MessageSender.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -138,8 +138,8 @@ } private void sendDir(FreemailAccount fromAccount, File dir) throws ConnectionTerminatedException { + if (dir == null) return; File[] files = dir.listFiles(); - if (dir == null) return; for (int i = 0; i < files.length; i++) { if (files[i].getName().startsWith(".")) continue; Modified: trunk/apps/Freemail/src/freemail/NIMContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/NIMContact.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/NIMContact.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -44,6 +44,7 @@ FileReader frdr = new FileReader(this.keyfile); BufferedReader br = new BufferedReader(frdr); String key = br.readLine(); + br.close(); frdr.close(); return key; } @@ -59,7 +60,7 @@ for (i = 0; i< files.length; i++) { if (!files[i].getName().startsWith(LOGFILE_PREFIX)) continue; - Date logdate = DateStringFactory.DateFromKeyString(files[i].getName().substring(LOGFILE_PREFIX.length())); + Date logdate = DateStringFactory.dateFromKeyString(files[i].getName().substring(LOGFILE_PREFIX.length())); if (logdate == null) { // couldn't parse the date... hmm files[i].delete(); Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -91,12 +91,18 @@ throw new BadFreemailAddressException(); } else { File contactsdir = new File(account.getAccountDir(), SingleAccountWatcher.CONTACTS_DIR); - if (!contactsdir.exists()) - contactsdir.mkdir(); + if (!contactsdir.exists()) { + if (!contactsdir.mkdir()) { + throw new IOException("Couldn't create contacts dir!"); + } + } File outbounddir = new File(contactsdir, SingleAccountWatcher.OUTBOUND_DIR); - if (!outbounddir.exists()) - outbounddir.mkdir(); + if (!outbounddir.exists()) { + if (!outbounddir.mkdir()) { + throw new IOException("Couldn't create outbound dir!"); + } + } if (!this.address.is_ssk_address()) { String ssk_mailsite = this.fetchKSKRedirect(this.address.getMailpageKey()); @@ -115,17 +121,19 @@ File obctdir = new File(outbounddir, this.address.getSubDomain().toLowerCase()); - if (!obctdir.exists()) - obctdir.mkdir(); + if (!obctdir.exists() && !obctdir.mkdir()) { + throw new IOException("Couldn't create outbound contact dir!"); + } this.contactfile = new PropsFile(new File(obctdir, PROPSFILE_NAME)); this.ctoutbox = new File(obctdir, OUTBOX_DIR); - if (!this.ctoutbox.exists()) - this.ctoutbox.mkdir(); + if (!this.ctoutbox.exists() && !this.ctoutbox.mkdir()) { + throw new IOException("Couldn't create contact outbox!"); + } } } - public OutboundContact(FreemailAccount acc, File ctdir) { + public OutboundContact(FreemailAccount acc, File ctdir) throws IOException { this.account = acc; this.address = new EmailAddress(); this.address.domain = ctdir.getName()+".freemail"; @@ -133,14 +141,19 @@ this.contactfile = new PropsFile(new File(ctdir, PROPSFILE_NAME)); this.ctoutbox = new File(ctdir, OUTBOX_DIR); - if (!this.ctoutbox.exists()) - this.ctoutbox.mkdir(); + if (!this.ctoutbox.exists()) { + if (!this.ctoutbox.mkdir()) { + throw new IOException("Couldn't create contact outbox dir!"); + } + } } public void checkCTS() throws OutboundContactFatalException, ConnectionTerminatedException { String status = this.contactfile.get("status"); if (status == null) { this.init(); + status = this.contactfile.get("status"); + if (status == null) return; } if (status.equals("cts-received")) { @@ -400,7 +413,7 @@ // insert it! HighLevelFCPClient cli = new HighLevelFCPClient(); - if (cli.SlotInsert(encmsg, "KSK@"+rtsksk+"-"+DateStringFactory.getKeyString(), 1, "") < 0) { + if (cli.slotInsert(encmsg, "KSK@"+rtsksk+"-"+DateStringFactory.getKeyString(), 1, "") < 0) { // safe to copy the message into the contact outbox though return false; } Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java =================================================================== --- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -133,7 +133,7 @@ log.pruneBefore(cal.getTime()); } - private class MySlotSaveData { + private static class MySlotSaveData { RTSLog log; String date; } Modified: trunk/apps/Freemail/src/freemail/RTSLog.java =================================================================== --- trunk/apps/Freemail/src/freemail/RTSLog.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/RTSLog.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -58,7 +58,7 @@ } private boolean isBeforeBirth(String daystr) { - Date day = DateStringFactory.DateFromKeyString(daystr); + Date day = DateStringFactory.dateFromKeyString(daystr); String birth_s = this.logfile.get("birth"); Date birth; if (birth_s == null) { @@ -66,7 +66,7 @@ birth_s = DateStringFactory.getOffsetKeyString(0); this.logfile.put("birth", birth_s); } else { - birth = DateStringFactory.DateFromKeyString(birth_s); + birth = DateStringFactory.dateFromKeyString(birth_s); if (birth.after(new Date())) { Logger.error(this, "RTS log was created in the future! Resetting to now"); birth = new Date(); @@ -103,7 +103,7 @@ continue; } - Date logdate = DateStringFactory.DateFromKeyString(datestr); + Date logdate = DateStringFactory.dateFromKeyString(datestr); if (logdate == null) { // couldn't parse the date... hmm hitlist.add(cur); Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java =================================================================== --- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -23,6 +23,7 @@ import java.io.File; import java.io.FilenameFilter; +import java.io.IOException; import java.lang.InterruptedException; import freemail.fcp.ConnectionTerminatedException; @@ -108,7 +109,7 @@ // is it time we inserted the mailsite? if (System.currentTimeMillis() > this.mailsite_last_upload + MAILSITE_UPLOAD_INTERVAL) { MailSite ms = new MailSite(account.getProps()); - if (ms.Publish() > 0) { + if (ms.publish() > 0) { this.mailsite_last_upload = System.currentTimeMillis(); } } @@ -120,9 +121,12 @@ if (obcontacts != null) { int i; for (i = 0; i < obcontacts.length; i++) { - OutboundContact obct = new OutboundContact(account, obcontacts[i]); - - obct.doComm(); + try { + OutboundContact obct = new OutboundContact(account, obcontacts[i]); + obct.doComm(); + } catch (IOException ioe) { + Logger.error(this, "Failed to create outbound contact - not sending mail"); + } } } if (this.nf != null) { @@ -170,14 +174,14 @@ stopping = true; } - private class outboundContactFilenameFilter implements FilenameFilter { + private static class outboundContactFilenameFilter implements FilenameFilter { // check that each dir is a base32 encoded filename public boolean accept(File dir, String name ) { return name.matches("[A-Za-z2-7]+"); } } - private class inboundContactFilenameFilter implements FilenameFilter { + private static class inboundContactFilenameFilter implements FilenameFilter { // check that each dir is a freenet key public boolean accept(File dir, String name ) { return name.matches("[A-Za-z0-9~-]+,[A-Za-z0-9~-]+,[A-Za-z0-9~-]+"); Modified: trunk/apps/Freemail/src/freemail/SlotManager.java =================================================================== --- trunk/apps/Freemail/src/freemail/SlotManager.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/SlotManager.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -175,7 +175,7 @@ return retval; } - private class Slot { + private static class Slot { String slot; long time_added; } Modified: trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java =================================================================== --- trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -195,7 +195,7 @@ return -1; } - public int SlotInsert(byte[] data, String basekey, int minslot, String suffix) throws ConnectionTerminatedException { + public int slotInsert(byte[] data, String basekey, int minslot, String suffix) throws ConnectionTerminatedException { int slot = minslot; boolean carryon = true; ByteArrayInputStream bis; Modified: trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java =================================================================== --- trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -191,10 +191,10 @@ } if (refname != null) refname = trimQuotes(refname); - if (refname.length() == 0) refname = null; + if (refname!= null && refname.length() == 0) refname = null; if (mbname != null) mbname = trimQuotes(mbname); - if (mbname.length() == 0) mbname = null; + if (mbname != null && mbname.length() == 0) mbname = null; if (mbname == null) { // return hierarchy delimiter @@ -1280,7 +1280,7 @@ EmailAddress addr = new EmailAddress(address); - String retval = new String("(("); + String retval = "(("; retval += this.IMAPifyString(addr.realname)+" "; // SMTP Source Route. Whatever this is, it's not relevant! retval += "NIL "; Modified: trunk/apps/Freemail/src/freemail/imap/IMAPMessageFlags.java =================================================================== --- trunk/apps/Freemail/src/freemail/imap/IMAPMessageFlags.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/imap/IMAPMessageFlags.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -122,7 +122,7 @@ } public String getFlags() { - String retval = new String(""); + String retval = ""; for (int i = 0; i < allFlags.length; i++) { if (this.flags.contains(allFlags[i])) { Modified: trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java =================================================================== --- trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -162,8 +162,6 @@ } if (b64password == null) return; - password = new String(Base64.decode(b64password.getBytes())); - uname = new String(Base64.decode(b64username.getBytes())); password = new String(Base64.decode(b64password.getBytes())); } else if (cmd.args[0].equalsIgnoreCase("plain")) { Modified: trunk/apps/Freemail/src/freemail/utils/DateStringFactory.java =================================================================== --- trunk/apps/Freemail/src/freemail/utils/DateStringFactory.java 2008-04-13 20:52:14 UTC (rev 19271) +++ trunk/apps/Freemail/src/freemail/utils/DateStringFactory.java 2008-04-13 21:39:22 UTC (rev 19272) @@ -30,12 +30,7 @@ public class DateStringFactory { private static final TimeZone gmt = TimeZone.getTimeZone("GMT"); private static final Calendar cal = Calendar.getInstance(gmt); - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); - static { - sdf.setTimeZone(gmt); - } - public static String getKeyString() { return getOffsetKeyString(0); } @@ -45,11 +40,17 @@ cal.setTime(new Date()); cal.add(Calendar.DAY_OF_MONTH, offset); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + sdf.setTimeZone(gmt); + return sdf.format(cal.getTime()); } - public static Date DateFromKeyString(String str) { + public static Date dateFromKeyString(String str) { try { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + sdf.setTimeZone(gmt); + sdf.setLenient(false); return sdf.parse(str); } catch (ParseException pe) { From dbkr at freenetproject.org Sun Apr 13 21:51:43 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 13 Apr 2008 21:51:43 +0000 (UTC) Subject: [Freemail] r19273 - trunk/apps/Freemail/src/freemail Message-ID: <20080413215143.3A6AF479947@freenetproject.org> Author: dbkr Date: 2008-04-13 21:51:43 +0000 (Sun, 13 Apr 2008) New Revision: 19273 Modified: trunk/apps/Freemail/src/freemail/AccountManager.java Log: Don't try & create accounts unless we actually want to. Don't fail to create an account because the directory already exists. Get username right for accounts. Modified: trunk/apps/Freemail/src/freemail/AccountManager.java =================================================================== --- trunk/apps/Freemail/src/freemail/AccountManager.java 2008-04-13 21:39:22 UTC (rev 19272) +++ trunk/apps/Freemail/src/freemail/AccountManager.java 2008-04-13 21:51:43 UTC (rev 19273) @@ -93,7 +93,10 @@ +"\"), you may get problems accessing the account."); } - FreemailAccount account = new FreemailAccount(files[i].toString(), files[i], getAccountFile(files[i])); + FreemailAccount account = new FreemailAccount(files[i].getName(), files[i], getAccountFile(files[i])); + if (account == null) { + Logger.error(this, "Couldn't initialise account from directory '"+files[i].getName()+"' - ignoring."); + } accounts.put(files[i].getName(), account); } @@ -135,9 +138,9 @@ } File accountdir = new File(datadir, username); - if (!accountdir.mkdir()) throw new IOException("Failed to create directory "+username+" in "+datadir); + if (!accountdir.exists() && !accountdir.mkdir()) throw new IOException("Failed to create directory "+username+" in "+datadir); - PropsFile accProps = getAccountFile(accountdir); + PropsFile accProps = newAccountFile(accountdir); FreemailAccount account = new FreemailAccount(username, accountdir, accProps); accounts.put(username, account); @@ -182,6 +185,16 @@ private static PropsFile getAccountFile(File accdir) { PropsFile accfile = new PropsFile(new File(accdir, ACCOUNT_FILE)); + if (!accdir.exists() || !accfile.exists()) { + return null; + } + + return accfile; + } + + private static PropsFile newAccountFile(File accdir) { + PropsFile accfile = new PropsFile(new File(accdir, ACCOUNT_FILE)); + if (accdir.exists() && !accfile.exists()) { initAccFile(accfile); } From dbkr at freenetproject.org Sun Apr 13 23:45:01 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 13 Apr 2008 23:45:01 +0000 (UTC) Subject: [Freemail] r19277 - trunk/apps/Freemail/src/freemail Message-ID: <20080413234501.1600A4797CF@freenetproject.org> Author: dbkr Date: 2008-04-13 23:45:00 +0000 (Sun, 13 Apr 2008) New Revision: 19277 Modified: trunk/apps/Freemail/src/freemail/Freemail.java trunk/apps/Freemail/src/freemail/FreemailPlugin.java Log: Implement FredPluginVersioned Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 23:44:01 UTC (rev 19276) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 23:45:00 UTC (rev 19277) @@ -108,6 +108,10 @@ smtpl = new SMTPListener(accountManager, sender, configurator); } + public static String getVersionString() { + return VER_MAJOR+"."+VER_MINOR+" build #"+BUILD_NO+" ("+VERSION_TAG+")"; + } + public static File getTempDir() { return Freemail.tempdir; } @@ -161,7 +165,7 @@ } protected void startWorkers(boolean daemon) { - System.out.println("This is Freemail version "+VER_MAJOR+"."+VER_MINOR+" build #"+BUILD_NO+" ("+VERSION_TAG+")"); + System.out.println("This is Freemail version "+getVersionString()); System.out.println("Freemail is released under the terms of the GNU Lesser General Public License. Freemail is provided WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see the LICENSE file included with this distribution."); System.out.println(""); Modified: trunk/apps/Freemail/src/freemail/FreemailPlugin.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-13 23:44:01 UTC (rev 19276) +++ trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-13 23:45:00 UTC (rev 19277) @@ -27,6 +27,7 @@ import freenet.pluginmanager.FredPlugin; import freenet.pluginmanager.FredPluginHTTP; import freenet.pluginmanager.FredPluginThreadless; +import freenet.pluginmanager.FredPluginVersioned; import freenet.pluginmanager.PluginHTTPException; import freenet.pluginmanager.PluginRespirator; import freenet.support.HTMLNode; @@ -35,13 +36,17 @@ // although we have threads, we still 'implement' FredPluginThreadless because our runPlugin method // returns rather than just continuing to run for the lifetime of the plugin. public class FreemailPlugin extends Freemail implements FredPlugin, FredPluginHTTP, - FredPluginThreadless { + FredPluginThreadless, FredPluginVersioned { private PluginRespirator pluginResp; public FreemailPlugin() throws IOException { super(CFGFILE); } + public String getVersion() { + return getVersionString(); + } + public void runPlugin(PluginRespirator pr) { pluginResp = pr; From dbkr at freenetproject.org Sun Apr 13 23:45:47 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 13 Apr 2008 23:45:47 +0000 (UTC) Subject: [Freemail] r19278 - trunk/apps/Freemail/src/freemail Message-ID: <20080413234547.989BC47983E@freenetproject.org> Author: dbkr Date: 2008-04-13 23:45:47 +0000 (Sun, 13 Apr 2008) New Revision: 19278 Modified: trunk/apps/Freemail/src/freemail/Freemail.java Log: Build number bump. Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 23:45:00 UTC (rev 19277) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 23:45:47 UTC (rev 19278) @@ -37,7 +37,7 @@ public abstract class Freemail implements ConfigClient { public static final int VER_MAJOR = 0; public static final int VER_MINOR = 1; - public static final int BUILD_NO = 9; + public static final int BUILD_NO = 10; public static final String VERSION_TAG = "Pet Shop"; private static final String TEMPDIRNAME = "temp"; From dbkr at freenetproject.org Sun Apr 13 23:47:54 2008 From: dbkr at freenetproject.org (Dave Baker) Date: Mon, 14 Apr 2008 00:47:54 +0100 Subject: [Freemail] Freemail Tweaks - Testing Required Message-ID: <200804140047.55566.dbkr@freenetproject.org> Hi all, I've just been through Freemail cleaning up things like access to account files, which could potentially have caused some issues. I'd appreciate if a few people could (having made sure their Freemail directory backup is recent!) test the latest build of Freemail, build 10. I've also just added a 'version' column to Freenet's plugin page, so if you're on the latest testing version of Freenet and using the Freemail plugin, you'll be able to verify that you have the latest version in the web interface. Please let me know of any problems. Dave From dbkr at freenetproject.org Sun Apr 13 20:26:19 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 13 Apr 2008 20:26:19 +0000 (UTC) Subject: [Freemail] r19270 - in trunk/apps/Freemail/src/freemail: . imap smtp utils Message-ID: <20080413202619.95B03479A4C@freenetproject.org> Author: dbkr Date: 2008-04-13 20:26:19 +0000 (Sun, 13 Apr 2008) New Revision: 19270 Added: trunk/apps/Freemail/src/freemail/FreemailAccount.java Modified: trunk/apps/Freemail/src/freemail/AccountManager.java trunk/apps/Freemail/src/freemail/Freemail.java trunk/apps/Freemail/src/freemail/FreemailCli.java trunk/apps/Freemail/src/freemail/FreemailPlugin.java trunk/apps/Freemail/src/freemail/MessageBank.java trunk/apps/Freemail/src/freemail/MessageSender.java trunk/apps/Freemail/src/freemail/OutboundContact.java trunk/apps/Freemail/src/freemail/RTSFetcher.java trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java trunk/apps/Freemail/src/freemail/imap/IMAPListener.java trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java trunk/apps/Freemail/src/freemail/smtp/SMTPListener.java trunk/apps/Freemail/src/freemail/utils/PropsFile.java Log: Do some refactoring: pass the account properties and messagebank around in a FreemailAccount object to things that need it rather than creating them as needed. This means we always use the same object rather than creating them as needed. Modified: trunk/apps/Freemail/src/freemail/AccountManager.java =================================================================== --- trunk/apps/Freemail/src/freemail/AccountManager.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/AccountManager.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -26,6 +26,10 @@ import java.io.PrintStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.Random; import java.util.Date; import java.text.SimpleDateFormat; @@ -51,7 +55,6 @@ import freemail.utils.Logger; public class AccountManager { - public static final String DATADIR = "data"; // this really doesn't matter a great deal public static final String NIMDIR = "nim"; @@ -64,7 +67,46 @@ public static final String MAILSITE_SUFFIX = "mailsite"; public static final String MAILSITE_VERSION = "-1"; + + // We keep FreemailAccount objects for all the accounts in this instance of Freemail - they need to be in memory + // anyway since there's SingleAccountWatcher thread running for each of them anyway - and we return the same object + // each time a request is made for a given account. + private Map/**/ accounts = new HashMap(); + + private final File datadir; + + public AccountManager(File _datadir) { + datadir = _datadir; + if (!datadir.exists()) { + datadir.mkdir(); + } + + File[] files = datadir.listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].getName().equals(".") || files[i].getName().equals("..")) + continue; + if (!files[i].isDirectory()) continue; + String invalid=validateUsername(files[i].getName()); + if(!invalid.equals("")) { + Logger.error(this,"Account name "+files[i].getName()+" contains invalid chars (\""+invalid + +"\"), you may get problems accessing the account."); + } + + FreemailAccount account = new FreemailAccount(files[i].toString(), files[i], getAccountFile(files[i])); + + accounts.put(files[i].getName(), account); + } + } + + public FreemailAccount getAccount(String username) { + return (FreemailAccount)accounts.get(username); + } + + public List/**/ getAllAccounts() { + return new LinkedList(accounts.values()); + } + // avoid invalid chars in username or address // returns the first invalid char to give user a hint private static String validateChars(String username, String invalid) { @@ -86,24 +128,27 @@ return validateChars(username, "@\'\"\\/,:%()+ "); } - public static void Create(String username) throws IOException,IllegalArgumentException { - File datadir = new File(DATADIR); + public FreemailAccount createAccount(String username) throws IOException,IllegalArgumentException { String invalid=validateUsername(username); if(!invalid.equals("")) { throw new IllegalArgumentException("The username may not contain the character '"+invalid+"'"); } - if (!datadir.exists()) { - if (!datadir.mkdir()) throw new IOException("Failed to create data directory"); - } - File accountdir = new File(DATADIR, username); - if (!accountdir.mkdir()) throw new IOException("Failed to create directory "+username+" in "+DATADIR); + File accountdir = new File(datadir, username); + if (!accountdir.mkdir()) throw new IOException("Failed to create directory "+username+" in "+datadir); - putWelcomeMessage(username, new EmailAddress(username+"@"+getFreemailDomain(accountdir))); + PropsFile accProps = getAccountFile(accountdir); + + FreemailAccount account = new FreemailAccount(username, accountdir, accProps); + accounts.put(username, account); + + putWelcomeMessage(account, new EmailAddress(username+"@"+getFreemailDomain(accProps))); + + return account; } - public static void setupNIM(String username) throws IOException { - File accountdir = new File(DATADIR, username); + public void setupNIM(String username) throws IOException { + File accountdir = new File(datadir, username); File contacts_dir = new File(accountdir, SingleAccountWatcher.CONTACTS_DIR); if (!contacts_dir.exists()) { @@ -123,25 +168,18 @@ pw.close(); } - public static void ChangePassword(String username, String newpassword) throws Exception { + public static void changePassword(FreemailAccount account, String newpassword) throws Exception { MD5Digest md5 = new MD5Digest(); - File accountdir = new File(DATADIR, username); - if (!accountdir.exists()) { - throw new Exception("No such account - "+username+"."); - } - - PropsFile accfile = getAccountFile(accountdir); - md5.update(newpassword.getBytes(), 0, newpassword.getBytes().length); byte[] md5passwd = new byte[md5.getDigestSize()]; md5.doFinal(md5passwd, 0); String strmd5 = new String(Hex.encode(md5passwd)); - accfile.put("md5passwd", strmd5); + account.getProps().put("md5passwd", strmd5); } - public static PropsFile getAccountFile(File accdir) { + private static PropsFile getAccountFile(File accdir) { PropsFile accfile = new PropsFile(new File(accdir, ACCOUNT_FILE)); if (accdir.exists() && !accfile.exists()) { @@ -151,12 +189,6 @@ return accfile; } - public static String getFreemailDomain(File accdir) { - PropsFile accfile = getAccountFile(accdir); - - return getFreemailDomain(accfile); - } - public static String getFreemailDomain(PropsFile accfile) { FreenetURI mailsite; try { @@ -173,9 +205,7 @@ return Base32.encode(mailsite.getKeyBody().getBytes())+".freemail"; } - public static String getKSKFreemailDomain(File accdir) { - PropsFile accfile = getAccountFile(accdir); - + public static String getKSKFreemailDomain(PropsFile accfile) { String alias = accfile.get("domain_alias"); if (alias == null) return null; @@ -183,9 +213,7 @@ return alias+".freemail"; } - public static RSAKeyParameters getPrivateKey(File accdir) { - PropsFile props = getAccountFile(accdir); - + public static RSAKeyParameters getPrivateKey(PropsFile props) { String mod_str = props.get("asymkey.modulus"); String privexp_str = props.get("asymkey.privexponent"); @@ -264,33 +292,24 @@ Logger.normal(AccountManager.class,"Account creation completed."); } - public static boolean addShortAddress(String username, String alias) throws Exception { - File accountdir = new File(DATADIR, username); - if (!accountdir.exists()) { - throw new Exception("No such account - "+username+"."); - } - + public static boolean addShortAddress(FreemailAccount account, String alias) throws Exception { String invalid=validateShortAddress(alias); if(!invalid.equals("")) { throw new IllegalArgumentException("The short address may not contain the character '"+invalid+"'"); } - PropsFile accfile = getAccountFile(accountdir); - alias = alias.toLowerCase(); - MailSite ms = new MailSite(accfile); + MailSite ms = new MailSite(account.getProps()); if (ms.insertAlias(alias)) { - accfile.put("domain_alias", alias); + account.getProps().put("domain_alias", alias); SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z"); - EmailAddress to = new EmailAddress(username+"@"+getKSKFreemailDomain(accountdir)); + EmailAddress to = new EmailAddress(account.getUsername()+"@"+getKSKFreemailDomain(account.getProps())); - MessageBank mb = new MessageBank(username); + MailMessage m = account.getMessageBank().createMessage(); - MailMessage m = mb.createMessage(); - m.addHeader("From", "Freemail Daemon "); m.addHeader("To", to.toString()); m.addHeader("Subject", "Your New Address"); @@ -317,20 +336,15 @@ } } - public static boolean authenticate(String username, String password) { - if (!validate_username(username)) return false; + public FreemailAccount authenticate(String username, String password) { + if (!validate_username(username)) return null; - //String sep = System.getProperty("file.separator"); + FreemailAccount account = (FreemailAccount)accounts.get(username); + if (account == null) return null; - File accountdir = new File(DATADIR, username); - if (!accountdir.exists()) { - return false; - } - PropsFile accfile = getAccountFile(accountdir); + String realmd5str = account.getProps().get("md5passwd"); + if (realmd5str == null) return null; - String realmd5str = accfile.get("md5passwd"); - if (realmd5str == null) return false; - MD5Digest md5 = new MD5Digest(); md5.update(password.getBytes(), 0, password.getBytes().length); byte[] givenmd5 = new byte[md5.getDigestSize()]; @@ -339,9 +353,9 @@ String givenmd5str = new String(Hex.encode(givenmd5)); if (realmd5str.equals(givenmd5str)) { - return true; + return account; } - return false; + return null; } private static boolean validate_username(String username) { @@ -350,13 +364,11 @@ return false; } - private static void putWelcomeMessage(String username, EmailAddress to) throws IOException { + private static void putWelcomeMessage(FreemailAccount account, EmailAddress to) throws IOException { SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z"); - MessageBank mb = new MessageBank(username); + MailMessage m = account.getMessageBank().createMessage(); - MailMessage m = mb.createMessage(); - m.addHeader("From", "Dave Baker "); m.addHeader("To", to.toString()); m.addHeader("Subject", "Welcome to Freemail!"); Modified: trunk/apps/Freemail/src/freemail/Freemail.java =================================================================== --- trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/Freemail.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -41,7 +41,7 @@ public static final String VERSION_TAG = "Pet Shop"; private static final String TEMPDIRNAME = "temp"; - protected static final String DATADIR = "data"; + protected static final String DEFAULT_DATADIR = "data"; private static final String GLOBALDATADIR = "globaldata"; private static final String ACKDIR = "delayedacks"; protected static final String CFGFILE = "globalconfig"; @@ -57,6 +57,7 @@ private Thread ackInserterThread; private Thread imapThread; + private final AccountManager accountManager; private final ArrayList singleAccountWatcherList = new ArrayList(); private final MessageSender sender; private final SMTPListener smtpl; @@ -70,7 +71,7 @@ configurator.register("loglevel", new Logger(), "normal|error"); - configurator.register("datadir", this, Freemail.DATADIR); + configurator.register("datadir", this, Freemail.DEFAULT_DATADIR); if (!getDataDir().exists()) { if (!getDataDir().mkdir()) { Logger.error(this,"Freemail: Couldn't create data directory. Please ensure that the user you are running Freemail as has write access to its working directory"); @@ -100,15 +101,17 @@ Freemail.fcpconn = new FCPConnection(fcpctx); - sender = new MessageSender(getDataDir()); + accountManager = new AccountManager(datadir); + sender = new MessageSender(accountManager); + File ackdir = new File(getGlobalDataDir(), ACKDIR); AckProcrastinator.setAckDir(ackdir); ackinserter = new AckProcrastinator(); - imapl = new IMAPListener(configurator); - smtpl = new SMTPListener(sender, configurator); + imapl = new IMAPListener(accountManager, configurator); + smtpl = new SMTPListener(accountManager, sender, configurator); } public static File getTempDir() { @@ -126,6 +129,10 @@ public static FCPConnection getFCPConnection() { return Freemail.fcpconn; } + + public AccountManager getAccountManager() { + return accountManager; + } public void setConfigProp(String key, String val) { if (key.equalsIgnoreCase("datadir")) { @@ -158,29 +165,26 @@ imapThread.start(); } + protected void startWorker(FreemailAccount account, boolean daemon) { + SingleAccountWatcher saw = new SingleAccountWatcher(account); + singleAccountWatcherList.add(saw); + Thread t = new Thread(saw, "Freemail Account Watcher for "+account.getUsername()); + t.setDaemon(daemon); + t.start(); + singleAccountWatcherThreadList.add(t); + } + protected void startWorkers(boolean daemon) { System.out.println("This is Freemail version "+VER_MAJOR+"."+VER_MINOR+" build #"+BUILD_NO+" ("+VERSION_TAG+")"); System.out.println("Freemail is released under the terms of the GNU Lesser General Public License. Freemail is provided WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see the LICENSE file included with this distribution."); System.out.println(""); // start a SingleAccountWatcher for each account - File[] files = getDataDir().listFiles(); - for (int i = 0; i < files.length; i++) { - if (files[i].getName().equals(".") || files[i].getName().equals("..")) - continue; - if (!files[i].isDirectory()) continue; - - String invalid=AccountManager.validateUsername(files[i].getName()); - if(!invalid.equals("")) { - Logger.error(this,"Account name "+files[i].getName()+" contains invalid chars (\""+invalid+"\"), you may get problems accessing the account."); - } + Iterator i = accountManager.getAllAccounts().iterator(); + while (i.hasNext()) { + FreemailAccount acc = (FreemailAccount)i.next(); - SingleAccountWatcher saw = new SingleAccountWatcher(files[i]); - singleAccountWatcherList.add(saw); - Thread t = new Thread(saw, "Freemail Account Watcher for "+files[i].getName()); - t.setDaemon(daemon); - t.start(); - singleAccountWatcherThreadList.add(t); + startWorker(acc, daemon); } // start the sender thread Added: trunk/apps/Freemail/src/freemail/FreemailAccount.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailAccount.java (rev 0) +++ trunk/apps/Freemail/src/freemail/FreemailAccount.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -0,0 +1,35 @@ +package freemail; + +import java.io.File; + +import freemail.utils.PropsFile; + +public class FreemailAccount { + private final String username; + private final File accdir; + private final PropsFile accprops; + private final MessageBank mb; + + FreemailAccount(String _username, File _accdir, PropsFile _accprops) { + username = _username; + accdir = _accdir; + accprops = _accprops; + mb = new MessageBank(this); + } + + public String getUsername() { + return username; + } + + public File getAccountDir() { + return accdir; + } + + public PropsFile getProps() { + return accprops; + } + + public MessageBank getMessageBank() { + return mb; + } +} Modified: trunk/apps/Freemail/src/freemail/FreemailCli.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/FreemailCli.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -33,7 +33,7 @@ public static void main(String[] args) { String action = ""; - String account = null; + String username = null; String newpasswd = null; String alias = null; String cfgfile = CFGFILE; @@ -47,7 +47,7 @@ return; } - account = args[i]; + username = args[i]; } else if (args[i].equals("--passwd") || args[i].equals("--password")) { action = "--passwd"; i = i + 2; @@ -55,7 +55,7 @@ System.out.println("Usage: --passwd "); return; } - account = args[i - 1]; + username = args[i - 1]; newpasswd = args[i]; } else if (args[i].equals("--shortaddress")) { action = args[i]; @@ -64,7 +64,7 @@ System.out.println("Usage: --shortaddress "); return; } - account = args[i - 1]; + username = args[i - 1]; alias = args[i]; } else if (args[i].equals("-c")) { i++; @@ -73,6 +73,17 @@ continue; } cfgfile = args[i]; + } else if (args[i].equals("--help") || args[i].equals("-help") || args[i].equals("--h")) { + System.out.println("Usage:"); + System.out.println(" java -jar Freemail.jar [-c config]"); + System.out.println(" Starts the Freemail daemon with config file 'config'"); + System.out.println(" java -jar Freemail.jar [-c config] --newaccount "); + System.out.println(" Creates an account"); + System.out.println(" java -jar Freemail.jar [-c config] --passwd "); + System.out.println(" Changes the password for the given account"); + System.out.println(" java -jar Freemail.jar [-c config] --shortaddress "); + System.out.println(" Adds a short address or changes the short address for the given account."); + return; } else { System.out.println("Unknown option: '"+args[i]+"'"); return; @@ -91,10 +102,10 @@ if (action.equals("--newaccount")) { try { - AccountManager.Create(account); + freemail.getAccountManager().createAccount(username); // by default, we'll not setup NIM now real mode works //AccountManager.setupNIM(account); - System.out.println("Account created for "+account+". You may now set a password with --passwd "); + System.out.println("Account created for "+username+". You may now set a password with --passwd "); //System.out.println("For the time being, you address is "+account+"@nim.freemail"); } catch (IOException ioe) { System.out.println("Couldn't create account. Please check write access to Freemail's working directory. If you want to overwrite your account, delete the appropriate directory manually in 'data' first. Freemail will intentionally not overwrite it. Error: "+ioe.getMessage()); @@ -104,15 +115,17 @@ return; } else if (action.equals("--passwd")) { try { - AccountManager.ChangePassword(account, newpasswd); + FreemailAccount account = freemail.getAccountManager().getAccount(username); + AccountManager.changePassword(account, newpasswd); System.out.println("Password changed."); } catch (Exception e) { - System.out.println("Couldn't change password for "+account+". "+e.getMessage()); + System.out.println("Couldn't change password for "+username+". "+e.getMessage()); e.printStackTrace(); } return; } else if (action.equals("--shortaddress")) { boolean success = false; + FreemailAccount account = freemail.getAccountManager().getAccount(username); try { success = AccountManager.addShortAddress(account, alias); } catch (IllegalArgumentException iae) { Modified: trunk/apps/Freemail/src/freemail/FreemailPlugin.java =================================================================== --- trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/FreemailPlugin.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -22,7 +22,6 @@ package freemail; -import java.io.File; import java.io.IOException; import freenet.pluginmanager.FredPlugin; @@ -90,17 +89,15 @@ if(add.equals("Add account")) { if(!(name.equals("") || password.equals(""))) { try { - AccountManager.Create(name); - AccountManager.ChangePassword(name, password); + FreemailAccount newAccount = getAccountManager().createAccount(name); + AccountManager.changePassword(newAccount, password); boolean tryShortAddress = false; boolean shortAddressWorked = false; if(!domain.equals("")) { tryShortAddress = true; - shortAddressWorked = AccountManager.addShortAddress(name, domain); + shortAddressWorked = AccountManager.addShortAddress(newAccount, domain); } - Thread t = new Thread(new SingleAccountWatcher(new File(DATADIR, name)), "Account Watcher for "+name); - t.setDaemon(true); - t.start(); + startWorker(newAccount, true); HTMLNode successBox = contentNode.addChild("div", "class", "infobox infobox-success"); successBox.addChild("div", "class", "infobox-header", "Account Created"); Modified: trunk/apps/Freemail/src/freemail/MessageBank.java =================================================================== --- trunk/apps/Freemail/src/freemail/MessageBank.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/MessageBank.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -42,8 +42,8 @@ private final File dir; - public MessageBank(String username) { - this.dir = new File(AccountManager.DATADIR + File.separator + username + File.separator + MESSAGES_DIR); + public MessageBank(FreemailAccount account) { + this.dir = new File(account.getAccountDir(), MESSAGES_DIR); if (!this.dir.exists()) { this.dir.mkdir(); @@ -71,7 +71,7 @@ return retval.toString(); } - public boolean delete() { + public synchronized boolean delete() { File[] files = this.dir.listFiles(); for (int i = 0; i < files.length; i++) { @@ -90,7 +90,7 @@ return this.dir.renameTo(newdir); } - public MailMessage createMessage() { + public synchronized MailMessage createMessage() { long newid = this.nextId(); File newfile; try { @@ -112,7 +112,7 @@ return null; } - public SortedMap listMessages() { + public synchronized SortedMap listMessages() { File[] files = this.dir.listFiles(new MessageFileNameFilter()); Arrays.sort(files, new UIDComparator()); @@ -131,7 +131,7 @@ return msgs; } - public MailMessage[] listMessagesArray() { + public synchronized MailMessage[] listMessagesArray() { File[] files = this.dir.listFiles(new MessageFileNameFilter()); Arrays.sort(files, new UIDComparator()); @@ -159,7 +159,7 @@ return new MessageBank(targetdir); } - public MessageBank makeSubFolder(String name) { + public synchronized MessageBank makeSubFolder(String name) { if (!name.matches("[\\w\\s_]*")) return null; File targetdir = new File(this.dir, name); @@ -183,7 +183,7 @@ return null; } - public MessageBank[] listSubFolders() { + public synchronized MessageBank[] listSubFolders() { File[] files = this.dir.listFiles(); Vector subfolders = new Vector(); @@ -206,7 +206,7 @@ return retval; } - private long nextId() { + private synchronized long nextId() { File nidfile = new File(this.dir, NIDFILE); long retval; @@ -225,7 +225,7 @@ return retval; } - private void writeNextId(long newid) { + private synchronized void writeNextId(long newid) { // write the new ID to a temporary file File nidfile = new File(this.dir, NIDTMPFILE); try { Modified: trunk/apps/Freemail/src/freemail/MessageSender.java =================================================================== --- trunk/apps/Freemail/src/freemail/MessageSender.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/MessageSender.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -25,6 +25,7 @@ import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.IOException; +import java.util.Iterator; import java.util.Vector; import java.util.Enumeration; @@ -44,17 +45,16 @@ private static final int MIN_RUN_TIME = 60000; public static final String NIM_KEY_PREFIX = "KSK at freemail-nim-"; private static final int MAX_TRIES = 10; - private final File datadir; + private final AccountManager accountManager; private Thread senderthread = null; private static final String ATTR_SEP_CHAR = "_"; - public MessageSender(File d) { - this.datadir = d; + public MessageSender(AccountManager accMgr) { + accountManager = accMgr; } - public void send_message(String from_user, Vector to, File msg) throws IOException { - File user_dir = new File(this.datadir, from_user); - File outbox = new File(user_dir, OUTBOX_DIR); + public void sendMessage(FreemailAccount fromAccount, Vector to, File msg) throws IOException { + File outbox = new File(fromAccount.getAccountDir(), OUTBOX_DIR); Enumeration e = to.elements(); while (e.hasMoreElements()) { @@ -103,32 +103,24 @@ long start = System.currentTimeMillis(); // iterate through users - File[] files = this.datadir.listFiles(); - for (int i = 0; i < files.length; i++) { - if(stopping) { - break; - } - if (files[i].getName().startsWith(".")) - continue; - File outbox = new File(files[i], OUTBOX_DIR); - if (!outbox.exists()) - outbox.mkdir(); + Iterator i = accountManager.getAllAccounts().iterator(); + while (i.hasNext()) { + if(stopping) break; + FreemailAccount acc = (FreemailAccount)i.next(); + File outbox = new File(acc.getAccountDir(), OUTBOX_DIR); + if (!outbox.exists()) outbox.mkdir(); + try { - this.sendDir(files[i], outbox); + this.sendDir(acc, outbox); } catch (ConnectionTerminatedException cte) { return; } } - // don't spin around the loop if nothing's - // going on - if(stopping) { - break; - } long runtime = System.currentTimeMillis() - start; - if (MIN_RUN_TIME - runtime > 0) { + if (MIN_RUN_TIME - runtime > 0 && !stopping) { try { Thread.sleep(MIN_RUN_TIME - runtime); } catch (InterruptedException ie) { @@ -145,18 +137,18 @@ if (senderthread != null) senderthread.interrupt(); } - private void sendDir(File accdir, File dir) throws ConnectionTerminatedException { + private void sendDir(FreemailAccount fromAccount, File dir) throws ConnectionTerminatedException { File[] files = dir.listFiles(); if (dir == null) return; for (int i = 0; i < files.length; i++) { if (files[i].getName().startsWith(".")) continue; - this.sendSingle(accdir, files[i]); + this.sendSingle(fromAccount, files[i]); } } - private void sendSingle(File accdir, File msg) throws ConnectionTerminatedException { + private void sendSingle(FreemailAccount fromAccount, File msg) throws ConnectionTerminatedException { String parts[] = msg.getName().split(ATTR_SEP_CHAR, 3); EmailAddress addr; int tries; @@ -185,12 +177,14 @@ // just don't delete the message } } else { - if (this.sendSecure(accdir, addr, msg)) { + if (this.sendSecure(fromAccount, addr, msg)) { msg.delete(); } else { tries++; if (tries > MAX_TRIES) { - if (Postman.bounceMessage(msg, new MessageBank(accdir.getName()), "Tried too many times to deliver this message, but it doesn't apear that this address even exists. If you're sure that it does, check your Freenet connection.")) { + if (Postman.bounceMessage(msg, fromAccount.getMessageBank(), + "Tried too many times to deliver this message, but it doesn't apear that this address even exists. " + +"If you're sure that it does, check your Freenet connection.")) { msg.delete(); } } else { @@ -200,17 +194,17 @@ } } - private boolean sendSecure(File accdir, EmailAddress addr, File msg) throws ConnectionTerminatedException { + private boolean sendSecure(FreemailAccount fromAccount, EmailAddress addr, File msg) throws ConnectionTerminatedException { Logger.normal(this,"sending secure"); OutboundContact ct; try { - ct = new OutboundContact(accdir, addr); + ct = new OutboundContact(fromAccount, addr); } catch (BadFreemailAddressException bfae) { // bounce - return Postman.bounceMessage(msg, new MessageBank(accdir.getName()), "The address that this message was destined for ("+addr+") is not a valid Freemail address."); + return Postman.bounceMessage(msg, fromAccount.getMessageBank(), "The address that this message was destined for ("+addr+") is not a valid Freemail address."); } catch (OutboundContactFatalException obfe) { // bounce - return Postman.bounceMessage(msg, new MessageBank(accdir.getName()), obfe.getMessage()); + return Postman.bounceMessage(msg, fromAccount.getMessageBank(), obfe.getMessage()); } catch (IOException ioe) { // couldn't get the mailsite - try again if you're not ready //to give up yet Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -62,7 +62,7 @@ public class OutboundContact { public static final String OUTBOX_DIR = "outbox"; private final PropsFile contactfile; - private final File accdir; + private final FreemailAccount account; private final File ctoutbox; private final EmailAddress address; // how long to wait for a CTS before sending the message again @@ -80,17 +80,17 @@ // we read 128 bytes for our IV, so it needs to be constant.) private static final int AES_BLOCK_LENGTH = 128 / 8; - public OutboundContact(File accdir, EmailAddress a) throws BadFreemailAddressException, IOException, + public OutboundContact(FreemailAccount acc, EmailAddress a) throws BadFreemailAddressException, IOException, OutboundContactFatalException, ConnectionTerminatedException { this.address = a; - this.accdir = accdir; + this.account = acc; if (!this.address.is_freemail_address()) { this.contactfile = null; throw new BadFreemailAddressException(); } else { - File contactsdir = new File(accdir, SingleAccountWatcher.CONTACTS_DIR); + File contactsdir = new File(account.getAccountDir(), SingleAccountWatcher.CONTACTS_DIR); if (!contactsdir.exists()) contactsdir.mkdir(); File outbounddir = new File(contactsdir, SingleAccountWatcher.OUTBOUND_DIR); @@ -125,8 +125,8 @@ } } - public OutboundContact(File accdir, File ctdir) { - this.accdir = accdir; + public OutboundContact(FreemailAccount acc, File ctdir) { + this.account = acc; this.address = new EmailAddress(); this.address.domain = ctdir.getName()+".freemail"; @@ -319,7 +319,7 @@ rtsmessage.append("to="+this.address.getSubDomain()+"\r\n"); // get our mailsite URI - String our_mailsite_uri = AccountManager.getAccountFile(this.accdir).get("mailsite.pubkey"); + String our_mailsite_uri = account.getProps().get("mailsite.pubkey"); rtsmessage.append("mailsite="+our_mailsite_uri+"\r\n"); @@ -332,7 +332,7 @@ byte[] hash = new byte[sha256.getDigestSize()]; sha256.doFinal(hash, 0); - RSAKeyParameters our_priv_key = AccountManager.getPrivateKey(this.accdir); + RSAKeyParameters our_priv_key = AccountManager.getPrivateKey(account.getProps()); AsymmetricBlockCipher sigcipher = new RSAEngine(); sigcipher.init(true, our_priv_key); @@ -609,7 +609,10 @@ if (!ready) { if (msgs[i].added_time + FAIL_DELAY < System.currentTimeMillis()) { - if (Postman.bounceMessage(msgs[i].getMessageFile(), new MessageBank(this.accdir.getName()), "Freemail has been trying to establish a communication channel with this party for too long without success. Check that the Freemail address is valid, and that the recipient still runs Freemail on at least a semi-regular basis.", true)) { + if (Postman.bounceMessage(msgs[i].getMessageFile(), account.getMessageBank(), + "Freemail has been trying to establish a communication channel with this party for too long " + +"without success. Check that the Freemail address is valid, and that the recipient still runs " + +"Freemail on at least a semi-regular basis.", true)) { msgs[i].delete(); } } @@ -650,7 +653,9 @@ msgs[i].saveProps(); } else if (msgs[i].added_time + FAIL_DELAY < System.currentTimeMillis()) { Logger.normal(this,"Giving up on a message - been trying to send for too long. Bouncing."); - if (Postman.bounceMessage(msgs[i].getMessageFile(), new MessageBank(this.accdir.getName()), "Freemail has been trying to deliver this message for too long without success. This is likley to be due to a poor connection to Freenet. Check your Freenet node.", true)) { + if (Postman.bounceMessage(msgs[i].getMessageFile(), account.getMessageBank(), + "Freemail has been trying to deliver this message for too long without success. " + +"This is likley to be due to a poor connection to Freenet. Check your Freenet node.", true)) { msgs[i].delete(); } } else { @@ -695,7 +700,10 @@ // give up and bounce the message File m = msgs[i].getMessageFile(); - Postman.bounceMessage(m, new MessageBank(this.accdir.getName()), "Freemail has been trying for too long to deliver this message, and has received no acknowledgement. It is possible that the recipient has not run Freemail since you sent the message. If you believe this is likely, try resending the message.", true); + Postman.bounceMessage(m, account.getMessageBank(), + "Freemail has been trying for too long to deliver this message, and has received no acknowledgement. " + +"It is possible that the recipient has not run Freemail since you sent the message. " + +"If you believe this is likely, try resending the message.", true); Logger.normal(this,"Giving up on message - been trying for too long."); msgs[i].delete(); } else if (System.currentTimeMillis() > msgs[i].last_send_time + RETRANSMIT_DELAY) { Modified: trunk/apps/Freemail/src/freemail/RTSFetcher.java =================================================================== --- trunk/apps/Freemail/src/freemail/RTSFetcher.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/RTSFetcher.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -67,14 +67,12 @@ private static final int RTS_MAX_SIZE = 2 * 1024 * 1024; private static final String RTS_UNPROC_PREFIX = "unprocessed_rts"; private static final int RTS_MAX_ATTEMPTS = 15; - private File accdir; - private PropsFile accprops; + private FreemailAccount account; - RTSFetcher(String key, File ctdir, File ad) { + RTSFetcher(String key, File ctdir, FreemailAccount acc) { this.rtskey = key; this.contact_dir = ctdir; - this.accdir = ad; - this.accprops = AccountManager.getAccountFile(this.accdir); + this.account = acc; } public void poll() throws ConnectionTerminatedException { @@ -357,7 +355,7 @@ // Now verify the message is for us String our_mailsite_keybody; try { - our_mailsite_keybody = new FreenetURI(this.accprops.get("mailsite.pubkey")).getKeyBody(); + our_mailsite_keybody = new FreenetURI(account.getProps().get("mailsite.pubkey")).getKeyBody(); } catch (MalformedURLException mfue) { Logger.normal(this,"Local mailsite URI is invalid! Corrupt account file?"); msfile.delete(); @@ -365,7 +363,7 @@ return false; } - String our_domain_alias = this.accprops.get("domain_alias"); + String our_domain_alias = account.getProps().get("domain_alias"); FreenetURI mailsite_furi; try { mailsite_furi = new FreenetURI(our_mailsite_keybody); @@ -407,7 +405,7 @@ private byte[] decrypt_rts(File rtsmessage) throws IOException, InvalidCipherTextException { // initialise our ciphers - RSAKeyParameters ourprivkey = AccountManager.getPrivateKey(this.accdir); + RSAKeyParameters ourprivkey = AccountManager.getPrivateKey(account.getProps()); AsymmetricBlockCipher deccipher = new RSAEngine(); deccipher.init(false, ourprivkey); Modified: trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java =================================================================== --- trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/SingleAccountWatcher.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -25,7 +25,6 @@ import java.io.FilenameFilter; import java.lang.InterruptedException; -import freemail.utils.PropsFile; import freemail.fcp.ConnectionTerminatedException; import freemail.utils.Logger; @@ -40,19 +39,16 @@ public static final String OUTBOUND_DIR = "outbound"; private static final int MIN_POLL_DURATION = 60000; // in milliseconds private static final int MAILSITE_UPLOAD_INTERVAL = 60 * 60 * 1000; - private final MessageBank mb; private final NIMFetcher nf; private final RTSFetcher rtsf; private long mailsite_last_upload; - private final PropsFile accprops; private final File obctdir; private final File ibctdir; - private final File accdir; + private final FreemailAccount account; - SingleAccountWatcher(File accdir) { - this.accdir = accdir; - this.accprops = AccountManager.getAccountFile(accdir); - File contacts_dir = new File(accdir, CONTACTS_DIR); + SingleAccountWatcher(FreemailAccount acc) { + this.account = acc; + File contacts_dir = new File(account.getAccountDir(), CONTACTS_DIR); if (!contacts_dir.exists()) { contacts_dir.mkdir(); @@ -66,34 +62,32 @@ this.ibctdir.mkdir(); } - this.mb = new MessageBank(accdir.getName()); - File nimdir = new File(contacts_dir, AccountManager.NIMDIR); if (nimdir.exists()) { - this.nf = new NIMFetcher(this.mb, nimdir); + this.nf = new NIMFetcher(account.getMessageBank(), nimdir); } else { this.nf = null; } - String rtskey=this.accprops.get("rtskey"); + String rtskey=account.getProps().get("rtskey"); if(rtskey==null) { Logger.error(this,"Your accprops file is missing the rtskey entry. This means it is broken, you will not be able to receive new contact requests."); } - this.rtsf = new RTSFetcher("KSK@"+rtskey+"-", this.ibctdir, accdir); + this.rtsf = new RTSFetcher("KSK@"+rtskey+"-", this.ibctdir, account); //this.mf = new MailFetcher(this.mb, inbound_dir, Freemail.getFCPConnection()); // temporary info message until there's a nicer UI :) - String freemailDomain=AccountManager.getFreemailDomain(accdir); + String freemailDomain=AccountManager.getFreemailDomain(account.getProps()); if(freemailDomain!=null) { - Logger.normal(this,"Secure Freemail address: @"+AccountManager.getFreemailDomain(accdir)); + Logger.normal(this,"Secure Freemail address: @"+AccountManager.getFreemailDomain(account.getProps())); } else { Logger.error(this, "You do not have a freemail address USK. This account is really broken."); } - String shortdomain = AccountManager.getKSKFreemailDomain(accdir); + String shortdomain = AccountManager.getKSKFreemailDomain(account.getProps()); if (shortdomain != null) { Logger.normal(this,"Short Freemail address (*probably* secure): @"+shortdomain); @@ -113,7 +107,7 @@ // is it time we inserted the mailsite? if (System.currentTimeMillis() > this.mailsite_last_upload + MAILSITE_UPLOAD_INTERVAL) { - MailSite ms = new MailSite(this.accprops); + MailSite ms = new MailSite(account.getProps()); if (ms.Publish() > 0) { this.mailsite_last_upload = System.currentTimeMillis(); } @@ -126,7 +120,7 @@ if (obcontacts != null) { int i; for (i = 0; i < obcontacts.length; i++) { - OutboundContact obct = new OutboundContact(this.accdir, obcontacts[i]); + OutboundContact obct = new OutboundContact(account, obcontacts[i]); obct.doComm(); } @@ -148,7 +142,7 @@ InboundContact ibct = new InboundContact(this.ibctdir, ibcontacts[i].getName()); - ibct.fetch(this.mb); + ibct.fetch(account.getMessageBank()); } } if(stopping) { Modified: trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java =================================================================== --- trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -34,6 +34,7 @@ import java.text.SimpleDateFormat; import java.util.Date; +import freemail.FreemailAccount; import freemail.MessageBank; import freemail.MailMessage; import freemail.AccountManager; @@ -48,10 +49,11 @@ private final BufferedReader bufrdr; private MessageBank mb; private MessageBank inbox; - + private final AccountManager accountManager; - IMAPHandler(Socket client) throws IOException { + IMAPHandler(AccountManager accMgr, Socket client) throws IOException { super(client); + accountManager = accMgr; this.os = client.getOutputStream(); this.ps = new PrintStream(this.os); this.bufrdr = new BufferedReader(new InputStreamReader(client.getInputStream())); @@ -135,8 +137,9 @@ return; } - if (AccountManager.authenticate(trimQuotes(msg.args[0]), trimQuotes(msg.args[1]))) { - this.inbox = new MessageBank(trimQuotes(msg.args[0])); + FreemailAccount account = accountManager.authenticate(trimQuotes(msg.args[0]), trimQuotes(msg.args[1])); + if (account != null) { + this.inbox = account.getMessageBank(); this.reply(msg, "OK Logged in"); } else { Modified: trunk/apps/Freemail/src/freemail/imap/IMAPListener.java =================================================================== --- trunk/apps/Freemail/src/freemail/imap/IMAPListener.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/imap/IMAPListener.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -26,6 +26,7 @@ import java.net.SocketTimeoutException; import java.io.IOException; +import freemail.AccountManager; import freemail.ServerListener; import freemail.config.Configurator; import freemail.config.ConfigClient; @@ -35,8 +36,10 @@ private static final int LISTENPORT = 3143; private String bindaddress; private int bindport; + private final AccountManager accountManager; - public IMAPListener(Configurator cfg) { + public IMAPListener(AccountManager accMgr, Configurator cfg) { + accountManager = accMgr; cfg.register("imap_bind_address", this, "127.0.0.1"); cfg.register("imap_bind_port", this, Integer.toString(LISTENPORT)); } @@ -62,7 +65,7 @@ sock.setSoTimeout(60000); while (!sock.isClosed()) { try { - IMAPHandler newcli = new IMAPHandler(sock.accept()); + IMAPHandler newcli = new IMAPHandler(accountManager, sock.accept()); Thread newthread = new Thread(newcli); newthread.setDaemon(true); newthread.start(); Modified: trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java =================================================================== --- trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/smtp/SMTPHandler.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -34,6 +34,7 @@ import freemail.Freemail; import freemail.AccountManager; +import freemail.FreemailAccount; import freemail.MessageSender; import freemail.ServerHandler; import freemail.utils.EmailAddress; @@ -44,16 +45,19 @@ private final OutputStream os; private final PrintStream ps; private final BufferedReader bufrdr; - private String username; + private FreemailAccount account; private final MessageSender msgsender; public static final String MY_HOSTNAME = "localhost"; + private final AccountManager accountmanager; + private Vector to; - public SMTPHandler(Socket client, MessageSender sender) throws IOException { + public SMTPHandler(AccountManager accMgr, Socket client, MessageSender sender) throws IOException { super(client); + accountmanager = accMgr; this.msgsender = sender; - this.username = null; + this.account = null; this.os = client.getOutputStream(); this.ps = new PrintStream(this.os); this.bufrdr = new BufferedReader(new InputStreamReader(client.getInputStream())); @@ -196,9 +200,8 @@ return; } - if (AccountManager.authenticate(uname, password)) { - this.username = uname; - + account = accountmanager.authenticate(uname, password); + if (account != null) { this.ps.print("235 Authenticated\r\n"); } else { this.ps.print("535 Authentication failed\r\n"); @@ -206,7 +209,7 @@ } private void handle_mail(SMTPCommand cmd) { - if (this.username == null) { + if (this.account == null) { this.ps.print("530 Authentication required\r\n"); return; } @@ -221,7 +224,7 @@ return; } - if (this.username == null) { + if (this.account == null) { this.ps.print("530 Authentication required\r\n"); return; } @@ -255,7 +258,7 @@ } private void handle_data(SMTPCommand cmd) { - if (this.username == null) { + if (this.account == null) { this.ps.print("530 Authentication required\r\n"); return; } @@ -289,7 +292,7 @@ return; } - this.msgsender.send_message(this.username, to, tempfile); + this.msgsender.sendMessage(this.account, to, tempfile); tempfile.delete(); Modified: trunk/apps/Freemail/src/freemail/smtp/SMTPListener.java =================================================================== --- trunk/apps/Freemail/src/freemail/smtp/SMTPListener.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/smtp/SMTPListener.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -25,6 +25,7 @@ import java.net.InetAddress; import java.io.IOException; +import freemail.AccountManager; import freemail.MessageSender; import freemail.ServerListener; import freemail.config.ConfigClient; @@ -36,9 +37,11 @@ private final MessageSender msgsender; private String bindaddress; private int bindport; + private final AccountManager accountManager; - public SMTPListener(MessageSender sender, Configurator cfg) { + public SMTPListener(AccountManager accMgr, MessageSender sender, Configurator cfg) { this.msgsender = sender; + this.accountManager = accMgr; cfg.register("smtp_bind_address", this, "127.0.0.1"); cfg.register("smtp_bind_port", this, Integer.toString(LISTENPORT)); } @@ -63,7 +66,7 @@ sock = new ServerSocket(this.bindport, 10, InetAddress.getByName(this.bindaddress)); while (!sock.isClosed()) { try { - SMTPHandler newcli = new SMTPHandler(sock.accept(), this.msgsender); + SMTPHandler newcli = new SMTPHandler(accountManager, sock.accept(), this.msgsender); Thread newthread = new Thread(newcli); newthread.setDaemon(true); newthread.start(); Modified: trunk/apps/Freemail/src/freemail/utils/PropsFile.java =================================================================== --- trunk/apps/Freemail/src/freemail/utils/PropsFile.java 2008-04-13 18:43:55 UTC (rev 19269) +++ trunk/apps/Freemail/src/freemail/utils/PropsFile.java 2008-04-13 20:26:19 UTC (rev 19270) @@ -69,7 +69,7 @@ this.header = hdr; } - private BufferedReader read(boolean stopAtBlank) throws IOException { + private synchronized BufferedReader read(boolean stopAtBlank) throws IOException { this.data = new HashMap(); BufferedReader br = new BufferedReader(new FileReader(this.file)); @@ -103,7 +103,7 @@ } } - private void write() throws IOException { + private synchronized void write() throws IOException { PrintWriter pw = new PrintWriter(new FileOutputStream(this.file)); if (this.header != null) pw.println(this.header); From dbkr at freenetproject.org Sun Apr 20 20:17:14 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 20 Apr 2008 20:17:14 +0000 (UTC) Subject: [Freemail] r19465 - trunk/apps/Freemail/src/freemail/utils Message-ID: <20080420201714.33EE7479A9E@freenetproject.org> Author: dbkr Date: 2008-04-20 20:17:13 +0000 (Sun, 20 Apr 2008) New Revision: 19465 Modified: trunk/apps/Freemail/src/freemail/utils/Logger.java Log: Timestamp log messages. Log to stderr rather than stdout. Modified: trunk/apps/Freemail/src/freemail/utils/Logger.java =================================================================== --- trunk/apps/Freemail/src/freemail/utils/Logger.java 2008-04-20 17:26:25 UTC (rev 19464) +++ trunk/apps/Freemail/src/freemail/utils/Logger.java 2008-04-20 20:17:13 UTC (rev 19465) @@ -10,6 +10,8 @@ package freemail.utils; import java.lang.NoClassDefFoundError; +import java.text.SimpleDateFormat; +import java.util.Date; import freemail.config.ConfigClient; @@ -28,6 +30,8 @@ //static final private int loglevel=DEBUG|NORMAL|ERROR; static private int loglevel=NORMAL|ERROR; // should be ok for normal users + static private SimpleDateFormat logDateFormat = new SimpleDateFormat("d/MM/yyyy HH:mm:ss"); + public void setConfigProp(String key, String val) { if (key.equals("loglevel")) { String[] levels = val.split("\\s*\\|\\s*"); @@ -66,14 +70,12 @@ } static private void log(int l, Object o, String s, String level) { - if((l&loglevel)!=0) { - System.out.println(level+"("+o.getClass().getName()+"): "+s); - } + log(l, o.getClass(), s, level); } - static private void log(int l, Class c, String s, String level) { + static private synchronized void log(int l, Class c, String s, String level) { if((l&loglevel)!=0) { - System.out.println(level+"("+c.getName()+"): "+s); + System.err.println(logDateFormat.format(new Date())+" "+level+"("+c.getName()+"): "+s); } } From dbkr at freenetproject.org Sun Apr 20 21:43:41 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Sun, 20 Apr 2008 21:43:41 +0000 (UTC) Subject: [Freemail] r19467 - trunk/apps/Freemail/src/freemail Message-ID: <20080420214341.1F92640188E@freenetproject.org> Author: dbkr Date: 2008-04-20 21:43:40 +0000 (Sun, 20 Apr 2008) New Revision: 19467 Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java Log: Make comment clearer Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-20 21:10:24 UTC (rev 19466) +++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-20 21:43:40 UTC (rev 19467) @@ -65,7 +65,7 @@ private final FreemailAccount account; private final File ctoutbox; private final EmailAddress address; - // how long to wait for a CTS before sending the message again + // how long to wait for a CTS before sending the RTS again // slightly over 24 hours since some people are likely to fire Freemail // up and roughly the same time every day private static final long CTS_WAIT_TIME = 26 * 60 * 60 * 1000; From dbkr at freenetproject.org Tue Apr 22 22:38:33 2008 From: dbkr at freenetproject.org (dbkr at freenetproject.org) Date: Tue, 22 Apr 2008 22:38:33 +0000 (UTC) Subject: [Freemail] r19505 - in trunk/apps/Freemail/src/freemail: . fcp Message-ID: <20080422223833.7E5BC47B2D6@freenetproject.org> Author: dbkr Date: 2008-04-22 22:38:33 +0000 (Tue, 22 Apr 2008) New Revision: 19505 Added: trunk/apps/Freemail/src/freemail/fcp/FCPFetchException.java Modified: trunk/apps/Freemail/src/freemail/InboundContact.java trunk/apps/Freemail/src/freemail/NIMFetcher.java trunk/apps/Freemail/src/freemail/OutboundContact.java trunk/apps/Freemail/src/freemail/RTSFetcher.java trunk/apps/Freemail/src/freemail/SlotManager.java trunk/apps/Freemail/src/freemail/fcp/HighLevelFCPClient.java Log: Change FCP API so fetches throw exceptions on failure. More checking of fetch failure codes, especially when fetching RTS messages. Ignore RTS slots whose fetches have produced fatal errors. Modified: trunk/apps/Freemail/src/freemail/InboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/InboundContact.java 2008-04-22 21:37:38 UTC (rev 19504) +++ trunk/apps/Freemail/src/freemail/InboundContact.java 2008-04-22 22:38:33 UTC (rev 19505) @@ -34,6 +34,7 @@ import freemail.utils.PropsFile; import freemail.utils.EmailAddress; import freemail.utils.Logger; +import freemail.fcp.FCPFetchException; import freemail.fcp.HighLevelFCPClient; import freemail.fcp.ConnectionTerminatedException; @@ -106,9 +107,9 @@ msg = fcpcli.fetch(key); } catch (ConnectionTerminatedException cte) { return; - } - if (msg == null) { - Logger.minor(this,"No mail there."); + } catch (FCPFetchException fe) { + // XXX: Slot should be marked dead if this is a fatal error + Logger.minor(this,"No mail in slot (fetch returned "+fe.getMessage()+")"); continue; } Logger.normal(this,"Found a message!"); @@ -212,14 +213,15 @@ if (sd.indexOf("\r") > 0 || sd.indexOf("\n") > 0) return false; Logger.normal(this,"Attempting to fetch sender's mailsite to validate From address..."); - File result = cli.fetch("KSK@"+sd+MailSite.ALIAS_SUFFIX); - - if (result == null) { + File result; + try { + result = cli.fetch("KSK@"+sd+MailSite.ALIAS_SUFFIX); + } catch (FCPFetchException fe) { // we just received the message so we can assume our // network connection is healthy, and the mailsite // ought to be easily retrievable, so fail. // If this proves to be an issue, change it. - Logger.error(this,"Failed to fetch sender's mailsite. Sender's From address therefore not valid."); + Logger.error(this,"Failed to fetch sender's mailsite ("+fe.getMessage()+"). Sender's From address therefore not valid."); return false; } Logger.normal(this,"Fetched sender's mailsite"); Modified: trunk/apps/Freemail/src/freemail/NIMFetcher.java =================================================================== --- trunk/apps/Freemail/src/freemail/NIMFetcher.java 2008-04-22 21:37:38 UTC (rev 19504) +++ trunk/apps/Freemail/src/freemail/NIMFetcher.java 2008-04-22 22:38:33 UTC (rev 19505) @@ -21,6 +21,7 @@ package freemail; +import freemail.fcp.FCPFetchException; import freemail.fcp.HighLevelFCPClient; import freemail.fcp.ConnectionTerminatedException; import freemail.utils.DateStringFactory; @@ -87,19 +88,21 @@ for (int i = startnum; i < startnum + POLL_AHEAD; i++) { Logger.normal(this,"trying to fetch "+keybase+i); - File result = fcpcli.fetch(keybase+i); + File result; + try { + result = fcpcli.fetch(keybase+i); + } catch (FCPFetchException fe) { + Logger.normal(this,keybase+i+": no message ("+fe.getMessage()+")."); + continue; + } - if (result != null) { - Logger.normal(this,keybase+i+": got message!"); - try { - this.storeMessage(new BufferedReader(new FileReader(result)), this.mb); - result.delete(); - log.addMessage(i, "received"); - } catch (IOException ioe) { - continue; - } - } else { - Logger.normal(this,keybase+i+": no message."); + Logger.normal(this,keybase+i+": got message!"); + try { + this.storeMessage(new BufferedReader(new FileReader(result)), this.mb); + result.delete(); + log.addMessage(i, "received"); + } catch (IOException ioe) { + continue; } } } Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java =================================================================== --- trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-22 21:37:38 UTC (rev 19504) +++ trunk/apps/Freemail/src/freemail/OutboundContact.java 2008-04-22 22:38:33 UTC (rev 19505) @@ -37,6 +37,7 @@ import freemail.utils.EmailAddress; import freemail.utils.PropsFile; import freemail.utils.DateStringFactory; +import freemail.fcp.FCPFetchException; import freemail.fcp.HighLevelFCPClient; import freemail.fcp.FCPInsertErrorMessage; import freemail.fcp.FCPBadFileException; @@ -170,9 +171,15 @@ HighLevelFCPClient fcpcli = new HighLevelFCPClient(); Logger.minor(this,"polling for CTS message: "+ctskey); - File cts = fcpcli.fetch(ctskey); - - if (cts == null) { + try { + File cts = fcpcli.fetch(ctskey); + + Logger.normal(this,"Sucessfully received CTS for "+this.address.getSubDomain()); + cts.delete(); + this.contactfile.put("status", "cts-received"); + // delete initial slot for forward secrecy + this.contactfile.remove("initialslot"); + } catch (FCPFetchException fe) { Logger.minor(this,"CTS not received"); // haven't got the CTS message. should we give up yet? String senttime = this.contactfile.get("rts-sent-at"); @@ -181,13 +188,6 @@ // yes, send another RTS this.init(); } - - } else { - Logger.normal(this,"Sucessfully received CTS for "+this.address.getSubDomain()); - cts.delete(); - this.contactfile.put("status", "cts-received"); - // delete initial slot for forward secrecy - this.contactfile.remove("initialslot"); } } else { this.init(); @@ -436,10 +436,11 @@ HighLevelFCPClient cli = new HighLevelFCPClient(); Logger.normal(this,"Attempting to fetch mailsite redirect "+key); - File result = cli.fetch(key); - - if (result == null) { - Logger.normal(this,"Failed to retrieve mailsite redirect "+key); + File result; + try { + result = cli.fetch(key); + } catch (FCPFetchException fe) { + Logger.normal(this,"Failed to retrieve mailsite redirect "+key+" ("+fe.getMessage()+")"); return null; } @@ -472,9 +473,10 @@ HighLevelFCPClient cli = new HighLevelFCPClient(); Logger.normal(this,"Attempting to fetch "+this.address.getMailpageKey()); - File mailsite_file = cli.fetch(this.address.getMailpageKey()); - - if (mailsite_file == null) { + File mailsite_file; + try { + mailsite_file = cli.fetch(this.address.getMailpageKey()); + } catch (FCPFetchException fe) { Logger.normal(this,"Failed to retrieve mailsite "+this.address.getMailpageKey()); return false; } @@ -698,8 +700,8 @@ Logger.minor(this,"Looking for message ack on "+key); - File ack = fcpcli.fetch(key); - if (ack != null) { + try { + File ack = fcpcli.fetch(key); Logger.normal(this,"Ack received for message "+msgs[i].uid+" on contact "+this.address.domain+". Now that's a job well done."); ack.delete(); msgs[i].delete(); @@ -707,24 +709,26 @@ this.contactfile.put("status", "cts-received"); // delete initial slot for forward secrecy this.contactfile.remove("initialslot"); - } else { - Logger.minor(this,"Failed to receive ack on "+key); - if (System.currentTimeMillis() > msgs[i].first_send_time + FAIL_DELAY) { - // give up and bounce the message - File m = msgs[i].getMessageFile(); - - Postman.bounceMessage(m, account.getMessageBank(), - "Freemail has been trying for too long to deliver this message, and has received no acknowledgement. " - +"It is possible that the recipient has not run Freemail since you sent the message. " - +"If you believe this is likely, try resending the message.", true); - Logger.normal(this,"Giving up on message - been trying for too long."); - msgs[i].delete(); - } else if (System.currentTimeMillis() > msgs[i].last_send_time + RETRANSMIT_DELAY) { - // no ack yet - retransmit on another slot - msgs[i].slot = this.popNextSlot(); - // mark for re-insertion - msgs[i].last_send_time = -1; - msgs[i].saveProps(); + } catch (FCPFetchException fe) { + Logger.minor(this,"Failed to receive ack on "+key+" ("+fe.getMessage()+")"); + if (!fe.isNetworkError()) { + if (System.currentTimeMillis() > msgs[i].first_send_time + FAIL_DELAY) { + // give up and bounce the message + File m = msgs[i].getMessageFile(); + + Postman.bounceMessa