more cleanup
authoradam <adam@megacz.com>
Sun, 13 Jun 2004 04:18:14 +0000 (04:18 +0000)
committeradam <adam@megacz.com>
Sun, 13 Jun 2004 04:18:14 +0000 (04:18 +0000)
darcs-hash:20040613041814-5007d-ec89b818f10644093f6bb531da0b4325775083dd.gz

src/org/ibex/mail/Query.java
src/org/ibex/mail/protocol/IMAP.java
src/org/ibex/mail/target/FileBasedMailbox.java
src/org/ibex/mail/target/Mailbox.java

index 4037b4b..5369f55 100644 (file)
@@ -37,6 +37,7 @@ public class Query {
     public static Query draft()                     { return new Query(DRAFT, null, 0, 0, 0, null, null, null, null, null); }
     public static Query answered()                  { return new Query(ANSWERED, null, 0, 0, 0, null, null, null, null, null); }
     public static Query recent()                    { return new Query(RECENT, null, 0, 0, 0, null, null, null, null, null); }
+    public static Query set(boolean uid, int[] set) { return uid ? uid(set) : num(set); }
 
     private Query(int type, Query[] q,int min,int max, int flags, String key, String text, Date earliest, Date latest, int[] set) {
         this.type = type; this.q = q; this.min = min; this.max = max; this.flags = flags; this.key = key; this.text = text;
index 1963ce2..21e937a 100644 (file)
@@ -72,7 +72,7 @@ public class IMAP extends MessageProtocol {
             return m;
         }
 
-        // FIXME: not accurate when a wildcard and subsequent non-wildcards both match a single component
+        // FEATURE: not accurate when a wildcard and subsequent non-wildcards both match a single component
         public HashSet lsub(String start, String ref, HashSet reply) { return list(start, ref, reply); }
         public HashSet list(String start, String ref, HashSet reply) {
             if (reply == null) reply = new HashSet();
@@ -124,30 +124,17 @@ public class IMAP extends MessageProtocol {
         public void expunge(Mailbox.Iterator it) { star(it.uid() + " EXPUNGE"); it.delete(); }
         public void subscribe(String mailbox) { }
         public void unsubscribe(String mailbox) { }
+        public int seen(String mailbox)        { return getMailbox(mailbox, false).count(Query.seen()); }
+        public int recent(String mailbox)      { return getMailbox(mailbox, false).count(Query.recent()); }
+        public int count(String mailbox)       { return getMailbox(mailbox, false).count(Query.all()); }
+        public int uidNext(String mailbox)     { return getMailbox(mailbox, false).uidNext(); }
+        public int uidValidity(String mailbox) { return getMailbox(mailbox, false).uidValidity(); }
         public void rename(Mailbox from, String to) {
             if (from.equals(inbox))                  from.copy(Query.all(), getMailbox(to, true));
             else if (to.equalsIgnoreCase("inbox")) { from.copy(Query.all(), getMailbox(to, true)); from.destroy(); }
             else from.rename(to);
         }
 
-        // FIXME lift out unparsing
-        public void status(Mailbox m, Token[] attrs) {
-            int seen = 0, recent = 0, messages = 0;
-            for(Mailbox.Iterator it = m.iterator(); it.next(); ) { if (!it.seen()) seen++; if (it.recent()) recent++; messages++; }
-            String response = "";
-            for(int i=0; i<attrs.length; i++) {
-                String s = attrs[i].atom();
-                if (s.equals("MESSAGES"))    response += "MESSAGES "    + messages;
-                if (s.equals("RECENT"))      response += "RECENT "      + seen;
-                if (s.equals("UIDNEXT"))     response += "UNSEEN "      + recent;
-                if (s.equals("UIDVALIDITY")) response += "UIDVALIDITY " + m.uidValidity();
-                if (s.equals("UNSEEN"))      response += "UIDNEXT "     + m.uidNext();
-            }
-            star("STATUS " + selectedName + " (" + response + ")");
-        }
-
-        // FIXME: we can omit UIDNEXT!
-        // FIXME use directory date/time as UIDNEXT and file date/time as UID; need to 'correct' file date/time after changes
         public void select(String mailbox, boolean examineOnly) {
             selected = getMailbox(selectedName = mailbox, false);
             star("FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)");
@@ -177,7 +164,7 @@ public class IMAP extends MessageProtocol {
                         FetchRequestBody frb = (FetchRequestBody)fr[i];
                         StringBuffer payload = new StringBuffer();
                         peek = frb.peek;
-                        // FIXME obey path[] here
+                        // obey path[] here
                         switch(frb.type) {
                             case FetchRequestBody.PATH:
                                 reply.append("BODY[] "); payload.append(m.body); break;
@@ -206,8 +193,8 @@ public class IMAP extends MessageProtocol {
 
         public void store(Query q, int addFlags, int removeFlags, boolean silent, boolean uid) {
             for(Mailbox.Iterator it = selected.iterator(q); it.next(); ) {
-                //it.addFlags(addFlags);        FIXME
-                //it.removeFlags(removeFlags);
+                it.addFlags(addFlags);
+                it.removeFlags(removeFlags);
                 if (!silent) star((uid ? it.uid() : it.num()) + " FETCH (FLAGS (" + flags(it) + "))");
             }
         }
@@ -236,7 +223,7 @@ public class IMAP extends MessageProtocol {
                     case RENAME:       rename(token().mailbox(), token().atom()); break;
                     case EXAMINE:      select(token().astring(), true); break;
                     case SELECT:       select(token().astring(), false); break;
-                    case COPY:         copy(uid ? Query.uid(token().set()) : Query.num(token().set()), token().mailbox()); break;
+                    case COPY:         copy(Query.set(uid, token().set()), token().mailbox()); break;
                     case DELETE:       delete(token().mailbox()); break;
                     case CHECK:        check(); break;
                     case NOOP:         noop(); break;
@@ -244,9 +231,21 @@ public class IMAP extends MessageProtocol {
                     case EXPUNGE:      expunge(); break;
                     case UNSELECT:     unselect(); break;
                     case CREATE:       create(token().astring()); break;
-                    case STATUS:       status(token().mailbox(), token().l()); break;
-                    case FETCH:        fetch(uid?Query.uid(token().set()):Query.num(token().set()),parseFetch(token().l()),uid);
-                        break;
+                    case FETCH:        fetch(Query.set(uid, token().set()), parseFetch(token().l()), uid); break;
+                    case STATUS: {
+                        String mailbox = token().atom();
+                        Token[] list = token().l();
+                        String response = "";
+                        for(int i=0; i<list.length; i++) {
+                            String s = list[i].atom();
+                            if (s.equals("MESSAGES"))    response += "MESSAGES "    + count(mailbox);
+                            if (s.equals("RECENT"))      response += "RECENT "      + seen(mailbox);
+                            if (s.equals("UIDNEXT"))     response += "UNSEEN "      + recent(mailbox);
+                            if (s.equals("UIDVALIDITY")) response += "UIDVALIDITY " + uidValidity(mailbox);
+                            if (s.equals("UNSEEN"))      response += "UIDNEXT "     + uidNext(mailbox);
+                        }
+                        star("STATUS " + selectedName + " (" + response + ")");
+                    }
                     case APPEND: { 
                         Mailbox m = token().mailbox();
                         int flags = 0;
@@ -479,7 +478,7 @@ public class IMAP extends MessageProtocol {
                     do { t = token(); if (t != null) toks.addElement(t); } while (t != null);
                     Token[] ret = new Token[toks.size()];
                     toks.copyInto(ret);
-                    return new Token(ret);  // FIXME
+                    return new Token(ret);
 
                 } else while(true) {
                     sb.append(c);
index 5788c8c..2373406 100644 (file)
@@ -7,6 +7,9 @@ import java.net.*;
 import java.util.*;
 import java.text.*;
 
+// FIXME: we can omit UIDNEXT!
+// FIXME use directory date/time as UIDNEXT and file date/time as UID; need to 'correct' file date/time after changes
+
 /** An exceptionally crude implementation of Mailbox relying on POSIXy filesystem semantics */
 public class FileBasedMailbox extends Mailbox.Default {
 
@@ -95,7 +98,7 @@ public class FileBasedMailbox extends Mailbox.Default {
         } catch (IOException e) { throw new MailException.IOException(e); }
     }
 
-    private class Iterator implements Mailbox.Default.Iterator {
+    private class Iterator extends Mailbox.Default.Iterator {
         int cur = -1;
         private String[] names;
         private boolean seen = false, deleted = false, draft = false, flagged = false, answered = false, recent = false;
index 2a86e1f..ec38126 100644 (file)
@@ -7,6 +7,7 @@ import java.net.*;
 import java.util.*;
 import java.text.*;
 
+/** abstract superclass for mailboxes, which store messages along with their flags */
 public abstract class Mailbox extends Target {
 
     public static final String STORAGE_ROOT =
@@ -49,6 +50,29 @@ public abstract class Mailbox extends Target {
         public void move(Query q, Mailbox dest) {
             for(Mailbox.Iterator it = iterator(q);it.next();) { dest.add(it.cur()); it.delete(); }
         }
+        public static abstract class Iterator implements Mailbox.Iterator {
+            public void addFlags(int flags) {
+                if ((flags & Flag.DELETED) == Flag.DELETED) deleted(true);
+                if ((flags & Flag.SEEN) == Flag.SEEN) seen(true);
+                if ((flags & Flag.FLAGGED) == Flag.FLAGGED) flagged(true);
+                if ((flags & Flag.DRAFT) == Flag.DRAFT) draft(true);
+                if ((flags & Flag.RECENT) == Flag.RECENT) recent(true);
+            }
+            public void removeFlags(int flags) {
+                if ((flags & Flag.DELETED) == Flag.DELETED) deleted(false);
+                if ((flags & Flag.SEEN) == Flag.SEEN) seen(false);
+                if ((flags & Flag.FLAGGED) == Flag.FLAGGED) flagged(false);
+                if ((flags & Flag.DRAFT) == Flag.DRAFT) draft(false);
+                if ((flags & Flag.RECENT) == Flag.RECENT) recent(false);
+            }
+            public void setFlags(int flags) {
+                if ((flags & Flag.DELETED) == Flag.DELETED) deleted(true); else deleted(false);
+                if ((flags & Flag.SEEN) == Flag.SEEN) seen(true); else seen(false);
+                if ((flags & Flag.FLAGGED) == Flag.FLAGGED) flagged(true); else flagged(false);
+                if ((flags & Flag.DRAFT) == Flag.DRAFT) draft(true); else draft(false);
+                if ((flags & Flag.RECENT) == Flag.RECENT) recent(true); else recent(false);
+            }
+        }
     }
 
 
@@ -74,6 +98,9 @@ public abstract class Mailbox extends Target {
         public abstract void    draft(boolean on);
         public abstract void    answered(boolean on);
         public abstract void    recent(boolean on);
+        public abstract void    addFlags(int flags);
+        public abstract void    removeFlags(int flags);
+        public abstract void    setFlags(int flags);
 
         public static class Wrapper implements Iterator {
             private Iterator it;
@@ -97,6 +124,9 @@ public abstract class Mailbox extends Target {
             public void    draft(boolean on) { it.draft(on); }
             public void    answered(boolean on) { it.answered(on); }
             public void    recent(boolean on) { it.recent(on); }
+            public void    addFlags(int flags) { it.addFlags(flags); }
+            public void    removeFlags(int flags) { it.removeFlags(flags); }
+            public void    setFlags(int flags) { it.setFlags(flags); }
         }
 
         class QueryIterator extends Mailbox.Iterator.Wrapper {
@@ -106,6 +136,7 @@ public abstract class Mailbox extends Target {
         }
     }
 
+    /** constants for the six IMAP flags */
     public static class Flag {
         public static final int DELETED  = 0x0001;
         public static final int SEEN     = 0x0002;