From fe4fee4ea29db833ddce7882e79861f33661681f Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 17 May 2004 05:38:55 +0000 Subject: [PATCH] mad changes darcs-hash:20040517053855-5007d-50af8dc340a4d9b6a0eeca66a4c0899ca260b885.gz --- src/org/ibex/mail/protocol/IMAP.java | 308 ++++++++++++++++++---------------- 1 file changed, 159 insertions(+), 149 deletions(-) diff --git a/src/org/ibex/mail/protocol/IMAP.java b/src/org/ibex/mail/protocol/IMAP.java index 504e6a8..6fe15a2 100644 --- a/src/org/ibex/mail/protocol/IMAP.java +++ b/src/org/ibex/mail/protocol/IMAP.java @@ -41,13 +41,7 @@ public class IMAP extends MessageProtocol { 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 create(String mailbox) {if(!mailbox.endsWith(".")&&!mailbox.equalsIgnoreCase("inbox"))storage.create(mailbox);} public void rename(Mailbox from, String to) { if (from.getName().toLowerCase().equals("inbox")) { int[] messages = from.list(); @@ -65,7 +59,7 @@ public class IMAP extends MessageProtocol { inbox.add(m); from.delete(messages[i]); } - // FIXME delete from + from.delete(); } else { from.rename(to); } @@ -124,35 +118,6 @@ public class IMAP extends MessageProtocol { if (!silent) ok("EXPUNGE completed"); } - public void fetch(int[] messageSet, boolean examineOnly, boolean uid) { - if (selected == null) throw new Bad("no mailbox selected"); - Object[] tokens = tokenize(args[0]); - String[] headers; - boolean negateHeaders; - boolean flags; - boolean internalDate; - boolean size; - boolean uid; - int start, end; - boolean setSeen; - for(int i=0; i'))); + s = s.substring(0, s.indexOf('<')); + } if (s.equals("ENVELOPE")) envelope = true; else if (s.equals("FLAGS")) flags = true; else if (s.equals("INTERNALDATE")) internaldate = true; - else if (s.equals("RFC822")) body = true; // FIXME: special return syntax? + else if (s.equals("RFC822")) body = true; else if (s.equals("RFC822.HEADER")) header = true; else if (s.equals("RFC822.SIZE")) size = true; else if (s.equals("RFC822.TEXT")) body = true; else if (s.equals("BODY")) body = true; + else if (s.equals("BODY[]")) body = true; + else if (s.equals("BODY[HEADER]")) header=true; + else if (s.startsWith("BODY[HEADER.FIELDS")) throw new No("partial headers not supported"); + else if (s.startsWith("BODY[HEADER.FIELDS.NOT")) throw new No("partial headers not supported"): else if (s.equals("BODYSTRUCTURE")) throw new No("FETCH BODYSTRUCTURE not supported"); + else if (s.equals("TEXT")) body = true; + else if (s.equals("MIME")) throw new Bad("FETCH BODY.MIME not supported"); else if (s.equals("UID")) uid = true; else if (s.startsWith("BODY")) throw new No("FETCH BODY[*] not supported"); else throw new Bad("unrecognized FETCH argument \"" + s + "\""); } - fetch(selected, null, false, flags, internaldate, size, uid, start, end, setseen, envelope); + fetch(selected, flags, internaldate, size, uid, start, end, setseen, envelope, header, peek); } else if (command.equals("STATUS")) { Mailbox m = mailbox(); Token[] attrs = l(); @@ -294,80 +306,47 @@ public class IMAP extends MessageProtocol { ")"; } - public static void fetch(Message m, String[] headers, boolean negateHeaders, boolean flags, boolean internalDate, - boolean size, boolean uid, int start, int end, boolean setSeen, boolean envelope) { - String reply = ""; - if (flags) - reply += - "FLAGS (" - + m.deleted ? "\Deleted " : "" - + m.seen ? "\Seen " : "" - + m.flagged ? "\Flagged " : "" - + m.draft ? "\Draft " : "" - + m.answered ? "\Answered " : "" - + m.recent ? "\Recent " : "" - + ") "; - if (size) reply += "RFC822.SIZE " m.rfc822size() + " ";; - if (bodyStructure) // FIXME - reply += "(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL \"7BIT\" " + m.rfc822size() +" "+ m.numLines() +")"; - if (envelope) - reply += - "(" + quotify(m.date) + - " " + quotify(m.subject) + - " " + quotify(new Address[] { m.from }) + " " + - " " + quotify(new Address[] { m.sender }) + " " + - " " + quotify(new Address[] { m.replyTo }) + " " + - " " + quotify(new Address[] { m.to }) + " " + - " " + quotify(cc) + " " + - " " + quotify(bcc) + " " + - " " + quotify(m.headers.get("in-reply-to")) + " " + - " " + quotify(m.messageId) + - ") "; - if (internaldate) reply += quotify(m.arrival) + " "; - // FIXME - } - public static Query parseQuery() { - String tok = null; + public static Query query() { + String s = null; boolean not = false; while(true) { Token t = token(); - if (t.type == t.LIST) { } - else if (t.type == t.SET) { } - tok = t.atom(); - if (tok.equals("NOT")) { not = true; continue; } - if (tok.equals("OR")) { /* FIXME */ } - if (tok.equals("AND")) { /* FIXME */ } + if (t.type == t.LIST) { /* FIXME */ } + else if (t.type == t.SET) return new Query.Set(t.set()); + s = t.atom(); + if (s.equals("NOT")) { not = true; continue; } + if (s.equals("OR")) { return new Query.OR(new Query[] { query(), query() }); } + if (s.equals("AND")) { return new Query.AND(new Query[] { query(), query() }); } break; } - if (tok.startsWith("UN")) { not = true; tok = tok.substring(2); } - if (tok.equals("ANSWERED")) q = new Query.Flag(Query.Flag.ANSWERED); - else if (tok.equals("DELETED")) q = new Query.Flag(Query.Flag.ANSWERED); - else if (tok.equals("DRAFT")) q = new Query.Flag(Query.Flag.ANSWERED); - else if (tok.equals("FLAGGED")) q = new Query.Flag(Query.Flag.ANSWERED); - else if (tok.equals("RECENT")) q = new Query.Flag(Query.Flag.ANSWERED); - else if (tok.equals("SEEN")) q = new Query.Flag(Query.Flag.ANSWERED); - else if (tok.equals("OLD")) { not = true; q = new Query.Flag(Query.Flag.RECENT); } - else if (tok.equals("NEW")) q = new Query.And(new Query.Flag(Query.Flag.RECENT), - new Query.Not(new Query.Flag(Query.Flag.SEEN))); - else if (tok.equals("KEYWORD")) q = new Query.Header("keyword", flag()); - else if (tok.equals("HEADER")) q = new Query.Header(astring(), astring()); - else if (tok.equals("BCC")) q = new Query.Header("bcc", astring()); - else if (tok.equals("CC")) q = new Query.Header("cc", astring()); - else if (tok.equals("FROM")) q = new Query.Header("from", astring()); - else if (tok.equals("TO")) q = new Query.Header("to", astring()); - else if (tok.equals("SUBJECT")) q = new Query.Header("subject", astring()); - else if (tok.equals("BEFORE")) q = new Query.Arrival(date(), true, false); - else if (tok.equals("SINCE")) q = new Query.Arrival(date(), false, true); - else if (tok.equals("ON")) q = new Query.Arrival(date(), true, true); - else if (tok.equals("LARGER")) q = new Query.Size(n(), true); - else if (tok.equals("SMALLER")) q = new Query.Size(n(), false); - else if (tok.equals("BODY")) q = new Query.FullText(astring(), true, false); - else if (tok.equals("TEXT")) q = new Query.FullText(astring(), true, true); - else if (tok.equals("SENTBEFORE")) { /* FIXME date() */ } - else if (tok.equals("SENTSINCE")) { /* FIXME date() */ } - else if (tok.equals("SENTON")) { /* FIXME date() */ } - else if (tok.equals("UID")) { /* FIXME set() */ } + if (s.startsWith("UN")) { not = true; tok = s.substring(2); } + if (s.equals("ANSWERED")) q = new Query.Flag(Query.Flag.ANSWERED); + else if (s.equals("DELETED")) q = new Query.Flag(Query.Flag.ANSWERED); + else if (s.equals("DRAFT")) q = new Query.Flag(Query.Flag.ANSWERED); + else if (s.equals("FLAGGED")) q = new Query.Flag(Query.Flag.ANSWERED); + else if (s.equals("RECENT")) q = new Query.Flag(Query.Flag.ANSWERED); + else if (s.equals("SEEN")) q = new Query.Flag(Query.Flag.ANSWERED); + else if (s.equals("OLD")) { not = true; q = new Query.Flag(Query.Flag.RECENT); } + else if (s.equals("NEW"))q=new Query.And(new Query.Flag(Query.Flag.RECENT),new Query.Not(new Query.Flag(Query.Flag.SEEN))); + else if (s.equals("KEYWORD")) q = new Query.Header("keyword", flag()); + else if (s.equals("HEADER")) q = new Query.Header(astring(), astring()); + else if (s.equals("BCC")) q = new Query.Header("bcc", astring()); + else if (s.equals("CC")) q = new Query.Header("cc", astring()); + else if (s.equals("FROM")) q = new Query.Header("from", astring()); + else if (s.equals("TO")) q = new Query.Header("to", astring()); + else if (s.equals("SUBJECT")) q = new Query.Header("subject", astring()); + else if (s.equals("LARGER")) q = new Query.Size(n(), true); + else if (s.equals("SMALLER")) q = new Query.Size(n(), false); + else if (s.equals("BODY")) q = new Query.FullText(astring(), true, false); + else if (s.equals("TEXT")) q = new Query.FullText(astring(), true, true); + else if (s.equals("BEFORE")) q = new Query.Arrival(date(), true, false); + else if (s.equals("SINCE")) q = new Query.Arrival(date(), false, true); + else if (s.equals("ON")) q = new Query.Arrival(date(), true, true); + else if (s.equals("SENTBEFORE")) q = new Query.Sent(date(), true, false); + else if (s.equals("SENTSINCE")) q = new Query.Sent(date(), false, true); + else if (s.equals("SENTON")) q = new Query.Sent(date(), true, true); + else if (s.equals("UID")) q = new Query.UID(set()); } private static class Token { @@ -390,7 +369,9 @@ public class IMAP extends MessageProtocol { public void deleteFlags(Message m) { } public String mailboxPattern() { - /* 1*(ATOM_CHAR / "%" / "*") / string */ + if (type == ATOM) retrn s; + if (type == QUOTED) return s; + throw new Bad("exepected a mailbox pattern"); } public String flag() throws Bad { if (type != ATOM) throw new Bad("expected a flag"); @@ -410,22 +391,44 @@ public class IMAP extends MessageProtocol { if (type != QUOTED) throw new Bad("expected qstring"); return s; } - public String nstring() throws Bad { - } public Token[] l() throws Bad { if (type == NIL) return null; if (type != LIST) throw new Bad("expected parenthesized list"); return l; } public int[] set() throws Bad { - // FIXME , : * (* = largest) + if (type != ATOM) throw new Bad("expected a messageid set"); + Vec ids = new Vec(); + StringTokenizer st = new StringTokenizer(s, ","); + while(st.hasMoreTokens()) { + String s = st.nextToken(); + if (s.indexOf(':') != -1) { + int start = Integer.parseInt(s.substring(0, s.indexOf(':'))); + String end_s = s.indexOf(':'+1); + if (end_s.equals("*")) { + ids.addElement(new Integer(start)); + ids.addElement(new Integer(-1)); + } else { + int end = Integer.parseInt(end_s); + for(int j=start; j<=end; j++) ids.addElement(new Integer(j)); + } + } else { + ids.addElement(new Integer(Integer.parseInt(s))); + } + } + int[] ret = new int[ids.size()]; + ids.copyInto(ret); + return ret; } public Date date() throws Bad { - // may be quoted or unquoted - try { - new SimpleDateFormat("dd-MMM-yyyy").parse(s); - } catch (DateParsingException) { - } + if (type != QUOTED && type != ATOM) throw new Bad("Expected quoted or unquoted date"); + try { new SimpleDateFormat("dd-MMM-yyyy").parse(s); + } catch (ParseException p) { throw new Bad("invalid date format; " + p); } + } + public Date datetime() throws Bad { + if (type != QUOTED && type != ATOM) throw new Bad("Expected quoted or unquoted datetime"); + try { new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss +zzzz").parse(s); + } catch (ParseException p) { throw new Bad("invalid datetime format; " + p); } } public String nstring() throws Bad { if (type == NIL) return null; @@ -438,46 +441,53 @@ public class IMAP extends MessageProtocol { 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"); + for(int i=0; i