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/*<String, FreemailAccount>*/ 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/*<FreemailAccount>*/ 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 <nowhere at
dontreply>");
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 <dave at dbkr.freemail>");
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
<account name> <password>");
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 <name> <domain prefix>");
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 <account name>");
+ System.out.println(" Creates an account");
+ System.out.println(" java -jar Freemail.jar [-c
config] --passwd <account name> <password>");
+ System.out.println(" Changes the password for
the given account");
+ System.out.println(" java -jar Freemail.jar [-c
config] --shortaddress <name> <domain prefix>");
+ 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 <username> <password>");
+ System.out.println("Account created for
"+username+". You may now set a password with --passwd <username> <password>");
//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:
<anything>@"+AccountManager.getFreemailDomain(accdir));
+ Logger.normal(this,"Secure Freemail address:
<anything>@"+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): <anything>@"+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);