Author: alexlehm Date: 2008-01-10 15:06:43 +0000 (Thu, 10 Jan 2008) New Revision: 16992
Modified: trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java Log: fix for issue 0001090: Accessing Freemail with Thunderbird gives error Bad Number (https://bugs.freenetproject.org/view.php?id=1090) parse ranges of the form n1:n2,n3:n4 or n1,n2 etc. correctly. This is done by using a TreeSet (SortedSet). Worked for me for a few weeks now, however there is another issue with enumerating message UIDs wrt. sorting. Also included is two protocol errors in the case where a parsing error happens and the trailing newline is missing. Modified: trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java =================================================================== --- trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java 2008-01-10 00:49:27 UTC (rev 16991) +++ trunk/apps/Freemail/src/freemail/imap/IMAPHandler.java 2008-01-10 15:06:43 UTC (rev 16992) @@ -27,7 +27,9 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; +import java.util.Iterator; import java.util.SortedMap; +import java.util.TreeSet; import java.lang.NumberFormatException; import java.text.SimpleDateFormat; import java.util.Date; @@ -406,67 +408,65 @@ } return; } + + // build a set from the uid ranges, first separated by , then by : + TreeSet ts=new TreeSet(); + String[] rangeparts = msg.args[1].split(","); - String[] parts = msg.args[1].split(":"); - try { - from = Integer.parseInt(parts[0]); - } catch (NumberFormatException nfe) { - this.reply(msg, "BAD Bad number: "+parts[0]+". Please report this error!"); - return; - } - if (parts.length < 2) { - to = from; - } else if (parts[1].equals("*")) { - Integer tmp = (Integer)msgs.lastKey(); - to = tmp.intValue(); - } else { - try { - to = Integer.parseInt(parts[1]); - } catch (NumberFormatException nfe) { - this.reply(msg, "BAD Bad number: "+parts[0]+". Please report this error!"); - return; + for(int i=0;i<rangeparts.length;i++) { + String vals[]=rangeparts[i].split(":"); + if(vals.length==1) { + ts.add(new Integer(vals[0])); + } else { + from=Integer.parseInt(vals[0]); + if(vals[1].equals("*")) { + to=((Integer)msgs.lastKey()).intValue(); + } else { + to=Integer.parseInt(vals[1]); + } + for(int j=from;j<=to;j++) { + ts.add(new Integer(j)); + } } } - + int msgnum = 1; if (msg.args[0].equalsIgnoreCase("fetch")) { - int oldsize = msgs.size(); - msgs = msgs.tailMap(new Integer(from)); - msgnum += (oldsize - msgs.size()); - while (msgs.size() > 0) { - Integer curuid = (Integer)msgs.firstKey(); - if (curuid.intValue() > to) { - break; - } + + Iterator it=ts.iterator(); + + while(it.hasNext()) { + Integer curuid = (Integer)it.next(); + + MailMessage mm=(MailMessage)msgs.get(curuid); - if (!this.fetch_single((MailMessage)msgs.get(msgs.firstKey()), msgnum, msg.args, 2, true)) { - this.reply(msg, "BAD Unknown attribute in list or unterminated list"); - return; + if(mm!=null) { + if (!this.fetch_single((MailMessage)msgs.get(curuid), msgnum, msg.args, 2, true)) { + this.reply(msg, "BAD Unknown attribute in list or unterminated list"); + return; + } + msgnum++; } - - msgs = msgs.tailMap(new Integer(curuid.intValue()+1)); - msgnum++; } this.reply(msg, "OK Fetch completed"); } else if (msg.args[0].equalsIgnoreCase("store")) { - int oldsize = msgs.size(); - msgs = msgs.tailMap(new Integer(from)); - int firstmsg = oldsize - msgs.size(); - msgs = msgs.headMap(new Integer(to + 1)); - - MailMessage[] targetmsgs = new MailMessage[msgs.size()]; - - for (int i = 0; i < targetmsgs.length; i++) { - targetmsgs[i] = (MailMessage)msgs.values().toArray()[i]; + MailMessage[] targetmsgs = new MailMessage[ts.size()]; + + Iterator it=ts.iterator(); + + int i=0; + while(it.hasNext()) { + Integer curuid = (Integer)it.next(); + targetmsgs[i] = (MailMessage)msgs.get(curuid); + i++; } - - this.do_store(msg.args, 2, targetmsgs, msg, firstmsg, true); - + // FIXME: firstmessage==0 is probably not right + this.do_store(msg.args, 2, targetmsgs, msg, 0, true); + this.reply(msg, "OK Store completed"); } else if (msg.args[0].equalsIgnoreCase("copy")) { - msgs = msgs.tailMap(new Integer(from)); - + if (msg.args.length < 3) { this.reply(msg, "BAD Not enough arguments"); return; @@ -479,22 +479,18 @@ } int copied = 0; - - while (msgs.size() > 0) { - Integer curuid = (Integer)msgs.firstKey(); - if (curuid.intValue() > to) { - break; - } + + Iterator it=ts.iterator(); + + while(it.hasNext()) { + Integer curuid = (Integer)it.next(); + + MailMessage srcmsg = (MailMessage)msgs.get(curuid); - MailMessage srcmsg = (MailMessage)msgs.get(msgs.firstKey()); - MailMessage copymsg = target.createMessage(); srcmsg.copyTo(copymsg); copied++; - - msgs = msgs.tailMap(new Integer(curuid.intValue()+1)); - msgnum++; } if (copied > 0) @@ -514,9 +510,12 @@ if (!imap_args[firstarg].startsWith("(")) { // It's a loner this.ps.flush(); - if (!this.send_attr(msg, imap_args[firstarg])) + if (!this.send_attr(msg, imap_args[firstarg])){ + // send fake end delimiter, so we do not break the protocol + this.ps.print(")\r\n"); + this.ps.flush(); return false; - + } if (send_uid_too && !imap_args[firstarg].equalsIgnoreCase("uid")) { this.ps.print(" UID "+msg.getUID()); } @@ -543,8 +542,12 @@ //this.ps.print(attr+" "); this.ps.flush(); - if (!this.send_attr(msg, attr)) + if (!this.send_attr(msg, attr)) { + // send fake end delimiter, so we do not break the protocol + this.ps.print(")\r\n"); + this.ps.flush(); return false; + } if (attr.equalsIgnoreCase("uid")) { send_uid_too = false;
