public class Main implements Listener {
public void accept(Connection conn) {
- Log.error(this, "connection port is " + conn.getLocalPort());
- if (conn.getLocalPort() == 25) {
- new SMTP.Server().handleRequest(conn);
- } else if (conn.getLocalPort() == 143) {
- new IMAP.Listener().handleRequest(conn);
+ try {
+ if (conn.getLocalPort() == 25) new SMTP.Server().handleRequest(conn);
+ else if (conn.getLocalPort() == 143) new IMAP.Listener(auth).handleRequest(conn);
+ else if (conn.getLocalPort() == 119) new NNTP.Listener(auth).handleRequest(conn);
+ } finally {
+ conn.close();
+ }
+ }
+
+ private static final Auth auth = new Auth();
+ private static class Auth implements Login {
+ final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT, true).slash("user", true);
+ public Account anonymous() { return null; }
+ public Account login(String user, String pass) {
+ if (!EtcPasswd.verify(user, pass)) return null;
+ return new Account(user, null, root.slash(user, true)){
+ public Mailbox getMailbox(Class protocol) {
+ if (protocol == NNTP.class) {
+ final Mailbox arch = new MailmanArchives();
+ return new Mailbox.Default() {
+ public void add(Message m) { throw new RuntimeException("not supported"); }
+ public void add(Message m, int i) { throw new RuntimeException("not supported"); }
+ public int uidValidity() { return 1; }
+ public Mailbox.Iterator iterator() { return null; }
+ public int uidNext() { return 0; }
+ public String[] children() { return new String[] { "us" }; }
+ public Mailbox slash(String name, boolean create) { return arch; }
+ };
+ } else {
+ return super.getMailbox(protocol);
+ }
+ }
+ };
}
}
public void fetch(Query q, int spec, String[] headers, int start, int end, boolean uid);
public void lsub(String start, String ref);
public void list(String start, String ref);
- public static interface Authenticator { public abstract Mailbox authenticate(String user, String pass); }
public static class Exn extends MailException { public Exn(String s) { super(s); } }
public static class Bad extends Exn { public Bad(String s) { super(s); } }
public static class No extends Exn { public No(String s) { super(s); } }
Mailbox selected = null;
Mailbox root = null;
Mailbox selected() { if (selected == null) throw new Bad("no mailbox selected"); return selected; }
- final Server.Authenticator auth;
+ final Login auth;
final Client client;
- public MailboxWrapper(Server.Authenticator auth, Client c) { this.auth=auth; this.client=c;}
+ public MailboxWrapper(Login auth, Client c) { this.auth=auth; this.client=c;}
private Mailbox mailbox(String name, boolean create) {
if (name.equalsIgnoreCase("inbox")) return inbox;
for(Mailbox.Iterator it=selected().iterator(q);it.next();) to.add(it.cur(), it.flags() | Mailbox.Flag.RECENT); }
public void login(String u, String p) {
- if ((root = auth.authenticate(u,p)) == null) throw new No("Login failed.");
+ Account account = null;
+ if ((account = auth.login(u,p)) == null) throw new No("Login failed.");
+ root = account.getMailbox(IMAP.class);
inbox = mailbox("INBOX", false); // FEATURE: ??
}
public void unselect() { selected = null; }
String selectedName = null;
Mailbox inbox = null, root = null;
Server api;
+ Login auth = null;
Parser parser = null;
Connection conn = null;
- public Listener() { }
+ public Listener(Login auth) { this.auth = auth; }
Parser.Token token() { return parser.token(); }
void println(String s) { conn.println(s); }
void newline() { parser.newline(); }
public void handleRequest(Connection conn) {
this.conn = conn;
parser = new Parser(conn);
- api = new IMAP.MailboxWrapper(new BogusAuthenticator(), this);
+ api = new IMAP.MailboxWrapper(auth, this);
conn.setTimeout(30 * 60 * 1000);
println("* OK " + conn.vhost + " " + IMAP.class.getName() + " IMAP4rev1 [RFC3501] v" + version + " server ready");
for(String tag = null;; newline()) try {
// Main //////////////////////////////////////////////////////////////////////////////
- /** simple listener for testing purposes */
- public static void main(String[] args) throws Exception {
- ServerSocket ss = new ServerSocket(143);
- for(;;) {
- final Socket s = ss.accept();
- new Thread() { public void run() { try {
- final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT+File.separatorChar+"imap", true);
- new Listener();
- } catch (Exception e) { e.printStackTrace(); } } }.start();
- }
- }
-
public static final int
PEEK=0x1, BODYSTRUCTURE=0x2, ENVELOPE=0x4, FLAGS=0x8, INTERNALDATE=0x10, FIELDS=0x800, FIELDSNOT=0x1000,
RFC822=0x20, RFC822TEXT=0x40, RFC822SIZE=0x80, HEADERNOT=0x100, UID=0x200, HEADER=0x400;
-
- public static class BogusAuthenticator implements IMAP.Server.Authenticator {
- final Mailbox root = FileBasedMailbox.getFileBasedMailbox(Mailbox.STORAGE_ROOT, true).slash("user", true);
- public Mailbox authenticate(String user, String pass) {
- return EtcPasswd.verify(user, pass) ? root.slash(user, false) : null; }
- }
}
}
public static class Listener implements Worker {
- private Server api;
+ private Server api = null;
+ private Login login;
private Connection conn;
- public Listener(Server api) { this.api = api; }
- public Listener() {
- Mailbox root = FileBasedMailbox.getFileBasedMailbox("/var/org.ibex.mail/user/megacz/newmail/", true);
- this.api = new MailboxWrapper(root);
- }
+ public Listener(Login l) { this.login = l; }
private void println(String s) { Log.warn("[nntp-write]", s); conn.println(s); }
private void println() { Log.warn("[nntp-write]", ""); conn.println(); }
this.conn = conn;
conn.setTimeout(30 * 60 * 1000);
println("200 " + conn.vhost + " [" + NNTP.class.getName() + "]");
+ String user = null;
+ String pass = null;
+ Account account = login.anonymous();
+ this.api = account == null ? null : new MailboxWrapper(account.getMailbox(NNTP.class));
for(String line = conn.readln(); line != null; line = conn.readln()) try {
Log.warn("[nntp-read]", line);
StringTokenizer st = new StringTokenizer(line, " ");
String command = st.nextToken().toUpperCase();
+ if (command.equals("AUTHINFO")) {
+ String uop = st.nextToken();
+ if (uop.equals("USER")) user = st.nextToken();
+ else if (uop.equals("PASS")) pass = st.nextToken();
+ // FIXME error here
+ }
+ if (this.api == null) {
+ if (user == null) { println("480 Authentication required"); continue; }
+ if (pass == null) { println("381 Password required"); continue; }
+ account = login.login(user, pass);
+ if (account == null) { println("502 Invalid"); continue; }
+ this.api = new MailboxWrapper(account.getMailbox(NNTP.class));
+ println("281 Good to go");
+ continue;
+ }
if (command.equals("ARTICLE")) { article(st.hasMoreTokens() ? st.nextToken() : null, true, true);
} else if (command.equals("HEAD")) { article(st.hasMoreTokens() ? st.nextToken() : null, true, false);
} else if (command.equals("MODE")) { println("201 Hello, you can post.");