X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fmail%2FMailbox.java;h=3d3f8bb02050519ed433d19b79fb0dfb8078c359;hb=HEAD;hp=a0dc665f46e790b4f3116d0d418de7080f83ecb7;hpb=bea75eed0419e5888bda70d9cb1f3951a1a6d510;p=org.ibex.mail.git diff --git a/src/org/ibex/mail/Mailbox.java b/src/org/ibex/mail/Mailbox.java index a0dc665..3d3f8bb 100644 --- a/src/org/ibex/mail/Mailbox.java +++ b/src/org/ibex/mail/Mailbox.java @@ -13,11 +13,7 @@ import java.util.*; import java.text.*; /** abstract superclass for mailboxes, which store messages along with their flags */ -public abstract class Mailbox extends MailboxTree implements Target { - - public JS get(JS key) throws JSExn { - return slash(JSU.toString(key), true); - } +public abstract class Mailbox extends JS.Obj implements Target { public static final String STORAGE_ROOT = System.getProperty("ibex.mail.root", File.separatorChar + "var" + File.separatorChar + "org.ibex.mail"); @@ -25,8 +21,6 @@ public abstract class Mailbox extends MailboxTree implements Target { // Required Methods ////////////////////////////////////////////////////////////////////////////// - /** phantom mailboxes merely contain others; like the alt.binaries in alt.binaries.warez */ - public abstract boolean phantom(); public abstract Mailbox.Iterator iterator(Query q); public abstract void insert(Message message, int flags); @@ -35,9 +29,6 @@ public abstract class Mailbox extends MailboxTree implements Target { public abstract void copy(Query q, Mailbox dest); public abstract int count(Query q); public abstract int uidNext(); - public abstract void rename(String newName); /* FIXME: IMAP semantics require creating parent dirs */ - public abstract void destroy(boolean recursive); - public Mailbox getMailbox() { return this; } // Thunks //////////////////////////////////////////////////////////////////////////// @@ -50,22 +41,29 @@ public abstract class Mailbox extends MailboxTree implements Target { private int randomUidValidity = new Random().nextInt(); public int uidValidity() { return randomUidValidity; } + public int maxuid() { + int ret = -1; + for(Mailbox.Iterator it = iterator(); it.next(); ) ret = Math.max(ret, it.uid()); + return ret; + } + /** default, inefficient implementation of Mailbox; only requires a few methods to be implemented */ - public static abstract class Default extends Mailbox { + public static abstract class Default extends Mailbox /* implements MailTree? */ { public Mailbox.Iterator iterator(Query q) { return new Mailbox.Iterator.QueryIterator(q, this); } - public boolean phantom() { return false; } public void copy(Query q, Mailbox dest) { for(Mailbox.Iterator it = iterator(q); it.next();) dest.insert(it.cur(), it.getFlags()); } public int count(Query q) { int count = 0; for(Mailbox.Iterator it = iterator(q); it.next();) count++; return count; } - public void rename(String newName) { throw new MailException("not supported"); } - public void destroy(boolean recursive) { throw new MailException("not supported"); } - public MailboxTree slash(String name, boolean create) { return null; } + public MailTree slash(String name, boolean create) { return null; } public String[] children() { return new String[] { }; } public void post(Message message) { insert(message, Flag.RECENT); } + public JS get(JS key) throws JSExn { + return (JS)slash(JSU.toString(key), true); + } public void move(Query q, Mailbox dest) { for(Mailbox.Iterator it = iterator(q);it.next();) { dest.insert(it.cur(), it.getFlags()); it.delete(); } } public static abstract class Iterator implements Mailbox.Iterator { // FIXME: NNTP spec allows us to use longs (64-bit) here + // FIXME: NNTP spec requires that the minimum nntpNumber of a group must never, ever decrease (no, that's not a typo) public int nntpNumber() { throw new MailException("not supported"); } public int getFlags() { return 0; } public void setFlags(int flags) { throw new MailException("not supported"); } @@ -78,7 +76,11 @@ public abstract class Mailbox extends MailboxTree implements Target { public static interface Iterator { public abstract Message cur(); public abstract Headers head(); + + // FIXME: change all code to actually use this convention! + /** JDBC convention: iterator starts "before the first element" */ public abstract boolean next(); + public abstract void delete(); /** a unique identifier for this message */ @@ -86,10 +88,10 @@ public abstract class Mailbox extends MailboxTree implements Target { /** * Message number according to IMAP semantics. + * - must range from 1..numMessagesInMailbox * - no two messages in the same mailbox may have the same imapNumber * - sorting by uid must yield the same order as sorting them by imapNumber - * - imapNumber may only change if uidValidity changes - * - if uidValidity changes, imapNumbers may change or be reused + * - imapNumber changes when messages with lower imapNumbers are deleted */ public abstract int imapNumber(); @@ -118,6 +120,20 @@ public abstract class Mailbox extends MailboxTree implements Target { public void setFlags(int flags) { it.setFlags(flags); } } + public static class AclWrapper extends Wrapper { + private Acl.Entry acl; + public AclWrapper(Iterator it, Acl.Entry acl) { super(it); this.acl = acl; } + public Message cur() { if (acl.read && acl.list) return super.cur(); else throw new Acl.PermissionDenied(); } + public Headers head() { if (acl.read && acl.list) return super.head(); else throw new Acl.PermissionDenied(); } + public boolean next() { if (acl.list) return super.next(); else throw new Acl.PermissionDenied(); } + public int uid() { if (acl.list) return super.uid(); else throw new Acl.PermissionDenied(); } + public int nntpNumber() { if (acl.list) return super.nntpNumber(); else throw new Acl.PermissionDenied(); } + public int imapNumber() { if (acl.list) return super.imapNumber(); else throw new Acl.PermissionDenied(); } + public void delete() { if (acl.delete) super.delete(); else throw new Acl.PermissionDenied(); } + public int getFlags() { if (acl.list) return super.getFlags(); else throw new Acl.PermissionDenied(); } + public void setFlags(int flags) { if (acl.flags) super.setFlags(flags); else throw new Acl.PermissionDenied(); } + } + class QueryIterator extends Mailbox.Iterator.Wrapper { Query q; public QueryIterator(Query q, Mailbox m) { super(m.iterator()); this.q = q; } @@ -151,11 +167,10 @@ public abstract class Mailbox extends MailboxTree implements Target { } public static class MailboxWrapper extends Mailbox { - private Mailbox m; public MailboxWrapper(Mailbox m) { this.m = m; } - public boolean phantom() { return m.phantom(); } + public Mailbox.Iterator iterator() { return m.iterator(); } public Mailbox.Iterator iterator(Query q) { return m.iterator(q); } public void insert(Message message, int flags) { m.insert(message, flags); } public void post(Message message) { m.insert(message, Flag.RECENT); } @@ -163,12 +178,21 @@ public abstract class Mailbox extends MailboxTree implements Target { public void copy(Query q, Mailbox dest) { m.copy(q, dest); } public int count(Query q) { return m.count(q); } public int uidNext() { return m.uidNext(); } - public void rename(String newName) { m.rename(newName); } - public void destroy(boolean recursive) { m.destroy(recursive); } - public MailboxTree slash(String name, boolean create) { return m.slash(name, create); } - public String[] children() { return m.children(); } - public Mailbox.Iterator iterator() { return m.iterator(); } public int uidValidity() { return m.uidValidity(); } } + public static class AclWrapper extends MailboxWrapper { + private Mailbox m; + private Acl.Entry acl; + public AclWrapper(Mailbox m, Acl.Entry acl) { super(m); this.acl = acl; } + public Mailbox.Iterator iterator(Query q) { if (acl.list) return new Mailbox.Iterator.AclWrapper(m.iterator(q), acl); else throw new Acl.PermissionDenied(); } + public Mailbox.Iterator iterator() { if (acl.list) return new Mailbox.Iterator.AclWrapper(m.iterator(), acl); else throw new Acl.PermissionDenied(); } + public void insert(Message message, int flags) { if (acl.insert) m.insert(message, flags); else throw new Acl.PermissionDenied(); } + public int uidValidity() { if (acl.list) return m.uidValidity(); else throw new Acl.PermissionDenied(); } + public void post(Message message) { if (acl.post) m.insert(message, Flag.RECENT); else throw new Acl.PermissionDenied(); } + public void move(Query q, Mailbox dest) { if (acl.list && acl.read && acl.delete) m.move(q, dest); else throw new Acl.PermissionDenied(); } + public void copy(Query q, Mailbox dest) { if (acl.list && acl.read) m.copy(q, dest); else throw new Acl.PermissionDenied(); } + public int count(Query q) { if (acl.list) return m.count(q); else throw new Acl.PermissionDenied(); } + public int uidNext() { if (acl.list) return m.uidNext(); else throw new Acl.PermissionDenied(); } + } }