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;
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();
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)");
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;
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) + "))");
}
}
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;
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;
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);
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 =
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);
+ }
+ }
}
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;
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 {
}
}
+ /** constants for the six IMAP flags */
public static class Flag {
public static final int DELETED = 0x0001;
public static final int SEEN = 0x0002;