bogus patch
[org.ibex.mail.git] / src / org / ibex / mail / protocol / IMAP.java
index 2291826..346f007 100644 (file)
@@ -1,6 +1,7 @@
 package org.ibex.mail.protocol;
 import org.ibex.io.*;
 import org.ibex.jinetd.Listener;
+import org.ibex.jinetd.Worker;
 import org.ibex.net.*;
 import org.ibex.mail.*;
 import org.ibex.util.*;
@@ -32,13 +33,7 @@ import java.io.*;
 // FEATURE: STARTTLS
 // FEATURE: asynchronous client notifications (need to re-read RFC)
 
-public class IMAP implements Listener {
-
-    public void accept(Connection c) {
-        Log.error(this, "IMAP got a connection!");
-        new Listener().handleRequest(c);
-        c.close();
-    }
+public class IMAP {
 
     public IMAP() { }
     public static final float version = (float)0.1;
@@ -163,7 +158,9 @@ public class IMAP implements Listener {
         public void delete(String m0) { delete(mailbox(m0,false)); }
         public void delete(Mailbox m) { if (!m.equals(inbox)) m.destroy(false); else throw new Bad("can't delete inbox"); }
         public void create(String m) { mailbox(m, true); }
-        public void append(String m,int f,Date a,String b){mailbox(m,false).add(new Message(null,null,b,a),f|Mailbox.Flag.RECENT);}
+        public void append(String m,int f,Date a,String b) { try {
+            mailbox(m,false).add(new Message(null,null,b,a),f|Mailbox.Flag.RECENT);
+        } catch (Message.Malformed e) { throw new No(e.getMessage()); } }
         public void check() { }
         public void noop() { }
         public void logout() { }
@@ -213,7 +210,10 @@ public class IMAP implements Listener {
         }
         public void fetch(Query q, int spec, String[] headers, int start, int end, boolean uid) {
             for(Mailbox.Iterator it = selected().iterator(q); it.next(); ) {
-                client.fetch(it.num(), it.flags(), it.cur().size(), it.cur(), it.uid());
+                Message message = ((spec & (BODYSTRUCTURE | ENVELOPE | INTERNALDATE | FIELDS | FIELDSNOT | RFC822 |
+                                            RFC822TEXT | RFC822SIZE | HEADERNOT | HEADER)) != 0) ? it.cur() : null;
+                int size = message == null ? 0 : message.size();
+                client.fetch(it.num(), it.flags(), size, message, it.uid());
                 it.recent(false);
             }
         }
@@ -235,13 +235,13 @@ public class IMAP implements Listener {
         void newline() { parser.newline(); }
         Query query() { return parser.query(); }
         public void handleRequest(Connection conn) {
-            parser = new Parser(conn);
             this.conn = conn;
+            parser = new Parser(conn);
             api = new IMAP.MailboxWrapper(new Main.BogusAuthenticator(), this);
             conn.setTimeout(30 * 60 * 1000);
             println("* OK " + conn.vhost + " " + IMAP.class.getName() + " IMAP4rev1 [RFC3501] v" + version + " server ready");
             for(String tag = null;; newline()) try {
-                conn.out.flush();
+                conn.flush();
                 boolean uid = false;
                 tag = null; Parser.Token tok = token(); if (tok == null) return; tag = tok.astring();
                 String command = token().atom();
@@ -321,8 +321,8 @@ public class IMAP implements Listener {
                 }
                 println(tag+" OK "+command+" Completed. " +
                         (commandKey == LOGIN ? ("[CAPABILITY "+Printer.join(" ", api.capability())+"]") : ""));
-            } catch (Server.Bad b) { println(tag==null ? "* BAD Invalid tag":(tag + " Bad " + b.toString())); b.printStackTrace();
-            } catch (Server.No n)  { println(tag==null?"* BAD Invalid tag":(tag+" No "  + n.toString())); n.printStackTrace(); }
+            } catch (Server.Bad b) { println(tag==null ? "* BAD Invalid tag":(tag + " Bad " + b.toString())); Log.warn(this,b);
+            } catch (Server.No n)  { println(tag==null?"* BAD Invalid tag":(tag+" No "  + n.toString())); Log.warn(this,n); }
         }
 
         private Parser.Token[] lastfetch = null; // hack
@@ -348,7 +348,7 @@ public class IMAP implements Listener {
         private void fetch(Object o, Parser.Token[] t, int num, int flags, int size, boolean uid, int muid) {
             Query q   = o instanceof Query ? (Query)o : null;
             Message m = o instanceof Message ? (Message)o : null;
-            boolean e = m != null;
+            boolean e = q == null;
 
             lastfetch = t;
             int spec = 0;                              // spec; see constants for flags
@@ -487,11 +487,9 @@ public class IMAP implements Listener {
         private static final int SEARCH = 25;      static { commands.put("SEARCH", new Integer(SEARCH)); }
     }
 
-    public static class Parser extends Stream.In {
+    public static class Parser {
         private Stream stream;
-        public Parser(Stream from) { super(from.in); this.stream = from; }
-        public char peekc() { int i = read(); unread(((char)i)+""); return (char)i; }
-        public char getc() { return (char)read(); }
+        public Parser(Stream from) { this.stream = from; }
         public Token token(String s) { return new Token(s); }
         protected Query query() {
             String s = null;
@@ -645,9 +643,9 @@ public class IMAP implements Listener {
         }
 
         public void newline() {
-           while (peekc() == '\r' || peekc() == '\n' || peekc() == ' ') {
-               for(char c = peekc(); c == ' ';) { getc(); c = peekc(); };
-               for(char c = peekc(); c == '\r' || c == '\n';) { getc(); c = peekc(); };
+           while (stream.peekc() == '\r' || stream.peekc() == '\n' || stream.peekc() == ' ') {
+               for(char c = stream.peekc(); c == ' ';) { stream.getc(); c = stream.peekc(); };
+               for(char c = stream.peekc(); c == '\r' || c == '\n';) { stream.getc(); c = stream.peekc(); };
            }
         }
 
@@ -655,21 +653,21 @@ public class IMAP implements Listener {
         public Token token(boolean freak) {
             Vec toks = new Vec();
             StringBuffer sb = new StringBuffer();
-            char c = getc(); while (c == ' ') c = getc();
+            char c = stream.getc(); while (c == ' ') c = stream.getc();
             if (c == '\r' || c == '\n') { if (freak) bad("unexpected end of line"); return null; }
             else if (c == '{') {
-                while(peekc() != '}') sb.append(getc());
-                stream.out.println("+ Ready when you are...");
+                while(stream.peekc() != '}') sb.append(stream.getc());
+                stream.println("+ Ready when you are...");
                 int octets = Integer.parseInt(sb.toString());
-                while(peekc() == ' ') getc();   // whitespace
-                while (getc() != '\n' && getc() != '\r') { }
+                while(stream.peekc() == ' ') stream.getc();   // whitespace
+                while (stream.getc() != '\n' && stream.getc() != '\r') { }
                 byte[] bytes = new byte[octets];
-                read(bytes, 0, bytes.length);
+                stream.read(bytes, 0, bytes.length);
                 return new Token(new String(bytes), true);
             } else if (c == '\"') {
                 while(true) {
-                    c = getc();
-                    if (c == '\\') sb.append(getc());
+                    c = stream.getc();
+                    if (c == '\\') sb.append(stream.getc());
                     else if (c == '\"') break;
                     else sb.append(c);
                 }
@@ -686,11 +684,11 @@ public class IMAP implements Listener {
                 
             } else while(true) {
                 sb.append(c);
-                c = peekc();
+                c = stream.peekc();
                 if (c == ' ' || c == '\"' || c == '(' || c == ')' || c == '[' || c == ']' ||
                     c == '{' || c == '\n' || c == '\r')
                     return new Token(sb.toString(), false);
-                getc();
+                stream.getc();
             }
         }
     }