if no inbox, use root
[org.ibex.mail.git] / src / org / ibex / mail / protocol / IMAP.java
index e143420..45ff1dc 100644 (file)
@@ -1,5 +1,6 @@
 package org.ibex.mail.protocol;
 import org.ibex.io.*;
+import org.ibex.crypto.*;
 import org.ibex.jinetd.Listener;
 import org.ibex.jinetd.Worker;
 import org.ibex.mail.*;
@@ -35,7 +36,7 @@ import java.io.*;
 public class IMAP {
 
     public IMAP() { }
-    public static final float version = (float)0.1;
+    public static final float version = (float)0.2;
 
     // API Class //////////////////////////////////////////////////////////////////////////////
 
@@ -75,7 +76,6 @@ public class IMAP {
         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); } }
@@ -93,16 +93,20 @@ public class IMAP {
         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) {
+        private Mailbox mailbox(String name, boolean create) { return mailbox(name, create, true); }
+        private Mailbox mailbox(String name, boolean create, boolean throwexn) {
             if (name.equalsIgnoreCase("inbox")) return inbox;
             Mailbox m = root;
             for(StringTokenizer st = new StringTokenizer(name, sep + ""); st.hasMoreTokens();)
-                if ((m = m.slash(st.nextToken(), create)) == null) throw new Server.No("no such mailbox " + name);
+                if ((m = m.slash(st.nextToken(), create)) == null) {
+                    if (throwexn) throw new Server.No("no such mailbox " + name);
+                    return null;
+                }
             return m;
         }
 
@@ -150,13 +154,16 @@ public class IMAP {
             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: ??
+            if (inbox == null) inbox = root;
         }
         public void unselect() { selected = null; }
         public void delete(String m0) { delete(mailbox(m0,false)); }
         public void delete(Mailbox m) { if (!m.equals(inbox)) m.destroy(false); else throw new Bad("can't delete inbox"); }
-        public void create(String m) { mailbox(m, true); }
+        public void create(String m) { mailbox(m, true, false); }
         public void append(String m,int f,Date a,String b) { try {
             mailbox(m,false).add(new Message(new Stream(b), new Message.Envelope(null,null,a)),f|Mailbox.Flag.RECENT);
         } catch (Message.Malformed e) { throw new No(e.getMessage()); } }
@@ -226,9 +233,10 @@ public class IMAP {
         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(); }
@@ -236,7 +244,7 @@ public class IMAP {
         public void handleRequest(Connection conn) {
             this.conn = conn;
             parser = new Parser(conn);
-            api = new IMAP.MailboxWrapper(new Main.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 {
@@ -441,7 +449,7 @@ public class IMAP {
             if (!negate) {
                 if(e) for(int j=0; j<headers.length; j++) {
                     r.append(headers[j] + (j<headers.length-1?" ":""));
-                    if (m.headers.get(headers[j]) != null) payload += headers[j]+": "+m.headers.get(headers[j])+"\r\n";
+                    if (m.headers.gets(headers[j]) != null) payload += headers[j]+": "+m.headers.gets(headers[j])+"\r\n";
                 }
             } else {
                throw new Server.No("HEADERS.NOT temporarily disaled");
@@ -450,7 +458,7 @@ public class IMAP {
                 if(e) { OUTER: for(Enumeration x=m.headers.keys(); x.hasMoreElements();) {
                     String key = (String)x.nextElement();
                     for(int j=0; j<headers.length; j++) if (key.equalsIgnoreCase(headers[j])) continue OUTER;
-                    payload += key + ": " + m.headers.get(key)+"\r\n";
+                    payload += key + ": " + m.headers.gets(key)+"\r\n";
                 } }
                */
             }
@@ -709,6 +717,7 @@ public class IMAP {
             public static String addressList(Object a) {
                 if (a == null) return "NIL";
                 if (a instanceof Address) return "("+address((Address)a)+")";
+                if (a instanceof String) return "("+address(Address.parse((String)a))+")";
                 Address[] aa = (Address[])a;
                 StringBuffer ret = new StringBuffer();
                 ret.append("(");
@@ -747,12 +756,12 @@ public class IMAP {
                 "(" + quotify(m.envelope.arrival.toString()) +
                 " " + quotify(m.subject) +          
                 " " + addressList(m.from) +      
-                " " + addressList(m.headers.get("sender")) +
+                " " + addressList(m.headers.gets("sender")) +
                 " " + addressList(m.replyto) + 
                 " " + addressList(m.to) + 
                 " " + addressList(m.cc) + 
                 " " + addressList(m.bcc) + 
-                " " + quotify((String)m.headers.get("in-reply-to")) +
+                " " + quotify((String)m.headers.gets("in-reply-to")) +
                 " " + quotify(m.messageid) +
                 ")";
         }
@@ -789,19 +798,8 @@ public class IMAP {
 
     // 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;
+
 }