From 3173d1c5764330a4ffab8baccbcf68d0007a7f15 Mon Sep 17 00:00:00 2001 From: adam Date: Sun, 9 May 2004 05:32:30 +0000 Subject: [PATCH] checkpoint imap support darcs-hash:20040509053230-5007d-03c154f72b37e6008e966f09ff303dc54ac852cd.gz --- src/org/ibex/mail/Message.java | 13 +- src/org/ibex/mail/protocol/IMAP.java | 462 +++++++++++++++++++- src/org/ibex/mail/protocol/Incoming.java | 2 +- src/org/ibex/mail/protocol/SMTP.java | 8 +- .../mail/target/{FileSystem.java => Mailbox.java} | 14 +- src/org/ibex/mail/target/Script.java | 2 +- 6 files changed, 482 insertions(+), 19 deletions(-) rename src/org/ibex/mail/target/{FileSystem.java => Mailbox.java} (93%) diff --git a/src/org/ibex/mail/Message.java b/src/org/ibex/mail/Message.java index 0e0b13a..89009fe 100644 --- a/src/org/ibex/mail/Message.java +++ b/src/org/ibex/mail/Message.java @@ -37,7 +37,7 @@ public class Message extends JSReflection { public final Address envelopeFrom; public final Address[] envelopeTo; - public final Date arrival; // when the message first arrived at this machine + public final Date arrival; // when the message first arrived at this machine; IMAP "internal date message attr" public void dump(OutputStream os) throws IOException { Writer w = new OutputStreamWriter(os); @@ -52,9 +52,18 @@ public class Message extends JSReflection { /* public static class StoredMessage extends Message { public int uid; + public final int uid; + public final int uidValidity; // must be reset if mailbox is deleted and then recreated + public final int sequenceNumber; // starts at 1; numbers reshuffled upon EXPUNGE + public Hash keywords = new Hash(); public boolean deleted = false; - public boolean read = false; + public boolean seen = false; + public boolean flagged = false; + public boolean draft = false; public boolean answered = false; + public boolean recent = false; // "Message is "recently" arrived in this mailbox. This + // session is the first session to have been notified + // about this message; public StoredMessage(LineReader rs) throws IOException, MailException.Malformed { super(rs); } } */ diff --git a/src/org/ibex/mail/protocol/IMAP.java b/src/org/ibex/mail/protocol/IMAP.java index fc72869..504e6a8 100644 --- a/src/org/ibex/mail/protocol/IMAP.java +++ b/src/org/ibex/mail/protocol/IMAP.java @@ -2,9 +2,8 @@ package org.ibex.mail.protocol; import java.net.*; import java.io.*; -class IMAPException extends IOException { -} - +// FEATURE: pipelining +// FEATURE: support [charset] public class IMAP extends MessageProtocol { public static void main(String[] args) throws Exception { @@ -25,6 +24,461 @@ public class IMAP extends MessageProtocol { } } - public static void service(Socket s) throws IOException { + private static class Listener extends Incoming { + Socket conn; + String vhost; + Mailbox selected = null; + public void init() { } + public Listener(Socket conn, String vhost) { this.vhost = vhost; this.conn = conn; this.selected = null; } + + public void login(String user, String password) { if (!auth(user, password)) throw new No("Liar, liar, pants on fire."); } + public void capability() { star("CAPABILITY IMAP4rev1"); ok("Completed"); } + public void noop() { ok("Completed"); } + public void logout() { star("BYE LOGOUT received"); ok("Completed"); } + public void delete(Mailbox m) { if (!m.getName().toLowerCase().equals("inbox")) m.delete(); } + public void subscribe(String[] args) { ok("SUBSCRIBE ignored"); } + public void unsubscribe(String[] args) { ok("UNSUBSCRIBE ignored"); } + public void check(String[] args, boolean examineOnly) { ok("check complete"); } + public void lsub(String[] args) { list(args); } + public void list(String[] args) { star("LIST () \".\" INBOX"); ok("LIST completed"); } + public void create(String mailbox) { + if (mailbox.charAt(mailbox.length() - 1) != '.' && + !mailbox.toLowerCase.equals("inbox")) + if (!storage.create(mailbox)) + throw No("unable to CREATE mailbox"); + ok("CREATE completed"); + } + public void rename(Mailbox from, String to) { + if (from.getName().toLowerCase().equals("inbox")) { + int[] messages = from.list(); + Malbox toBox = getMailbox(to); + for(int i=0; i, : * (* = largest) + } + public Date date() throws Bad { + // may be quoted or unquoted + try { + new SimpleDateFormat("dd-MMM-yyyy").parse(s); + } catch (DateParsingException) { + } + } + public String nstring() throws Bad { + if (type == NIL) return null; + if (type == QUOTED) return s; + throw new Bad("expected NIL or string"); + } + public String astring() throws Bad { + if (type == ATOM) return s; + if (type == QUOTED) return s; + throw new Bad("expected atom or string"); + } + public String atom() throws Bad { + // ATOM_CHAR ::= + // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials + if (type != ATOM) throw new Bad("expected atom"); + } + public Mailbox mailbox() throws Bad { + if (type == BAREWORD && s.toLowerCase().equals("inbox")) return Mailbox.INBOX; + return Mailbox.getMailbox(astring()); + } + public Date datetime() throws Bad { + // expected to be a quoted string + + new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss +zzzz").parse(s); + } + + } + + + + // literal ::= "{" number "}" CRLF *CHAR8 ;; Number represents the number of CHAR8 octets + + public static Token[] tokenize(String s) { + Vec toks = new Vec(); + StringBuffer sb = new StringBuffer(); + for(int i=0; i