Changeset 689


Ignore:
Timestamp:
08/21/10 14:10:33 (18 months ago)
Author:
octorian
Message:

Conversion of connection layer to be byte-based, and complete rewrite of the IMAP paren-string parser (#224, #222)

Location:
trunk
Files:
3 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapClient.java

    r678 r689  
    917917 
    918918 
    919         String data = getMessageBody(imapMessageToken.getImapMessageUid(), partAddress, progressHandler); 
     919        byte[] data = getMessageBody(imapMessageToken.getImapMessageUid(), partAddress, progressHandler); 
    920920        MimeMessageContent content; 
    921921        try { 
    922             content = MimeMessageContentFactory.createContent(mimeMessagePart, data); 
     922            content = MimeMessageContentFactory.createContentEncoded(mimeMessagePart, data); 
    923923        } catch (UnsupportedContentException e) { 
    924924            content = null; 
     
    937937        MimeMessagePart part; 
    938938        if(MimeMessagePartFactory.isMimeMessagePartSupported(structure.type, structure.subtype)) { 
    939             String data; 
     939            byte[] data; 
    940940            if(structure.type.equalsIgnoreCase("multipart")) 
    941941                data = null; 
     
    961961                    structure.address); 
    962962            try { 
    963                 contentMap.put(part, MimeMessageContentFactory.createContent(part, data)); 
     963                contentMap.put(part, MimeMessageContentFactory.createContentEncoded(part, data)); 
    964964            } catch (UnsupportedContentException e) { 
    965965                System.err.println("UnsupportedContentException: " + e.getMessage()); 
     
    10421042    } 
    10431043 
    1044     private String getMessageBody(int uid, String address, MailProgressHandler progressHandler) throws IOException, MailException { 
     1044    private byte[] getMessageBody(int uid, String address, MailProgressHandler progressHandler) throws IOException, MailException { 
    10451045        if(activeMailbox == null) { 
    10461046            throw new MailException("Mailbox not selected"); 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapParser.java

    r656 r689  
    11/*- 
    2  * Copyright (c) 2006, Derek Konigsberg 
     2 * Copyright (c) 2010, Derek Konigsberg 
    33 * All rights reserved. 
    44 * 
     
    3232 
    3333import net.rim.device.api.system.EventLogger; 
     34import net.rim.device.api.util.Arrays; 
     35import net.rim.device.api.util.ByteVector; 
    3436 
    3537import org.logicprobe.LogicMail.AppInfo; 
    3638import org.logicprobe.LogicMail.message.MessageEnvelope; 
     39import org.logicprobe.LogicMail.util.StringArrays; 
    3740import org.logicprobe.LogicMail.util.StringParser; 
    3841 
     
    4851 */ 
    4952class ImapParser { 
    50     private static String strNIL = "NIL"; 
    51     private static String MODIFIED_BASE64_ALPHABET = 
    52         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; 
    53  
     53    private static String NIL = "NIL"; 
     54    private static String BODYSTRUCTURE = "BODYSTRUCTURE"; 
     55    private static String MODIFIED_BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; 
     56    private static Character LPAREN = new Character('('); 
     57    private static Character RPAREN = new Character(')'); 
     58    private static String US_ASCII = "US-ASCII"; 
    5459    static String FLAG_SEEN = "\\Seen"; 
    5560    static String FLAG_ANSWERED = "\\Answered"; 
     
    6166    static String FLAG_JUNK0 = "Junk"; 
    6267    static String FLAG_JUNK1 = "$Junk"; 
    63  
     68     
    6469    private ImapParser() { 
    6570    } 
     
    110115                buf.append(' '); 
    111116            } 
     117 
    112118            buf.append(FLAG_ANSWERED); 
    113119        } 
     
    117123                buf.append(' '); 
    118124            } 
     125 
    119126            buf.append(FLAG_FLAGGED); 
    120127        } 
     
    124131                buf.append(' '); 
    125132            } 
     133 
    126134            buf.append(FLAG_DELETED); 
    127135        } 
     
    131139                buf.append(' '); 
    132140            } 
     141 
    133142            buf.append(FLAG_DRAFT); 
    134143        } 
     
    138147                buf.append(' '); 
    139148            } 
     149 
    140150            buf.append(FLAG_RECENT); 
    141151        } 
     
    145155                buf.append(' '); 
    146156            } 
     157 
    147158            buf.append(FLAG_FORWARDED); 
    148159        } 
     
    163174        MessageEnvelope env = new MessageEnvelope(); 
    164175 
    165         if (parsedEnv.elementAt(0) instanceof String) { 
     176        if (parsedEnv.elementAt(0) instanceof byte[]) { 
    166177            try { 
    167                 env.date = StringParser.parseDateString((String) parsedEnv.elementAt( 
    168                             0)); 
     178                env.date = StringParser.parseDateString( 
     179                        new String((byte[]) parsedEnv.elementAt(0))); 
    169180            } catch (Exception e) { 
    170181                env.date = Calendar.getInstance().getTime(); 
    171182            } 
    172183        } 
    173  
    174         if (parsedEnv.elementAt(1) instanceof String) { 
    175             String subject = (String) parsedEnv.elementAt(1); 
    176  
    177             if (subject.equals(strNIL)) { 
    178                 env.subject = ""; 
    179             } else { 
    180                 env.subject = StringParser.parseEncodedHeader(subject); 
    181             } 
     184        else { 
     185            env.date = Calendar.getInstance().getTime(); 
     186        } 
     187 
     188        if (parsedEnv.elementAt(1) instanceof byte[]) { 
     189            env.subject = StringParser.parseEncodedHeader( 
     190                    new String((byte[])parsedEnv.elementAt(1))); 
     191        } 
     192        else { 
     193            env.subject = ""; 
    182194        } 
    183195 
     
    206218        } 
    207219 
    208         if (parsedEnv.elementAt(8) instanceof String) { 
    209             env.inReplyTo = (String) parsedEnv.elementAt(8); 
    210  
    211             if (env.inReplyTo.equals(strNIL)) { 
    212                 env.inReplyTo = ""; 
    213             } 
    214         } 
    215  
    216         if (parsedEnv.elementAt(9) instanceof String) { 
    217             env.messageId = (String) parsedEnv.elementAt(9); 
    218  
    219             if (env.messageId.equals(strNIL)) { 
    220                 env.messageId = ""; 
    221             } 
     220        if (parsedEnv.elementAt(8) instanceof byte[]) { 
     221            env.inReplyTo = new String((byte[])parsedEnv.elementAt(8)); 
     222        } 
     223        else { 
     224            env.inReplyTo = ""; 
     225        } 
     226 
     227        if (parsedEnv.elementAt(9) instanceof byte[]) { 
     228            env.messageId = new String((byte[])parsedEnv.elementAt(9)); 
     229        } 
     230        else { 
     231            env.messageId = ""; 
    222232        } 
    223233 
     
    235245                Vector entry = (Vector) addrVec.elementAt(i); 
    236246 
    237                 String realName = strNIL; 
    238  
    239                 if (entry.elementAt(0) instanceof String) { 
    240                     realName = StringParser.parseEncodedHeader((String) entry.elementAt( 
    241                                 0)); 
    242                 } 
    243  
    244                 String mbName = strNIL; 
    245  
    246                 if (entry.elementAt(2) instanceof String) { 
    247                     mbName = (String) entry.elementAt(2); 
    248                 } 
    249  
    250                 String hostName = strNIL; 
    251  
    252                 if (entry.elementAt(3) instanceof String) { 
    253                     hostName = (String) entry.elementAt(3); 
    254                 } 
    255  
    256                 String addrStr = (mbName.equals(strNIL) ? "" : mbName) + 
    257                     (hostName.equals(strNIL) ? "" : ('@' + hostName)); 
     247                String realName = NIL; 
     248 
     249                if (entry.elementAt(0) instanceof byte[]) { 
     250                    realName = StringParser.parseEncodedHeader( 
     251                            new String((byte[]) entry.elementAt(0))); 
     252                } 
     253 
     254                String mbName = NIL; 
     255 
     256                if (entry.elementAt(2) instanceof byte[]) { 
     257                    mbName = new String((byte[]) entry.elementAt(2)); 
     258                } 
     259 
     260                String hostName = NIL; 
     261 
     262                if (entry.elementAt(3) instanceof byte[]) { 
     263                    hostName = new String((byte[]) entry.elementAt(3)); 
     264                } 
     265 
     266                String addrStr = (mbName.equals(NIL) ? "" : mbName) + 
     267                    (hostName.equals(NIL) ? "" : ('@' + hostName)); 
    258268 
    259269                // Now assemble these into a single address entry 
    260270                // (possibly eventually storing them separately) 
    261                 if ((realName.length() > 0) && !realName.equals(strNIL)) { 
     271                if ((realName.length() > 0) && !realName.equals(NIL)) { 
    262272                    addrList[index] = realName + " <" + addrStr + ">"; 
    263273                } else { 
     
    288298     * @return Root of the message structure tree 
    289299     */ 
    290     static MessageSection parseMessageStructure(String rawText) { 
     300    static MessageSection parseMessageStructure(byte[] rawText) { 
    291301        Vector parsedText = null; 
    292302 
    293303        try { 
    294             parsedText = StringParser.nestedParenStringLexer(rawText.substring( 
    295                         rawText.indexOf('('))); 
     304            int offset = Arrays.getIndex(rawText, (byte)'('); 
     305            parsedText = ImapParser.parenListParser(rawText, offset, rawText.length - offset); 
    296306        } catch (Exception exp) { 
    297307            EventLogger.logEvent(AppInfo.GUID, 
     
    311321                String label = (String) parsedText.elementAt(i); 
    312322 
    313                 if (label.equalsIgnoreCase("BODYSTRUCTURE") && 
     323                if (label.equalsIgnoreCase(BODYSTRUCTURE) && 
    314324                        (i < (size - 1)) && 
    315325                        parsedText.elementAt(i + 1) instanceof Vector) { 
     
    335345    /** 
    336346     * Parse the IMAP message structure tree from a prepared object tree 
    337      * generated by {@link StringParser#nestedParenStringLexer(String)}. 
     347     * generated by {@link ImapParser#parenListParser(String)}. 
    338348     * 
    339349     * @param parsedStruct Tree containing the {@link Vector} that follows a BODYSTRUCTURE string 
     
    341351     */ 
    342352    static MessageSection parseMessageStructureParameter(Vector parsedStruct) { 
    343         MessageSection msgStructure = parseMessageStructureHelper(null, 1, parsedStruct); 
     353        MessageSection msgStructure = parseMessageStructureHelper( 
     354                null, 1, parsedStruct); 
    344355        fixMessageStructure(msgStructure); 
     356 
    345357        return msgStructure; 
    346358    } 
    347      
     359 
    348360    /** 
    349361     * This method implements a kludge to fix body part addresses 
     
    380392 
    381393        // Determine the number of body parts and parse 
    382         if (parsedStruct.elementAt(0) instanceof String) { 
     394        if (parsedStruct.elementAt(0) instanceof byte[]) { 
    383395            // The first element is a string, so we hit a simple message part 
    384396            MessageSection section = parseMessageStructureSection(parsedStruct); 
     
    396408                    subSectionsVector.addElement(parseMessageStructureHelper( 
    397409                            address, i + 1, (Vector) parsedStruct.elementAt(i))); 
    398                 } else if (parsedStruct.elementAt(i) instanceof String) { 
     410                } else if (parsedStruct.elementAt(i) instanceof byte[]) { 
    399411                    MessageSection section = new MessageSection(); 
    400412                    section.type = "multipart"; 
    401                     section.subtype = ((String) parsedStruct.elementAt(i)).toLowerCase(); 
     413                    section.subtype = (new String((byte[]) parsedStruct.elementAt(i))).toLowerCase(); 
    402414                    section.subsections = new MessageSection[subSectionsVector.size()]; 
    403415                    subSectionsVector.copyInto(section.subsections); 
     
    412424    } 
    413425 
    414     private static MessageSection parseMessageStructureSection(Vector sectionList) { 
     426    private static MessageSection parseMessageStructureSection( 
     427        Vector sectionList) { 
    415428        MessageSection sec = new MessageSection(); 
    416429        Vector tmpVec; 
    417430        int sectionListSize = sectionList.size(); 
    418431 
    419         if (sectionList.elementAt(0) instanceof String) { 
    420             sec.type = ((String) sectionList.elementAt(0)).toLowerCase(); 
    421         } 
    422  
    423         if (sectionList.elementAt(1) instanceof String) { 
    424             sec.subtype = ((String) sectionList.elementAt(1)).toLowerCase(); 
     432        if (sectionList.elementAt(0) instanceof byte[]) { 
     433            sec.type = (new String((byte[])sectionList.elementAt(0))).toLowerCase(); 
     434        } 
     435 
     436        if (sectionList.elementAt(1) instanceof byte[]) { 
     437            sec.subtype = (new String((byte[])sectionList.elementAt(1))).toLowerCase(); 
    425438        } 
    426439 
     
    431444 
    432445            int size = tmpVec.size(); 
    433             for(int i=0; i < size - 1; i+=2) { 
    434                 if(tmpVec.elementAt(i) instanceof String && 
    435                    tmpVec.elementAt(i+1) instanceof String) { 
    436                         String key = (String)tmpVec.elementAt(i); 
    437                         String value = (String)tmpVec.elementAt(i+1); 
    438                         if(key.equalsIgnoreCase("charset")) { 
    439                                 sec.charset = value; 
    440                         } 
    441                         else if(key.equalsIgnoreCase("name")) { 
    442                                 sec.name = value; 
    443                         } 
    444                 } 
    445             } 
    446         } 
    447  
    448         if (sectionList.elementAt(3) instanceof String) { 
    449                 sec.contentId = (String) sectionList.elementAt(3); 
    450         } 
    451          
    452         if (sectionList.elementAt(5) instanceof String) { 
    453             sec.encoding = ((String) sectionList.elementAt(5)).toLowerCase(); 
     446 
     447            for (int i = 0; i < (size - 1); i += 2) { 
     448                if (tmpVec.elementAt(i) instanceof byte[] && 
     449                        tmpVec.elementAt(i + 1) instanceof byte[]) { 
     450                    String key = new String((byte[]) tmpVec.elementAt(i)); 
     451                    String value = new String((byte[]) tmpVec.elementAt(i + 1)); 
     452 
     453                    if (key.equalsIgnoreCase("charset")) { 
     454                        sec.charset = value; 
     455                    } else if (key.equalsIgnoreCase("name")) { 
     456                        sec.name = value; 
     457                    } 
     458                } 
     459            } 
     460        } 
     461 
     462        if (sectionList.elementAt(3) instanceof byte[]) { 
     463            sec.contentId = new String((byte[]) sectionList.elementAt(3)); 
     464        } 
     465 
     466        if (sectionList.elementAt(5) instanceof byte[]) { 
     467            sec.encoding = new String(((byte[]) sectionList.elementAt(5))).toLowerCase(); 
    454468        } 
    455469 
     
    462476        } 
    463477 
    464         if (sectionListSize > 8 && sectionList.elementAt(8) instanceof Vector) { 
    465                 tmpVec = (Vector) sectionList.elementAt(8); 
    466                 if(tmpVec.elementAt(0) instanceof String) { 
    467                         sec.disposition = ((String)tmpVec.elementAt(0)).toLowerCase(); 
    468                 } 
    469         } 
    470          
     478        if ((sectionListSize > 8) && 
     479                sectionList.elementAt(8) instanceof Vector) { 
     480            tmpVec = (Vector) sectionList.elementAt(8); 
     481 
     482            if (tmpVec.elementAt(0) instanceof byte[]) { 
     483                sec.disposition = new String((byte[]) tmpVec.elementAt(0)).toLowerCase(); 
     484            } 
     485        } 
     486 
    471487        return sec; 
    472488    } 
     
    574590    } 
    575591 
     592    static Vector parenListLexer(byte[] rawText, int offset, int length) { 
     593        if(offset + length > rawText.length) { 
     594            throw new ArrayIndexOutOfBoundsException(); 
     595        } 
     596 
     597        Vector result = new Vector(); 
     598        ByteVector buf = new ByteVector(); 
     599 
     600        int size = offset + length; 
     601        int i = offset; 
     602 
     603        while (i < size) { 
     604            byte ch = rawText[i]; 
     605 
     606            if (ch == (byte)'(') { 
     607                result.addElement(LPAREN); 
     608                i++; 
     609            } else if (ch == (byte)')') { 
     610                result.addElement(RPAREN); 
     611                i++; 
     612            } else if (ch == (byte)'"') { 
     613                // Quoted string 
     614                i++; 
     615                buf.setSize(0); 
     616 
     617                while (i < (size - 1)) { 
     618                    ch = rawText[i]; 
     619 
     620                    if (ch == (byte)'\\') { 
     621                        byte ch1 = rawText[i + 1]; 
     622 
     623                        if (ch1 == (byte)'\\' || ch1 == (byte)'"') { 
     624                            buf.addElement(ch1); 
     625                        } 
     626 
     627                        i += 2; 
     628                    } else if (ch == '"') { 
     629                        result.addElement(buf.toArray()); 
     630                        i++; 
     631 
     632                        break; 
     633                    } else { 
     634                        buf.addElement(ch); 
     635                        i++; 
     636                    } 
     637                } 
     638            } else if (ch == '{') { 
     639                // Literal string 
     640                int p = StringArrays.indexOf(rawText, (byte)'}', i); 
     641                int len = StringArrays.parseInt(rawText, i + 1, p - i - 1); 
     642                i = p + 3; 
     643                result.addElement(Arrays.copy(rawText, i, len)); 
     644                i += len; 
     645 
     646                // Check for invalid length, etc 
     647            } else if (ch == ' ') { 
     648                // Skip the space 
     649                i++; 
     650            } else { 
     651                // Keyword 
     652                int p1 = StringArrays.indexOf(rawText, (byte)' ', i); 
     653                int p2 = StringArrays.indexOf(rawText, (byte)')', i); 
     654                int p; 
     655 
     656                if (p1 == -1) { 
     657                    p = p2; 
     658                } else if (p2 == -1) { 
     659                    p = p1; 
     660                } else { 
     661                    p = Math.min(p1, p2); 
     662                } 
     663 
     664                // check if p == -1, and bomb out 
     665                if(p == -1) { 
     666                    p = size; 
     667                } 
     668                try { 
     669                    result.addElement(new String(rawText, i, p - i, US_ASCII)); 
     670                } catch (UnsupportedEncodingException e) { 
     671                    result.addElement(new String(rawText, i, p - i)); 
     672                } 
     673 
     674                i = p; 
     675            } 
     676        } 
     677 
     678        return result; 
     679    } 
     680 
     681    /** 
     682     * Recursively parse an IMAP parenthesized string. 
     683     * <p> 
     684     * Parses through a string of the form "(A (B C (D) E F))" and 
     685     * returns a tree of representing its contents.  Each element will either 
     686     * be a <code>Vector</code>, <code>String</code>, or a <code>byte[]</code>. 
     687     * Vectors are elements that contain other elements, strings are unquoted 
     688     * elements (e.g. keywords, flags, numbers), and byte arrays are quoted 
     689     * text or literals. 
     690     * </p> 
     691     * 
     692     * @param rawText The raw text to be parsed 
     693     * @return A tree containing the parsed data 
     694     */ 
     695    static Vector parenListParser(byte[] rawText) { 
     696        return parenListParser(rawText, 0, rawText.length); 
     697    } 
     698     
     699    /** 
     700     * Recursively parse an IMAP parenthesized string. 
     701     * <p> 
     702     * Parses through a string of the form "(A (B C (D) E F))" and 
     703     * returns a tree of representing its contents.  Each element will either 
     704     * be a <code>Vector</code>, <code>String</code>, or a <code>byte[]</code>. 
     705     * Vectors are elements that contain other elements, strings are unquoted 
     706     * elements (e.g. keywords, flags, numbers), and byte arrays are quoted 
     707     * text or literals. 
     708     * </p> 
     709     * 
     710     * @param rawText The raw text to be parsed 
     711     * @param The offset to start parsing from 
     712     * @param length The length of the data to parse 
     713     * @return A tree containing the parsed data 
     714     */ 
     715    static Vector parenListParser(byte[] rawText, int offset, int length) { 
     716        Vector tokenized = parenListLexer(rawText, offset, length); 
     717        MutableInteger mutableInteger = new MutableInteger(); 
     718        Vector result = parenListParserImpl(tokenized, mutableInteger); 
     719        return result; 
     720    } 
     721 
     722    static Vector parenListParserImpl(Vector tokenized, MutableInteger index) { 
     723        Vector result = new Vector(); 
     724        Object element = tokenized.elementAt(++index.value); 
     725 
     726        while (element != RPAREN) { 
     727            if (element == LPAREN) { 
     728                result.addElement(parenListParserImpl(tokenized, index)); 
     729            } else { 
     730                result.addElement(element); 
     731            } 
     732 
     733            element = tokenized.elementAt(++index.value); 
     734        } 
     735 
     736        return result; 
     737    } 
     738 
    576739    /** 
    577740     * Simple container for a parsed message structure tree 
     
    589752        public MessageSection[] subsections; 
    590753    } 
     754 
     755    private static class MutableInteger { 
     756        public int value = 0; 
     757    } 
    591758} 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapProtocol.java

    r676 r689  
    3333import net.rim.device.api.system.EventLogger; 
    3434import net.rim.device.api.util.Arrays; 
    35 import net.rim.device.api.util.ToIntHashtable; 
     35import net.rim.device.api.util.IntIntHashtable; 
    3636 
    3737import org.logicprobe.LogicMail.AppInfo; 
     
    4040import org.logicprobe.LogicMail.message.MessageEnvelope; 
    4141import org.logicprobe.LogicMail.util.Connection; 
     42import org.logicprobe.LogicMail.util.ConnectionResponseTester; 
     43import org.logicprobe.LogicMail.util.StringArrays; 
    4244import org.logicprobe.LogicMail.util.StringParser; 
    4345 
     
    5254 */ 
    5355public class ImapProtocol { 
     56 
    5457    private Connection connection; 
    5558    private String idleCommandTag; 
    56      
     59 
    5760    /** 
    5861     * Counts the commands executed so far in this session. Every command of an 
     
    6669    } 
    6770 
    68  
    6971    /** 
    7072     * Execute the "STARTTLS" command. 
     
    7577        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    7678            EventLogger.logEvent(AppInfo.GUID, 
    77                     ("ImapProtocol.executeStartTLS()").getBytes(), 
    78                     EventLogger.DEBUG_INFO); 
    79         } 
     79                ("ImapProtocol.executeStartTLS()").getBytes(), 
     80                EventLogger.DEBUG_INFO); 
     81        } 
     82 
    8083        execute(STARTTLS, null, null); 
    8184    } 
     
    8891     */ 
    8992    public boolean executeLogin(String username, String password) 
    90     throws IOException, MailException { 
    91         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    92             EventLogger.logEvent(AppInfo.GUID, 
    93                     ("ImapProtocol.executeLogin(\"" + username + "\", \"" + 
    94                             password + "\")").getBytes(), EventLogger.DEBUG_INFO); 
     93        throws IOException, MailException { 
     94        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     95            EventLogger.logEvent(AppInfo.GUID, 
     96                ("ImapProtocol.executeLogin(\"" + username + "\", \"" + 
     97                password + "\")").getBytes(), EventLogger.DEBUG_INFO); 
    9598        } 
    9699 
     
    98101        try { 
    99102            execute(LOGIN, 
    100                     CHAR_QUOTE + StringParser.addEscapedChars(username) + "\" \"" + 
    101                     StringParser.addEscapedChars(password) + CHAR_QUOTE, null); 
     103                CHAR_QUOTE + StringParser.addEscapedChars(username) + "\" \"" + 
     104                StringParser.addEscapedChars(password) + CHAR_QUOTE, null); 
    102105        } catch (MailException exp) { 
    103106            // Invalid users are caught by execute() 
     
    115118        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    116119            EventLogger.logEvent(AppInfo.GUID, 
    117                     ("ImapProtocol.executeLogout()").getBytes(), 
    118                     EventLogger.DEBUG_INFO); 
     120                ("ImapProtocol.executeLogout()").getBytes(), 
     121                EventLogger.DEBUG_INFO); 
    119122        } 
    120123 
     
    128131        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    129132            EventLogger.logEvent(AppInfo.GUID, 
    130                     ("ImapProtocol.executeClose()").getBytes(), 
    131                     EventLogger.DEBUG_INFO); 
     133                ("ImapProtocol.executeClose()").getBytes(), 
     134                EventLogger.DEBUG_INFO); 
    132135        } 
    133136 
     
    143146        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    144147            EventLogger.logEvent(AppInfo.GUID, 
    145                     ("ImapProtocol.executeCapability()").getBytes(), 
    146                     EventLogger.DEBUG_INFO); 
     148                ("ImapProtocol.executeCapability()").getBytes(), 
     149                EventLogger.DEBUG_INFO); 
    147150        } 
    148151 
     
    170173     */ 
    171174    public NamespaceResponse executeNamespace() 
    172     throws IOException, MailException { 
    173         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    174             EventLogger.logEvent(AppInfo.GUID, 
    175                     ("ImapProtocol.executeNamespace()").getBytes(), 
    176                     EventLogger.DEBUG_INFO); 
    177         } 
    178  
    179         String[] replyText = execute(NAMESPACE, null, null); 
     175        throws IOException, MailException { 
     176        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     177            EventLogger.logEvent(AppInfo.GUID, 
     178                ("ImapProtocol.executeNamespace()").getBytes(), 
     179                EventLogger.DEBUG_INFO); 
     180        } 
     181 
     182        byte[][] replyText = executeResponse(NAMESPACE, null, null); 
    180183 
    181184        if ((replyText == null) || (replyText.length < 1)) { 
     
    183186        } 
    184187 
    185         // Assume a single-line reply 
    186         Vector tokens = StringParser.nestedParenStringLexer("(" + 
    187                 replyText[0].substring(replyText[0].indexOf('(')) + ")"); 
     188        // Assume a single-line reply, and modify that reply so its enclosed 
     189        // within a set of outer parenthesis so that the parser is happy. 
     190        int offset = Arrays.getIndex(replyText[0], (byte)'('); 
     191        byte[] data = new byte[(replyText[0].length - offset) + 2]; 
     192        data[0] = (byte)'('; 
     193        int j = 1; 
     194        for(int i=offset; i<replyText[0].length; i++) { 
     195            data[j++] = replyText[0][i]; 
     196        } 
     197        data[j] = (byte)')'; 
     198         
     199        Vector tokens = ImapParser.parenListParser(data); 
    188200 
    189201        // Sanity check on results 
     
    210222 
    211223                    if (temp.size() >= 2) { 
    212                         if (temp.elementAt(0) instanceof String) { 
    213                             response.personal[i].prefix = 
    214                                 StringParser.removeEscapedChars((String) temp.elementAt(0)); 
     224                        if (temp.elementAt(0) instanceof byte[]) { 
     225                            response.personal[i].prefix = new String((byte[]) temp.elementAt(0)); 
    215226                        } 
    216227 
    217                         if (temp.elementAt(1) instanceof String) { 
    218                             response.personal[i].delimiter = 
    219                                 StringParser.removeEscapedChars((String) temp.elementAt(1)); 
     228                        if (temp.elementAt(1) instanceof byte[]) { 
     229                            response.personal[i].delimiter = new String((byte[]) temp.elementAt(1)); 
    220230                        } 
    221231                    } 
     
    236246 
    237247                    if (temp.size() >= 2) { 
    238                         if (temp.elementAt(0) instanceof String) { 
    239                             response.other[i].prefix = 
    240                                 StringParser.removeEscapedChars((String) temp.elementAt(0)); 
     248                        if (temp.elementAt(0) instanceof byte[]) { 
     249                            response.other[i].prefix = new String((byte[]) temp.elementAt(0)); 
    241250                        } 
    242251 
    243                         if (temp.elementAt(1) instanceof String) { 
    244                             response.other[i].delimiter = 
    245                                 StringParser.removeEscapedChars((String) temp.elementAt(1)); 
     252                        if (temp.elementAt(1) instanceof byte[]) { 
     253                            response.other[i].delimiter = new String((byte[]) temp.elementAt(1)); 
    246254                        } 
    247255                    } 
     
    262270 
    263271                    if (temp.size() >= 2) { 
    264                         if (temp.elementAt(0) instanceof String) { 
    265                             response.shared[i].prefix = 
    266                                 StringParser.removeEscapedChars((String) temp.elementAt(0)); 
     272                        if (temp.elementAt(0) instanceof byte[]) { 
     273                            response.shared[i].prefix = new String((byte[]) temp.elementAt(0)); 
    267274                        } 
    268275 
    269                         if (temp.elementAt(1) instanceof String) { 
    270                             response.shared[i].delimiter = 
    271                                 StringParser.removeEscapedChars((String) temp.elementAt(1)); 
     276                        if (temp.elementAt(1) instanceof byte[]) { 
     277                            response.shared[i].delimiter = new String((byte[]) temp.elementAt(1)); 
    272278                        } 
    273279                    } 
     
    285291     */ 
    286292    public SelectResponse executeSelect(String mboxpath) 
    287     throws IOException, MailException { 
    288         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    289             EventLogger.logEvent(AppInfo.GUID, 
    290                     ("ImapProtocol.executeSelect(\"" + mboxpath + "\")").getBytes(), 
    291                     EventLogger.DEBUG_INFO); 
     293        throws IOException, MailException { 
     294        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     295            EventLogger.logEvent(AppInfo.GUID, 
     296                ("ImapProtocol.executeSelect(\"" + mboxpath + "\")").getBytes(), 
     297                EventLogger.DEBUG_INFO); 
    292298        } 
    293299 
    294300        String[] replyText = execute(SELECT, 
    295                 CHAR_QUOTE + StringParser.addEscapedChars(mboxpath) + CHAR_QUOTE, null); 
     301                CHAR_QUOTE + StringParser.addEscapedChars(mboxpath) + 
     302                CHAR_QUOTE, null); 
    296303        SelectResponse response = new SelectResponse(); 
    297304 
     
    308315                if ((q != -1) && (p != -1) && (q > p)) { 
    309316                    try { 
    310                         response.exists = Integer.parseInt( 
    311                                 rowText.substring(p + 1, q)); 
     317                        response.exists = Integer.parseInt(rowText.substring(p + 
     318                                    1, q)); 
    312319                    } catch (NumberFormatException e) { 
    313320                        response.exists = 0; 
     
    320327                if ((q != -1) && (p != -1) && (q > p)) { 
    321328                    try { 
    322                         response.recent = Integer.parseInt( 
    323                                 rowText.substring(p + 1, q)); 
     329                        response.recent = Integer.parseInt(rowText.substring(p + 
     330                                    1, q)); 
    324331                    } catch (NumberFormatException e) { 
    325332                        response.recent = 0; 
     
    332339                if ((q != -1) && (p != -1) && (q > p)) { 
    333340                    try { 
    334                         response.unseen = Integer.parseInt( 
    335                                 rowText.substring(p + 1, q)); 
     341                        response.unseen = Integer.parseInt(rowText.substring(p + 
     342                                    1, q)); 
    336343                    } catch (NumberFormatException e) { 
    337344                        response.unseen = 0; 
     
    344351                if ((q != -1) && (p != -1) && (q > p)) { 
    345352                    try { 
    346                         response.uidValidity = Integer.parseInt( 
    347                                 rowText.substring(p + 1, q)); 
     353                        response.uidValidity = Integer.parseInt(rowText.substring(p + 
     354                                    1, q)); 
    348355                    } catch (NumberFormatException e) { 
    349356                        response.uidValidity = 0; 
     
    356363                if ((q != -1) && (p != -1) && (q > p)) { 
    357364                    try { 
    358                         response.uidNext = Integer.parseInt( 
    359                                 rowText.substring(p + 1, q)); 
     365                        response.uidNext = Integer.parseInt(rowText.substring(p + 
     366                                    1, q)); 
    360367                    } catch (NumberFormatException e) { 
    361368                        response.uidNext = -1; 
     
    371378        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    372379            EventLogger.logEvent(AppInfo.GUID, 
    373                     ("ImapProtocol.executeExpunge()").getBytes(), 
    374                     EventLogger.DEBUG_INFO); 
     380                ("ImapProtocol.executeExpunge()").getBytes(), 
     381                EventLogger.DEBUG_INFO); 
    375382        } 
    376383 
     
    378385    } 
    379386 
    380     public StatusResponse[] executeStatus(String[] mboxpaths, MailProgressHandler progressHandler) 
    381     throws IOException, MailException { 
     387    public StatusResponse[] executeStatus(String[] mboxpaths, 
     388        MailProgressHandler progressHandler) throws IOException, MailException { 
    382389        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    383390            StringBuffer buf = new StringBuffer(); 
     
    394401            buf.append("})"); 
    395402            EventLogger.logEvent(AppInfo.GUID, buf.toString().getBytes(), 
    396                     EventLogger.DEBUG_INFO); 
     403                EventLogger.DEBUG_INFO); 
    397404        } 
    398405 
     
    403410 
    404411        for (i = 0; i < mboxpaths.length; i++) { 
    405             arguments[i] = CHAR_QUOTE + StringParser.addEscapedChars(mboxpaths[i]) + 
    406             "\" (MESSAGES UNSEEN)"; 
     412            arguments[i] = CHAR_QUOTE + 
     413                StringParser.addEscapedChars(mboxpaths[i]) + 
     414                "\" (MESSAGES UNSEEN)"; 
    407415        } 
    408416 
     
    427435            } 
    428436 
    429             String[] fields = StringParser.parseTokenString( 
    430                     result[i].substring(p + 1, q), CHAR_SP); 
     437            String[] fields = StringParser.parseTokenString(result[i].substring(p + 
     438                        1, q), CHAR_SP); 
    431439 
    432440            if (fields.length != 4) { 
     
    459467     * @return Array of FetchFlagsResponse objects 
    460468     */ 
    461     public FetchFlagsResponse[] executeFetchFlags( 
    462             int firstIndex, 
    463             int lastIndex, 
    464             MailProgressHandler progressHandler) throws IOException, MailException { 
    465         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    466             EventLogger.logEvent(AppInfo.GUID, 
    467                     ("ImapProtocol.executeFetchFlags(" + firstIndex + ", " + 
    468                             lastIndex + ")").getBytes(), EventLogger.DEBUG_INFO); 
    469         } 
    470  
    471         String[] rawList = execute(FETCH, 
     469    public FetchFlagsResponse[] executeFetchFlags(int firstIndex, 
     470        int lastIndex, MailProgressHandler progressHandler) 
     471        throws IOException, MailException { 
     472        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     473            EventLogger.logEvent(AppInfo.GUID, 
     474                ("ImapProtocol.executeFetchFlags(" + firstIndex + ", " + 
     475                lastIndex + ")").getBytes(), EventLogger.DEBUG_INFO); 
     476        } 
     477 
     478        byte[][] rawList = executeResponse(FETCH, 
    472479                Integer.toString(firstIndex) + CHAR_COLON + 
    473480                Integer.toString(lastIndex) + " (FLAGS UID)", progressHandler); 
     
    482489     * @return Array of FetchFlagsResponse objects 
    483490     */ 
    484     public FetchFlagsResponse[] executeFetchFlagsUid( 
    485             int uidNext, 
    486             MailProgressHandler progressHandler) throws IOException, MailException { 
    487         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    488             EventLogger.logEvent(AppInfo.GUID, 
    489                     ("ImapProtocol.executeFetchFlagsUid(" + uidNext + ")").getBytes(), 
    490                     EventLogger.DEBUG_INFO); 
    491         } 
    492  
    493         String[] rawList = execute(UID_FETCH, 
    494                 Integer.toString(uidNext) + CHAR_COLON_ASTERISK + " (FLAGS UID)", progressHandler); 
     491    public FetchFlagsResponse[] executeFetchFlagsUid(int uidNext, 
     492        MailProgressHandler progressHandler) throws IOException, MailException { 
     493        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     494            EventLogger.logEvent(AppInfo.GUID, 
     495                ("ImapProtocol.executeFetchFlagsUid(" + uidNext + ")").getBytes(), 
     496                EventLogger.DEBUG_INFO); 
     497        } 
     498 
     499        byte[][] rawList = executeResponse(UID_FETCH, 
     500                Integer.toString(uidNext) + CHAR_COLON_ASTERISK + 
     501                " (FLAGS UID)", progressHandler); 
    495502 
    496503        return prepareFetchFlagsResponse(rawList, progressHandler); 
    497504    } 
    498505 
    499     private FetchFlagsResponse[] prepareFetchFlagsResponse( 
    500             String[] rawList, MailProgressHandler progressHandler) throws IOException, MailException { 
    501  
    502         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 0, -1); } 
    503         // Preprocess the returned text to clean up mid-field line breaks 
    504         // This should all become unnecessary once execute() 
    505         // becomes more intelligent in how it handles replies 
    506         Vector rawList2 = prepareCleanFetchResponse(rawList); 
     506    private FetchFlagsResponse[] prepareFetchFlagsResponse(byte[][] rawList, 
     507        MailProgressHandler progressHandler) throws IOException, MailException { 
     508        if (progressHandler != null) { 
     509            progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 
     510                0, -1); 
     511        } 
    507512 
    508513        Vector flagResponses = new Vector(); 
    509         int size = rawList2.size(); 
    510  
    511         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 0, size); } 
    512         for (int i = 0; i < size; i++) { 
     514 
     515        if (progressHandler != null) { 
     516            progressHandler.mailProgress( 
     517                    MailProgressHandler.TYPE_PROCESSING, 0, rawList.length); 
     518        } 
     519         
     520        for (int i = 0; i < rawList.length; i++) { 
     521            byte[] rawText = rawList[i]; 
     522            if(rawText == null || rawText.length == 0 || rawText[0] != CHAR_ASTERISK) { 
     523                continue; 
     524            } 
     525             
    513526            try { 
    514                 String rawText = (String) rawList2.elementAt(i); 
    515  
    516527                Vector parsedText = null; 
    517528 
    518529                try { 
    519                     parsedText = StringParser.nestedParenStringLexer(rawText.substring( 
    520                             rawText.indexOf('('))); 
     530                    int offset = Arrays.getIndex(rawText, (byte)'('); 
     531                    parsedText = ImapParser.parenListParser(rawText, offset, rawText.length - offset); 
    521532                } catch (Exception exp) { 
    522533                    parsedText = null; 
     534 
    523535                    continue; 
    524536                } 
     
    533545                for (int j = 0; j < parsedSize; j++) { 
    534546                    if (parsedText.elementAt(j) instanceof String) { 
    535                         if (((String)parsedText.elementAt(j)).equals(FLAGS) 
    536                                 && (parsedSize > (j + 1)) 
    537                                 && parsedText.elementAt(j + 1) instanceof Vector) { 
    538                             flagRespItem.flags = ImapParser.parseMessageFlags((Vector) parsedText.elementAt(j + 1)); 
    539                         } 
    540                         else if (((String)parsedText.elementAt(j)).equals(UID) 
    541                                 && (parsedSize > (j + 1)) 
    542                                 && parsedText.elementAt(j + 1) instanceof String) { 
     547                        if (((String) parsedText.elementAt(j)).equals(FLAGS) && 
     548                                (parsedSize > (j + 1)) && 
     549                                parsedText.elementAt(j + 1) instanceof Vector) { 
     550                            flagRespItem.flags = ImapParser.parseMessageFlags((Vector) parsedText.elementAt(j + 
     551                                        1)); 
     552                        } else if (((String) parsedText.elementAt(j)).equals( 
     553                                    UID) && (parsedSize > (j + 1)) && 
     554                                parsedText.elementAt(j + 1) instanceof String) { 
    543555                            try { 
    544                                 flagRespItem.uid = Integer.parseInt((String) parsedText.elementAt(j + 1)); 
     556                                flagRespItem.uid = Integer.parseInt((String) parsedText.elementAt(j + 
     557                                            1)); 
    545558                            } catch (NumberFormatException e) { 
    546559                                flagRespItem.uid = -1; 
     
    555568 
    556569                // Find the message index in the reply 
    557                 int midx = Integer.parseInt(rawText.substring(rawText.indexOf( 
    558                 ' '), rawText.indexOf(FETCH) - 1).trim()); 
     570                int spaceIndex = Arrays.getIndex(rawText, (byte)' '); 
     571                int fetchIndex = StringArrays.indexOf(rawText, FETCH.getBytes(), spaceIndex); 
     572                int midx = StringArrays.parseInt(rawText, spaceIndex + 1, fetchIndex - spaceIndex - 2); 
    559573 
    560574                flagRespItem.index = midx; 
     
    562576            } catch (Exception exp) { 
    563577                EventLogger.logEvent(AppInfo.GUID, 
    564                         ("Parse error: " + exp).getBytes(), 
    565                         EventLogger.ERROR); 
    566             } 
    567             if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, i, size); } 
     578                    ("Parse error: " + exp).getBytes(), EventLogger.ERROR); 
     579            } 
     580 
     581            if (progressHandler != null) { 
     582                progressHandler.mailProgress( 
     583                        MailProgressHandler.TYPE_PROCESSING, i, rawList.length); 
     584            } 
    568585        } 
    569586 
    570587        FetchFlagsResponse[] result = new FetchFlagsResponse[flagResponses.size()]; 
    571588        flagResponses.copyInto(result); 
    572         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, size, size); } 
     589 
     590        if (progressHandler != null) { 
     591            progressHandler.mailProgress( 
     592                    MailProgressHandler.TYPE_PROCESSING, 
     593                    rawList.length, rawList.length); 
     594        } 
    573595 
    574596        return result; 
     
    582604     * @param progressHandler the progress handler 
    583605     */ 
    584     public void executeFetchEnvelope( 
    585             int firstIndex, 
    586             int lastIndex, 
    587             FetchEnvelopeCallback callback, 
    588             MailProgressHandler progressHandler) throws IOException, MailException { 
    589         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    590             EventLogger.logEvent(AppInfo.GUID, 
    591                     ("ImapProtocol.executeFetchEnvelope(" + firstIndex + ", " + 
    592                             lastIndex + ")").getBytes(), EventLogger.DEBUG_INFO); 
    593         } 
    594  
    595         String[] rawList = execute(FETCH, 
     606    public void executeFetchEnvelope(int firstIndex, int lastIndex, 
     607        FetchEnvelopeCallback callback, MailProgressHandler progressHandler) 
     608        throws IOException, MailException { 
     609        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     610            EventLogger.logEvent(AppInfo.GUID, 
     611                ("ImapProtocol.executeFetchEnvelope(" + firstIndex + ", " + 
     612                lastIndex + ")").getBytes(), EventLogger.DEBUG_INFO); 
     613        } 
     614 
     615        byte[][] rawList = executeResponse(FETCH, 
    596616                Integer.toString(firstIndex) + CHAR_COLON + 
    597                 Integer.toString(lastIndex) + " (FLAGS UID ENVELOPE BODYSTRUCTURE)", progressHandler); 
     617                Integer.toString(lastIndex) + 
     618                " (FLAGS UID ENVELOPE BODYSTRUCTURE)", progressHandler); 
    598619 
    599620        prepareFetchEnvelopeResponse(rawList, callback, progressHandler); 
     
    606627     * @param progressHandler the progress handler 
    607628     */ 
    608     public void executeFetchEnvelopeUid(int uidNext, FetchEnvelopeCallback callback, MailProgressHandler progressHandler) 
    609     throws IOException, MailException { 
    610         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    611             EventLogger.logEvent(AppInfo.GUID, 
    612                     ("ImapProtocol.executeFetchEnvelopeUid(" + uidNext + ")").getBytes(), 
    613                     EventLogger.DEBUG_INFO); 
    614         } 
    615  
    616         String[] rawList = execute(UID_FETCH, 
    617                 Integer.toString(uidNext) + CHAR_COLON_ASTERISK + " (FLAGS UID ENVELOPE BODYSTRUCTURE)", progressHandler); 
     629    public void executeFetchEnvelopeUid(int uidNext, 
     630        FetchEnvelopeCallback callback, MailProgressHandler progressHandler) 
     631        throws IOException, MailException { 
     632        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     633            EventLogger.logEvent(AppInfo.GUID, 
     634                ("ImapProtocol.executeFetchEnvelopeUid(" + uidNext + ")").getBytes(), 
     635                EventLogger.DEBUG_INFO); 
     636        } 
     637 
     638        byte[][] rawList = executeResponse(UID_FETCH, 
     639                Integer.toString(uidNext) + CHAR_COLON_ASTERISK + 
     640                " (FLAGS UID ENVELOPE BODYSTRUCTURE)", progressHandler); 
    618641 
    619642        prepareFetchEnvelopeResponse(rawList, callback, progressHandler); 
     
    626649     * @param progressHandler the progress handler 
    627650     */ 
    628     public void executeFetchEnvelopeUid(int[] uids, FetchEnvelopeCallback callback, MailProgressHandler progressHandler) 
    629     throws IOException, MailException { 
    630         if(uids.length == 0) { callback.responseAvailable(null); return; } 
     651    public void executeFetchEnvelopeUid(int[] uids, 
     652        FetchEnvelopeCallback callback, MailProgressHandler progressHandler) 
     653        throws IOException, MailException { 
     654        if (uids.length == 0) { 
     655            callback.responseAvailable(null); 
     656 
     657            return; 
     658        } 
     659 
    631660        StringBuffer buf = new StringBuffer(); 
    632         for(int i=0; i<uids.length - 1; i++) { 
     661 
     662        for (int i = 0; i < (uids.length - 1); i++) { 
    633663            buf.append(uids[i]); 
    634664            buf.append(','); 
    635665        } 
     666 
    636667        buf.append(uids[uids.length - 1]); 
     668 
    637669        String uidList = buf.toString(); 
    638670 
    639671        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    640672            EventLogger.logEvent(AppInfo.GUID, 
    641                     ("ImapProtocol.executeFetchEnvelopeUid(" + uidList + ")").getBytes(), 
    642                     EventLogger.DEBUG_INFO); 
    643         } 
    644  
    645         String[] rawList = execute(UID_FETCH, 
     673                ("ImapProtocol.executeFetchEnvelopeUid(" + uidList + ")").getBytes(), 
     674                EventLogger.DEBUG_INFO); 
     675        } 
     676 
     677        byte[][] rawList = executeResponse(UID_FETCH, 
    646678                uidList + " (FLAGS UID ENVELOPE BODYSTRUCTURE)", progressHandler); 
    647679 
     
    649681    } 
    650682 
    651     private void prepareFetchEnvelopeResponse( 
    652             String[] rawList, FetchEnvelopeCallback callback, MailProgressHandler progressHandler) throws IOException, MailException { 
    653  
    654         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 0, -1); } 
    655         // Preprocess the returned text to clean up mid-field line breaks 
    656         // This should all become unnecessary once execute() 
    657         // becomes more intelligent in how it handles replies 
    658         Vector rawList2 = prepareCleanFetchResponse(rawList); 
    659  
    660         int size = rawList2.size(); 
    661  
    662         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 0, size); } 
    663         for (int i = 0; i < size; i++) { 
     683    private void prepareFetchEnvelopeResponse(byte[][] rawList, 
     684        FetchEnvelopeCallback callback, MailProgressHandler progressHandler) 
     685        throws IOException, MailException { 
     686        if (progressHandler != null) { 
     687            progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 
     688                0, -1); 
     689        } 
     690 
     691        if (progressHandler != null) { 
     692            progressHandler.mailProgress( 
     693                    MailProgressHandler.TYPE_PROCESSING, 0, rawList.length); 
     694        } 
     695 
     696        for (int i = 0; i < rawList.length; i++) { 
     697            byte[] rawText = rawList[i]; 
     698            if(rawText == null || rawText.length == 0 || rawText[0] != CHAR_ASTERISK) { 
     699                continue; 
     700            } 
     701             
    664702            FetchEnvelopeResponse envRespItem = null; 
    665703            try { 
    666                 String rawText = (String) rawList2.elementAt(i); 
    667  
    668704                MessageEnvelope env = null; 
    669705                ImapParser.MessageSection structure = null; 
     
    671707 
    672708                try { 
    673                     parsedText = StringParser.nestedParenStringLexer(rawText.substring( 
    674                             rawText.indexOf('('))); 
     709                    int offset = Arrays.getIndex(rawText, (byte)'('); 
     710                    parsedText = ImapParser.parenListParser(rawText, offset, rawText.length - offset); 
    675711                } catch (Exception exp) { 
    676712                    continue; 
     
    685721 
    686722                for (int j = 0; j < parsedSize; j++) { 
    687                     if (parsedText.elementAt(j) instanceof String) { 
    688                         if (((String)parsedText.elementAt(j)).equals(FLAGS) 
    689                                 && (parsedSize > (j + 1)) 
    690                                 && parsedText.elementAt(j + 1) instanceof Vector) { 
    691                             envRespItem.flags = ImapParser.parseMessageFlags((Vector) parsedText.elementAt(j + 1)); 
     723                    if (FLAGS.equals(parsedText.elementAt(j)) 
     724                            && (parsedSize > (j + 1)) 
     725                            && parsedText.elementAt(j + 1) instanceof Vector) { 
     726                        envRespItem.flags = ImapParser.parseMessageFlags((Vector) parsedText.elementAt(j + 1)); 
     727                    } 
     728                    else if (UID.equals(parsedText.elementAt(j)) 
     729                            && (parsedSize > (j + 1)) 
     730                            && parsedText.elementAt(j + 1) instanceof String) { 
     731                        try { 
     732                            envRespItem.uid = Integer.parseInt((String) parsedText.elementAt(j + 1)); 
     733                        } catch (NumberFormatException e) { 
     734                            envRespItem.uid = -1; 
    692735                        } 
    693                         else if (((String)parsedText.elementAt(j)).equals(UID) 
    694                                 && (parsedSize > (j + 1)) 
    695                                 && parsedText.elementAt(j + 1) instanceof String) { 
    696                             try { 
    697                                 envRespItem.uid = Integer.parseInt((String) parsedText.elementAt(j + 1)); 
    698                             } catch (NumberFormatException e) { 
    699                                 envRespItem.uid = -1; 
    700                             } 
    701                         } 
    702                         else if (((String)parsedText.elementAt(j)).equals(ENVELOPE) 
    703                                 && (parsedSize > (j + 1)) 
    704                                 && parsedText.elementAt(j + 1) instanceof Vector) { 
    705                             env = ImapParser.parseMessageEnvelope((Vector) parsedText.elementAt(j + 1)); 
    706                         } 
    707                         else if (((String)parsedText.elementAt(j)).equals(BODYSTRUCTURE) 
    708                                 && (parsedSize > (j + 1)) 
    709                                 && parsedText.elementAt(j + 1) instanceof Vector) { 
    710                             structure = ImapParser.parseMessageStructureParameter( 
    711                                     (Vector)parsedText.elementAt(j + 1)); 
    712                         } 
     736                    } 
     737                    else if (ENVELOPE.equals(parsedText.elementAt(j)) 
     738                            && (parsedSize > (j + 1)) 
     739                            && parsedText.elementAt(j + 1) instanceof Vector) { 
     740                        env = ImapParser.parseMessageEnvelope((Vector) parsedText.elementAt(j + 1)); 
     741                    } 
     742                    else if (BODYSTRUCTURE.equals(parsedText.elementAt(j)) 
     743                            && (parsedSize > (j + 1)) 
     744                            && parsedText.elementAt(j + 1) instanceof Vector) { 
     745                        structure = ImapParser.parseMessageStructureParameter((Vector) parsedText.elementAt(j + 1)); 
    713746                    } 
    714747                } 
     
    725758 
    726759                // Find the message index in the reply 
    727                 int midx = Integer.parseInt(rawText.substring(rawText.indexOf( 
    728                 ' '), rawText.indexOf(FETCH) - 1).trim()); 
     760                int spaceIndex = Arrays.getIndex(rawText, (byte)' '); 
     761                int fetchIndex = StringArrays.indexOf(rawText, FETCH.getBytes(), spaceIndex); 
     762                int midx = StringArrays.parseInt(rawText, spaceIndex + 1, fetchIndex - spaceIndex - 2); 
    729763 
    730764                envRespItem.index = midx; 
     
    733767            } catch (Exception exp) { 
    734768                EventLogger.logEvent(AppInfo.GUID, 
    735                         ("Parse error: " + exp).getBytes(), 
    736                         EventLogger.ERROR); 
     769                    ("Parse error: " + exp).getBytes(), EventLogger.ERROR); 
    737770                envRespItem = null; 
    738771            } 
    739             if(envRespItem != null) { 
     772 
     773            if (envRespItem != null) { 
    740774                callback.responseAvailable(envRespItem); 
    741775            } 
    742             if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, i, size); } 
     776 
     777            if (progressHandler != null) { 
     778                progressHandler.mailProgress( 
     779                        MailProgressHandler.TYPE_PROCESSING, i, rawList.length); 
     780            } 
    743781        } 
    744782 
    745783        callback.responseAvailable(null); 
    746     } 
    747  
    748     private static Vector prepareCleanFetchResponse(String[] rawList) { 
    749         Vector cleanList = new Vector(); 
    750         String line; 
    751         StringBuffer lineBuf = new StringBuffer(); 
    752         for (int i = 0; i < rawList.length; i++) { 
    753             line = rawList[i]; 
    754  
    755             if ((line.length() > 0) && lineBuf.toString().startsWith(CHAR_ASTERISK_SP) && 
    756                     line.startsWith(CHAR_ASTERISK_SP)) { 
    757                 cleanList.addElement(lineBuf.toString()); 
    758                 lineBuf = new StringBuffer(); 
    759             } 
    760  
    761             lineBuf.append(line); 
    762  
    763             if ((i == (rawList.length - 1)) && 
    764                     lineBuf.toString().startsWith(CHAR_ASTERISK_SP)) { 
    765                 cleanList.addElement(lineBuf.toString()); 
    766             } 
    767         } 
    768         return cleanList; 
    769784    } 
    770785 
     
    775790     */ 
    776791    public ImapParser.MessageSection executeFetchBodystructure(int uid) 
    777     throws IOException, MailException { 
    778         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    779             EventLogger.logEvent(AppInfo.GUID, 
    780                     ("ImapProtocol.executeFetchBodyStructure(" + uid + ")").getBytes(), 
    781                     EventLogger.DEBUG_INFO); 
    782         } 
    783  
    784         String[] rawList = execute(UID_FETCH, uid + " (BODYSTRUCTURE)", null); 
    785  
    786         // Pre-process the returned text to clean up mid-field line breaks 
    787         // This should all become unnecessary once execute() 
    788         // becomes more intelligent in how it handles replies 
    789         String line; 
    790         StringBuffer lineBuf = new StringBuffer(); 
    791         Vector rawList2 = new Vector(); 
     792        throws IOException, MailException { 
     793        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     794            EventLogger.logEvent(AppInfo.GUID, 
     795                ("ImapProtocol.executeFetchBodyStructure(" + uid + ")").getBytes(), 
     796                EventLogger.DEBUG_INFO); 
     797        } 
     798 
     799        byte[][] rawList = executeResponse(UID_FETCH, uid + " (BODYSTRUCTURE)", null); 
     800 
     801        ImapParser.MessageSection msgStructure = null; 
    792802 
    793803        for (int i = 0; i < rawList.length; i++) { 
    794             line = rawList[i]; 
    795  
    796             if ((line.length() > 0) && lineBuf.toString().startsWith(CHAR_ASTERISK_SP) && 
    797                     line.startsWith(CHAR_ASTERISK_SP)) { 
    798                 rawList2.addElement(lineBuf.toString()); 
    799                 lineBuf = new StringBuffer(); 
    800             } 
    801  
    802             lineBuf.append(line); 
    803  
    804             if ((i == (rawList.length - 1)) && 
    805                     lineBuf.toString().startsWith(CHAR_ASTERISK_SP)) { 
    806                 rawList2.addElement(lineBuf.toString()); 
    807             } 
    808         } 
    809  
    810         ImapParser.MessageSection msgStructure = null; 
    811         int size = rawList2.size(); 
    812  
    813         for (int i = 0; i < size; i++) { 
     804            byte[] rawText = rawList[i]; 
     805            if(rawText == null || rawText.length == 0 || rawText[0] != CHAR_ASTERISK) { 
     806                continue; 
     807            } 
     808             
    814809            try { 
    815                 msgStructure = ImapParser.parseMessageStructure((String) rawList2.elementAt(i)); 
     810                msgStructure = ImapParser.parseMessageStructure(rawText); 
    816811            } catch (Exception exp) { 
    817812                EventLogger.logEvent(AppInfo.GUID, 
    818                         ("Parse error: " + exp).getBytes(), 
    819                         EventLogger.ERROR); 
     813                    ("Parse error: " + exp).getBytes(), EventLogger.ERROR); 
    820814            } 
    821815        } 
     
    831825     * @return Body text as a string 
    832826     */ 
    833     public String executeFetchBody(int uid, String address, MailProgressHandler progressHandler) 
    834     throws IOException, MailException { 
    835         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    836             EventLogger.logEvent(AppInfo.GUID, 
    837                     ("ImapProtocol.executeFetchBody(" + uid + ", \"" + address + 
    838                     "\")").getBytes(), EventLogger.DEBUG_INFO); 
    839         } 
    840  
    841         String[] rawList = execute( 
    842                 UID_FETCH, 
    843                 uid + " (BODY[" + address + "])", 
    844                 progressHandler); 
    845  
    846         if (rawList.length <= 1) { 
    847             return ""; 
    848         } 
    849  
    850         // Attempt to parse the message length out of the first line of the response 
    851         int p = rawList[0].indexOf('{'); 
    852         int q = rawList[0].indexOf('}'); 
    853         int messageLength = -1; 
    854  
    855         if ((p != -1) && (q != -1) && ((q - p) > 1)) { 
    856             try { 
    857                 messageLength = Integer.parseInt(rawList[0].substring(p + 1, q)); 
    858             } catch (NumberFormatException e) { 
    859                 messageLength = -1; 
    860             } 
    861         } 
    862  
    863         StringBuffer msgBuf = new StringBuffer(); 
    864  
    865         if (messageLength != -1) { 
    866             for (int i = 1; i < rawList.length; i++) { 
    867                 int rawListLength = rawList[i].length(); 
    868                 if ((rawListLength + 2) <= messageLength) { 
    869                     msgBuf.append(rawList[i]); 
    870                     messageLength -= rawListLength; 
    871                     msgBuf.append(CRLF); 
    872                     messageLength -= 2; 
    873                 } else if (!(messageLength == 1 && rawListLength == 1 && rawList[i].charAt(0) == ')')) { 
    874                     msgBuf.append(rawList[i].substring(0, messageLength)); 
    875                 } 
    876             } 
    877         } else { 
    878             // Workaround for mail servers that sometimes append untagged 
    879             // replies to the end of this response 
    880             int lastLineIndex = rawList.length - 1; 
    881  
    882             while ((lastLineIndex > 0) && rawList[lastLineIndex].startsWith(CHAR_ASTERISK_SP)) { 
    883                 lastLineIndex--; 
    884             } 
    885  
    886             for (int i = 1; i < lastLineIndex; i++) { 
    887                 msgBuf.append(rawList[i]); 
    888                 msgBuf.append(CRLF); 
    889             } 
    890  
    891             String lastLine = rawList[lastLineIndex]; 
    892             msgBuf.append(lastLine.substring(0, lastLine.lastIndexOf(')'))); 
    893         } 
    894  
    895         return msgBuf.toString(); 
     827    public byte[] executeFetchBody(int uid, String address, 
     828        MailProgressHandler progressHandler) throws IOException, MailException { 
     829        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     830            EventLogger.logEvent(AppInfo.GUID, 
     831                ("ImapProtocol.executeFetchBody(" + uid + ", \"" + address + 
     832                "\")").getBytes(), EventLogger.DEBUG_INFO); 
     833        } 
     834 
     835        byte[][] rawList = executeResponse(UID_FETCH, 
     836                uid + " (BODY[" + address + "])", progressHandler); 
     837 
     838        if (rawList.length < 1) { 
     839            return new byte[0]; 
     840        } 
     841 
     842        int offset = Arrays.getIndex(rawList[0], (byte)'('); 
     843        Vector parsedList = ImapParser.parenListParser(rawList[0], offset, rawList[0].length - offset); 
     844        int size = parsedList.size(); 
     845         
     846        byte[] rawMessage = null; 
     847        for(int i=0; i<(size - 1); i++) { 
     848            Object element = parsedList.elementAt(i); 
     849            if(element instanceof String 
     850                    && ((String)element).startsWith(BODY) 
     851                    && parsedList.elementAt(i + 1) instanceof byte[]) { 
     852                rawMessage = (byte[])parsedList.elementAt(i + 1); 
     853            } 
     854        } 
     855 
     856        if(rawMessage == null) { 
     857            rawMessage = new byte[0]; 
     858        } 
     859 
     860 
     861        return rawMessage; 
    896862    } 
    897863 
     
    903869     * @return Updated standard message flags, or null if there was a parse error. 
    904870     */ 
    905     public MessageFlags executeStore(int uid, boolean addOrRemove, String[] flags) 
    906     throws IOException, MailException { 
     871    public MessageFlags executeStore(int uid, boolean addOrRemove, 
     872        String[] flags) throws IOException, MailException { 
    907873        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    908874            StringBuffer buf = new StringBuffer(); 
     
    919885 
    920886            EventLogger.logEvent(AppInfo.GUID, 
    921                     ("ImapProtocol.executeStore(" + uid + ", " + 
    922                             (addOrRemove ? "add" : "remove") + ", {" + buf.toString() + 
    923                     "})").getBytes(), EventLogger.DEBUG_INFO); 
     887                ("ImapProtocol.executeStore(" + uid + ", " + 
     888                (addOrRemove ? "add" : "remove") + ", {" + buf.toString() + 
     889                "})").getBytes(), EventLogger.DEBUG_INFO); 
    924890        } 
    925891 
     
    947913 
    948914        MessageFlags result; 
     915 
    949916        try { 
    950917            int p = rawList[0].indexOf('('); 
    951918            int q = rawList[0].lastIndexOf(')'); 
    952919            Vector tokenVec = null; 
     920 
    953921            if ((p != -1) && (q != -1) && (p < q)) { 
    954                 Vector parsedText = 
    955                     StringParser.nestedParenStringLexer(rawList[0].substring(p, q + 1)); 
     922                Vector parsedText = ImapParser.parenListParser( 
     923                        rawList[0].substring(p, q + 1).getBytes()); 
    956924                int size = parsedText.size(); 
    957                 for(int i=0; i<size; i++) { 
     925 
     926                for (int i = 0; i < size; i++) { 
    958927                    Object element = parsedText.elementAt(i); 
    959                     if(element instanceof String 
    960                             && element.equals(FLAGS) 
    961                             && i < size - 1 
    962                             && parsedText.elementAt(i + 1) instanceof Vector) { 
    963                         tokenVec = (Vector)parsedText.elementAt(i + 1); 
     928 
     929                    if (element instanceof String && element.equals(FLAGS) && 
     930                            (i < (size - 1)) && 
     931                            parsedText.elementAt(i + 1) instanceof Vector) { 
     932                        tokenVec = (Vector) parsedText.elementAt(i + 1); 
     933 
    964934                        break; 
    965935                    } 
     
    967937            } 
    968938 
    969             if(tokenVec != null) { 
     939            if (tokenVec != null) { 
    970940                result = ImapParser.parseMessageFlags(tokenVec); 
    971             } 
    972             else { 
     941            } else { 
    973942                result = null; 
    974943            } 
    975944        } catch (Exception e) { 
    976945            EventLogger.logEvent(AppInfo.GUID, 
    977                     ("Unable to parse STORE response: " + e.toString()).getBytes(), 
    978                     EventLogger.ERROR); 
     946                ("Unable to parse STORE response: " + e.toString()).getBytes(), 
     947                EventLogger.ERROR); 
    979948 
    980949            result = null; 
    981950        } 
     951 
    982952        return result; 
    983953    } 
     
    990960     */ 
    991961    public void executeAppend(String mboxName, String rawMessage, 
    992             MessageFlags flags) throws IOException, MailException { 
     962        MessageFlags flags) throws IOException, MailException { 
    993963        String flagsString = ImapParser.createMessageFlagsString(flags); 
    994964 
    995965        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    996966            EventLogger.logEvent(AppInfo.GUID, 
    997                     ("ImapProtocol.executeAppend(rawMessage, \"" + flagsString + 
    998                     "\")").getBytes(), EventLogger.DEBUG_INFO); 
     967                ("ImapProtocol.executeAppend(rawMessage, \"" + flagsString + 
     968                "\")").getBytes(), EventLogger.DEBUG_INFO); 
    999969        } 
    1000970 
    1001971        executeContinue(APPEND, 
    1002                 CHAR_QUOTE + StringParser.addEscapedChars(mboxName) + "\" (" + 
    1003                 flagsString + ") {" + rawMessage.length() + "}", rawMessage, 
    1004                 "Unable to append message to " + mboxName); 
     972            CHAR_QUOTE + StringParser.addEscapedChars(mboxName) + "\" (" + 
     973            flagsString + ") {" + rawMessage.length() + "}", rawMessage, 
     974            "Unable to append message to " + mboxName); 
    1005975    } 
    1006976 
     
    1008978     * Execute the "COPY" command to copy a message from the current mailbox 
    1009979     * to a different mailbox. 
    1010      *  
    1011      * @param uid The IMAP unique ID of the message to copy.  
     980     * 
     981     * @param uid The IMAP unique ID of the message to copy. 
    1012982     * @param mboxPath The path of the destination mailbox 
    1013983     */ 
    1014     public void executeCopy(int uid, String mboxPath) throws IOException, MailException { 
    1015         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    1016             EventLogger.logEvent(AppInfo.GUID, 
    1017                     ("ImapProtocol.executeCopy(\"" + uid + "\", \"" + mboxPath + 
    1018                     "\")").getBytes(), EventLogger.DEBUG_INFO); 
     984    public void executeCopy(int uid, String mboxPath) 
     985        throws IOException, MailException { 
     986        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     987            EventLogger.logEvent(AppInfo.GUID, 
     988                ("ImapProtocol.executeCopy(\"" + uid + "\", \"" + mboxPath + 
     989                "\")").getBytes(), EventLogger.DEBUG_INFO); 
    1019990        } 
    1020991 
    1021992        execute(UID_COPY, 
    1022                 uid + " \"" + StringParser.addEscapedChars(mboxPath) + CHAR_QUOTE, 
    1023                 null); 
     993            uid + " \"" + StringParser.addEscapedChars(mboxPath) + CHAR_QUOTE, 
     994            null); 
    1024995    } 
    1025996 
    1026997    /** 
    1027998     * Execute the "LIST" command, and return a fully parsed response. 
    1028      *  
     999     * 
    10291000     * @param refName Reference name 
    10301001     * @param mboxName Mailbox name or wildcards (i.e. "%") 
     
    10321003     * @return Vector of ListResponse objects 
    10331004     */ 
    1034     public Vector executeList(String refName, String mboxName, MailProgressHandler progressHandler) 
    1035     throws IOException, MailException { 
     1005    public Vector executeList(String refName, String mboxName, 
     1006        MailProgressHandler progressHandler) throws IOException, MailException { 
    10361007        // 
    10371008        // The default behavior should be to use executeListSubscribed. 
     
    10451016    /** 
    10461017     * Execute the "LSUB" command, and return a fully parsed response. 
    1047      *  
     1018     * 
    10481019     * @param refName Reference name 
    10491020     * @param mboxName Mailbox name or wildcards (i.e. "%") 
     
    10511022     * @return Vector of ListResponse objects 
    10521023     */ 
    1053     public Vector executeLsub(String refName, String mboxName, MailProgressHandler progressHandler) 
    1054     throws IOException, MailException { 
     1024    public Vector executeLsub(String refName, String mboxName, 
     1025        MailProgressHandler progressHandler) throws IOException, MailException { 
    10551026        return executeListImpl(LSUB, refName, mboxName, progressHandler); 
    10561027    } 
    10571028 
    1058     private Vector executeListImpl(String ListVerb, String refName, String mboxName, MailProgressHandler progressHandler) 
    1059     throws IOException, MailException { 
    1060         if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    1061             EventLogger.logEvent(AppInfo.GUID, 
    1062                     ("ImapProtocol.executeList(\"" + refName + "\", \"" + mboxName + 
    1063                     "\")").getBytes(), EventLogger.DEBUG_INFO); 
     1029    private Vector executeListImpl(String ListVerb, String refName, 
     1030        String mboxName, MailProgressHandler progressHandler) 
     1031        throws IOException, MailException { 
     1032        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     1033            EventLogger.logEvent(AppInfo.GUID, 
     1034                ("ImapProtocol.executeList(\"" + refName + "\", \"" + mboxName + 
     1035                "\")").getBytes(), EventLogger.DEBUG_INFO); 
    10641036        } 
    10651037 
     
    10671039        results = execute(ListVerb, 
    10681040                CHAR_QUOTE + StringParser.addEscapedChars(refName) + "\" \"" + 
    1069                 StringParser.addEscapedChars(mboxName) + CHAR_QUOTE, progressHandler); 
     1041                StringParser.addEscapedChars(mboxName) + CHAR_QUOTE, 
     1042                progressHandler); 
    10701043 
    10711044        Vector retVec = new Vector(results.length); 
     
    10811054        int line = 0; 
    10821055 
    1083         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 0, -1); } 
     1056        if (progressHandler != null) { 
     1057            progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 
     1058                0, -1); 
     1059        } 
    10841060 
    10851061        StringBuffer buf = new StringBuffer(); 
     1062 
    10861063        while (line < results.length) { 
    10871064            p = results[line].indexOf('{'); 
     
    10911068                    (p < q) && (q == (results[line].length() - 1))) { 
    10921069                int len = Integer.parseInt(results[line].substring(p + 1, q)); 
    1093                  
     1070 
    10941071                buf.append(results[line].substring(0, p)); 
    10951072                buf.append('"'); 
     
    11071084        int resultsSize = resultsVec.size(); 
    11081085 
    1109         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 0, resultsSize); } 
     1086        if (progressHandler != null) { 
     1087            progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 
     1088                0, resultsSize); 
     1089        } 
     1090 
    11101091        for (int i = 0; i < resultsSize; i++) { 
    11111092            // Separate out the flag and argument strings 
     
    11251106 
    11261107            // List response is invalid if both parts are not available 
    1127             if(flagStr == null || argStr == null) { continue; } 
    1128              
     1108            if ((flagStr == null) || (argStr == null)) { 
     1109                continue; 
     1110            } 
     1111 
    11291112            response = new ListResponse(); 
    11301113            response.delim = ""; 
     
    11361119            response.noInferiors = (flagStr.indexOf(FLAG_NOINFERIORS) != -1); 
    11371120            response.marked = (flagStr.indexOf(FLAG_MARKED) != -1); 
     1121 
    11381122            try { 
    11391123                p = 0; 
     
    11981182                // Prevent parse errors from being fatal 
    11991183            } 
    1200             if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, i, resultsSize); } 
    1201         } 
    1202         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, resultsSize, resultsSize); } 
     1184 
     1185            if (progressHandler != null) { 
     1186                progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 
     1187                    i, resultsSize); 
     1188            } 
     1189        } 
     1190 
     1191        if (progressHandler != null) { 
     1192            progressHandler.mailProgress(MailProgressHandler.TYPE_PROCESSING, 
     1193                resultsSize, resultsSize); 
     1194        } 
    12031195 
    12041196        return retVec; 
     
    12131205        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    12141206            EventLogger.logEvent(AppInfo.GUID, 
    1215                     ("ImapProtocol.executeNoop()").getBytes(), 
    1216                     EventLogger.DEBUG_INFO); 
    1217         } 
     1207                ("ImapProtocol.executeNoop()").getBytes(), 
     1208                EventLogger.DEBUG_INFO); 
     1209        } 
     1210 
    12181211        String[] replyText = execute(NOOP, null, null); 
    12191212 
    12201213        if ((replyText == null) || (replyText.length < 1)) { 
    12211214            EventLogger.logEvent(AppInfo.GUID, 
    1222                     ("Unable to read NOOP response").getBytes(), 
    1223                     EventLogger.WARNING); 
     1215                ("Unable to read NOOP response").getBytes(), EventLogger.WARNING); 
     1216 
    12241217            return false; 
    12251218        } 
    12261219 
    1227         for(int i=0; i<replyText.length; i++) { 
    1228             if(replyText[i].startsWith(CHAR_ASTERISK) && replyText[i].toLowerCase().endsWith("recent")) { 
     1220        for (int i = 0; i < replyText.length; i++) { 
     1221            if (replyText[i].startsWith(ASTERISK) && 
     1222                    replyText[i].toLowerCase().endsWith("recent")) { 
    12291223                return true; 
    12301224            } 
     
    12401234        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    12411235            EventLogger.logEvent(AppInfo.GUID, 
    1242                     ("ImapProtocol.executeIdle()").getBytes(), 
    1243                     EventLogger.DEBUG_INFO); 
     1236                ("ImapProtocol.executeIdle()").getBytes(), 
     1237                EventLogger.DEBUG_INFO); 
    12441238        } 
    12451239 
     
    12531247        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
    12541248            EventLogger.logEvent(AppInfo.GUID, 
    1255                     ("ImapProtocol.executeIdleDone()").getBytes(), 
    1256                     EventLogger.DEBUG_INFO); 
     1249                ("ImapProtocol.executeIdleDone()").getBytes(), 
     1250                EventLogger.DEBUG_INFO); 
    12571251        } 
    12581252 
     
    12701264        String result = receive(); 
    12711265 
    1272         if ((result != null) && result.startsWith(CHAR_ASTERISK) && 
     1266        if ((result != null) && result.startsWith(ASTERISK) && 
    12731267                result.toLowerCase().endsWith("recent")) { 
    12741268            return true; 
     
    12861280     * @return List of returned strings 
    12871281     */ 
    1288     protected String[] executeBatch(String command, String[] arguments, MailProgressHandler progressHandler) 
    1289     throws IOException, MailException { 
     1282    protected String[] executeBatch(String command, String[] arguments, 
     1283        MailProgressHandler progressHandler) throws IOException, MailException { 
    12901284        String[] result = new String[arguments.length]; 
    12911285        int count = 0; 
    12921286 
    1293         ToIntHashtable commandMap = new ToIntHashtable(); 
     1287        IntIntHashtable commandMap = new IntIntHashtable(); 
    12941288        StringBuffer commandBuf = new StringBuffer(); 
    12951289 
    12961290        for (int i = 0; i < arguments.length; i++) { 
    12971291            String tag = TAG_PREFIX + (commandCount++); 
    1298             commandMap.put(tag, i); 
     1292            commandMap.put(StringArrays.hashCode(tag.getBytes()), i); 
    12991293            commandBuf.append(tag); 
    13001294            commandBuf.append(' '); 
    13011295            commandBuf.append(command); 
    1302             commandBuf.append(((arguments[i] == null) ? "" : (CHAR_SP + 
    1303                     arguments[i]))); 
     1296            commandBuf.append(((arguments[i] == null) ? "" 
     1297                                                      : (CHAR_SP + 
     1298                arguments[i]))); 
    13041299            commandBuf.append(CRLF); 
    13051300        } 
     
    13071302        int preCount = connection.getBytesReceived(); 
    13081303        connection.sendRaw(commandBuf.toString()); 
     1304 
    13091305        int postCount = connection.getBytesReceived(); 
    1310         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, (postCount - preCount), -1); } 
    1311  
    1312         String temp; 
     1306 
     1307        if (progressHandler != null) { 
     1308            progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, 
     1309                (postCount - preCount), -1); 
     1310        } 
     1311 
     1312        byte[] temp; 
    13131313        String tempResult = ""; 
    13141314        int p; 
     
    13181318            temp = connection.receive(); 
    13191319            postCount = connection.getBytesReceived(); 
    1320             if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, (postCount - preCount), -1); } 
    1321  
    1322             String temp2 = temp.substring(temp.indexOf(CHAR_SP) + 1); 
    1323  
    1324             if (temp2.startsWith(BAD_PREFIX) || temp2.startsWith(NO_PREFIX)) { 
    1325                 throw new MailException(temp); 
    1326             } 
    1327  
    1328             p = temp.indexOf(CHAR_SP); 
    1329  
    1330             if ((p != -1) && commandMap.containsKey(temp.substring(0, p))) { 
    1331                 result[commandMap.get(temp.substring(0, p))] = tempResult; 
     1320 
     1321            if (progressHandler != null) { 
     1322                progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, 
     1323                    (postCount - preCount), -1); 
     1324            } 
     1325 
     1326            p = Arrays.getIndex(temp, (byte) ' '); 
     1327 
     1328            if ((StringArrays.indexOf(temp, BAD_PREFIX, p + 1) != -1) || 
     1329                    (StringArrays.indexOf(temp, NO_PREFIX, p + 1) != -1)) { 
     1330                throw new MailException(new String(temp)); 
     1331            } 
     1332 
     1333            int keyHashCode = StringArrays.hashCode(temp, 0, p); 
     1334 
     1335            if ((p != -1) && commandMap.containsKey(keyHashCode)) { 
     1336                result[commandMap.get(keyHashCode)] = tempResult; 
    13321337                tempResult = ""; 
    13331338                count++; 
    13341339            } else { 
    1335                 tempResult = temp; 
     1340                tempResult = new String(temp); 
    13361341            } 
    13371342        } 
     
    13481353     * @return List of returned strings 
    13491354     */ 
    1350     protected String[] execute(String command, String arguments, MailProgressHandler progressHandler) 
    1351     throws IOException, MailException { 
    1352         String[] result = new String[0]; 
     1355    protected byte[][] executeResponse(String command, String arguments, 
     1356        MailProgressHandler progressHandler) throws IOException, MailException { 
     1357        byte[][] result = new byte[0][]; 
    13531358 
    13541359        String tag = TAG_PREFIX + commandCount++ + CHAR_SP; 
    13551360        connection.sendCommand(tag + command + 
    1356                 ((arguments == null) ? "" : (CHAR_SP + arguments))); 
     1361            ((arguments == null) ? "" : (CHAR_SP + arguments))); 
     1362 
     1363        byte[] tagBytes = tag.getBytes(); 
    13571364 
    13581365        int preCount = connection.getBytesReceived(); 
    1359         String temp = connection.receive(); 
     1366        byte[] temp = connection.receive(executeResponseTester); 
    13601367        int postCount = connection.getBytesReceived(); 
    1361         if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, (postCount - preCount), -1); } 
    1362  
    1363         while (!temp.startsWith(tag)) { 
     1368 
     1369        if (progressHandler != null) { 
     1370            progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, 
     1371                (postCount - preCount), -1); 
     1372        } 
     1373 
     1374        while (!StringArrays.startsWith(temp, tagBytes)) { 
    13641375            Arrays.add(result, temp); 
     1376            preCount = postCount; 
     1377            temp = connection.receive(executeResponseTester); 
     1378            postCount = connection.getBytesReceived(); 
     1379 
     1380            if (progressHandler != null) { 
     1381                progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, 
     1382                    (postCount - preCount), -1); 
     1383            } 
     1384        } 
     1385 
     1386        if (StringArrays.startsWith(temp, BAD_PREFIX, tagBytes.length) || 
     1387                StringArrays.startsWith(temp, NO_PREFIX, 
     1388                    tagBytes.length)) { 
     1389            throw new MailException(new String(temp)); 
     1390        } 
     1391 
     1392        return result; 
     1393    } 
     1394 
     1395    /** 
     1396     * Executes an IMAP command, and returns the reply as an 
     1397     * array of strings. 
     1398     * @param command IMAP command 
     1399     * @param arguments Arguments for the command 
     1400     * @param progressHandler the progress handler 
     1401     * @return List of returned strings 
     1402     */ 
     1403    protected String[] execute(String command, String arguments, 
     1404        MailProgressHandler progressHandler) throws IOException, MailException { 
     1405        String[] result = new String[0]; 
     1406 
     1407        String tag = TAG_PREFIX + commandCount++ + CHAR_SP; 
     1408        connection.sendCommand(tag + command + 
     1409            ((arguments == null) ? "" : (CHAR_SP + arguments))); 
     1410 
     1411        byte[] tagBytes = tag.getBytes(); 
     1412 
     1413        int preCount = connection.getBytesReceived(); 
     1414        byte[] temp = connection.receive(); 
     1415        int postCount = connection.getBytesReceived(); 
     1416 
     1417        if (progressHandler != null) { 
     1418            progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, 
     1419                (postCount - preCount), -1); 
     1420        } 
     1421 
     1422        while (!StringArrays.startsWith(temp, tagBytes)) { 
     1423            Arrays.add(result, new String(temp)); 
    13651424            preCount = postCount; 
    13661425            temp = connection.receive(); 
    13671426            postCount = connection.getBytesReceived(); 
    1368             if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, (postCount - preCount), -1); } 
    1369         } 
    1370  
    1371         temp = temp.substring(tag.length()); 
    1372  
    1373         if (temp.startsWith(BAD_PREFIX) || temp.startsWith(NO_PREFIX)) { 
    1374             throw new MailException(temp); 
     1427 
     1428            if (progressHandler != null) { 
     1429                progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, 
     1430                    (postCount - preCount), -1); 
     1431            } 
     1432        } 
     1433 
     1434        if (StringArrays.startsWith(temp, BAD_PREFIX, tagBytes.length) || 
     1435                StringArrays.startsWith(temp, NO_PREFIX, 
     1436                    tagBytes.length)) { 
     1437            throw new MailException(new String(temp)); 
    13751438        } 
    13761439 
     
    13891452     */ 
    13901453    protected String[] executeContinue(String command, String arguments, 
    1391             String text, String errorMsg) throws IOException, MailException { 
     1454        String text, String errorMsg) throws IOException, MailException { 
    13921455        String[] result = new String[0]; 
    13931456 
    13941457        String tag = TAG_PREFIX + commandCount++ + CHAR_SP; 
    13951458        connection.sendCommand(tag + command + 
    1396                 ((arguments == null) ? "" : (CHAR_SP + arguments))); 
    1397  
    1398         String temp = connection.receive(); 
    1399  
    1400         if (!temp.startsWith(CHAR_PLUS)) { 
     1459            ((arguments == null) ? "" : (CHAR_SP + arguments))); 
     1460 
     1461        byte[] tagBytes = tag.getBytes(); 
     1462 
     1463        byte[] temp = connection.receive(); 
     1464 
     1465        if (Arrays.getIndex(temp, CHAR_PLUS) == -1) { 
    14011466            throw new MailException(errorMsg); 
    14021467        } 
     
    14071472        temp = connection.receive(); 
    14081473 
    1409         while (!temp.startsWith(tag)) { 
    1410             Arrays.add(result, temp); 
     1474        while (!StringArrays.startsWith(temp, tagBytes)) { 
     1475            Arrays.add(result, new String(temp)); 
    14111476            temp = connection.receive(); 
    14121477        } 
    14131478 
    1414         temp = temp.substring(tag.length()); 
    1415  
    1416         if (temp.startsWith(BAD_PREFIX) || temp.startsWith(NO_PREFIX)) { 
    1417             throw new MailException(temp); 
     1479        if (StringArrays.startsWith(temp, BAD_PREFIX, tagBytes.length) || 
     1480                StringArrays.startsWith(temp, NO_PREFIX, 
     1481                    tagBytes.length)) { 
     1482            throw new MailException(new String(temp)); 
    14181483        } 
    14191484 
     
    14301495 
    14311496        if (connection.available() > 0) { 
    1432             result = connection.receive(); 
     1497            result = new String(connection.receive()); 
    14331498        } else { 
    14341499            result = null; 
     
    14451510     */ 
    14461511    protected String executeNoReply(String command, String arguments) 
    1447     throws IOException, MailException { 
     1512        throws IOException, MailException { 
    14481513        String tag = TAG_PREFIX + commandCount++ + CHAR_SP; 
    14491514        connection.sendCommand(tag + command + 
    1450                 ((arguments == null) ? "" : (CHAR_SP + arguments))); 
     1515            ((arguments == null) ? "" : (CHAR_SP + arguments))); 
    14511516 
    14521517        return tag; 
     
    14611526     * @return List of returned strings 
    14621527     */ 
    1463     protected String[] executeUntagged(String command, String arguments, String endTag) 
    1464     throws IOException, MailException { 
     1528    protected String[] executeUntagged(String command, String arguments, 
     1529        String endTag) throws IOException, MailException { 
    14651530        String[] result = new String[0]; 
    14661531 
    14671532        connection.sendCommand(command + 
    1468                 ((arguments == null) ? "" : (CHAR_SP + arguments))); 
    1469  
    1470         String temp = connection.receive(); 
    1471  
    1472         while (!temp.startsWith(endTag)) { 
    1473             Arrays.add(result, temp); 
     1533            ((arguments == null) ? "" : (CHAR_SP + arguments))); 
     1534 
     1535        byte[] tagBytes = endTag.getBytes(); 
     1536        byte[] temp = connection.receive(); 
     1537 
     1538        while (!StringArrays.startsWith(temp, tagBytes)) { 
     1539            Arrays.add(result, new String(temp)); 
    14741540            temp = connection.receive(); 
    14751541        } 
    14761542 
    1477         temp = temp.substring(endTag.length()); 
    1478  
    1479         if (temp.startsWith(BAD_PREFIX) || temp.startsWith(NO_PREFIX)) { 
    1480             throw new MailException(temp); 
     1543        if (StringArrays.startsWith(temp, BAD_PREFIX, tagBytes.length) || 
     1544                StringArrays.startsWith(temp, NO_PREFIX, 
     1545                    tagBytes.length)) { 
     1546            throw new MailException(new String(temp)); 
    14811547        } 
    14821548 
    14831549        return result; 
     1550    } 
     1551 
     1552    /** 
     1553     * Callback for fetching envelopes. 
     1554     */ 
     1555    public static interface FetchEnvelopeCallback { 
     1556        void responseAvailable(FetchEnvelopeResponse response); 
    14841557    } 
    14851558 
     
    15061579        /** Message has recently arrived */ 
    15071580        public boolean recent; 
    1508          
     1581 
    15091582        /** Message has been forwarded */ 
    15101583        public boolean forwarded; 
     
    15801653 
    15811654    /** 
    1582      * Callback for fetching envelopes. 
    1583      */ 
    1584     public static interface FetchEnvelopeCallback { 
    1585         void responseAvailable(FetchEnvelopeResponse response); 
    1586     } 
    1587  
    1588     /** 
    15891655     * Container for a LIST response 
    15901656     */ 
     
    15971663        public String name; 
    15981664    } 
    1599  
     1665     
     1666    private static ConnectionResponseTester executeResponseTester = new ConnectionResponseTester() { 
     1667        private static final byte CR = (byte) 0x0D; 
     1668        private static final byte LF = (byte) 0x0A; 
     1669        private int trimCount; 
     1670        private int lastLength = 0; 
     1671        private int literalLength = 0; 
     1672 
     1673        public int checkForCompleteResponse(byte[] buf, int len) { 
     1674            trimCount = 0; 
     1675 
     1676            if (literalLength > 0) { 
     1677                if ((lastLength + literalLength) < len) { 
     1678                    lastLength += literalLength; 
     1679                    literalLength = 0; 
     1680                } else { 
     1681                    literalLength -= (len - lastLength); 
     1682                    lastLength = len; 
     1683 
     1684                    return -1; 
     1685                } 
     1686            } 
     1687 
     1688            int p = StringArrays.indexOf(buf, LF, lastLength); 
     1689 
     1690            while ((p != -1) && (p < len)) { 
     1691                if ((p > 0) && (buf[p - 1] == CR)) { 
     1692                    if ((p > 3) && (buf[p - 2] == '}')) { 
     1693                        int i = p - 3; 
     1694 
     1695                        while (i >= 0) { 
     1696                            if ((buf[i] >= '0') && (buf[i] <= '9')) { 
     1697                                i--; 
     1698                            } else if (buf[i] == '{') { 
     1699                                try { 
     1700                                    literalLength = StringArrays.parseInt(buf, i + 1, p - i - 3); 
     1701                                    break; 
     1702                                } catch (NumberFormatException e) { } 
     1703                            } 
     1704                        } 
     1705                    } 
     1706 
     1707                    trimCount = 2; 
     1708                } else { 
     1709                    trimCount = 1; 
     1710                } 
     1711 
     1712                p++; 
     1713 
     1714                if (literalLength > 0) { 
     1715                    if ((len - p) >= literalLength) { 
     1716                        p += literalLength; 
     1717                        literalLength = 0; 
     1718                    } else { 
     1719                        literalLength -= (len - p); 
     1720                        lastLength = len; 
     1721 
     1722                        return -1; 
     1723                    } 
     1724                } else { 
     1725                    lastLength = 0; 
     1726                    literalLength = 0; 
     1727 
     1728                    return p; 
     1729                } 
     1730 
     1731                p = StringArrays.indexOf(buf, LF, p); 
     1732            } 
     1733 
     1734            lastLength = len; 
     1735 
     1736            return -1; 
     1737        } 
     1738 
     1739        public int trimCount() { 
     1740            return trimCount; 
     1741        } 
     1742 
     1743        public String logString(byte[] result) { 
     1744            return new String(result); 
     1745        } 
     1746    }; 
     1747     
    16001748    // String constants 
    16011749    private static String UID_COPY = "UID COPY"; 
     
    16101758    private static String FETCH = "FETCH"; 
    16111759    private static String BODYSTRUCTURE = "BODYSTRUCTURE"; 
     1760    private static String BODY = "BODY"; 
    16121761    private static String ENVELOPE = "ENVELOPE"; 
    16131762    private static String UID = "UID"; 
     
    16291778    private static String FLAG_NOSELECT = "\\Noselect"; 
    16301779    private static String TAG_PREFIX = "A"; 
    1631     private static String NO_PREFIX = "NO "; 
    1632     private static String BAD_PREFIX = "BAD "; 
     1780    private static final byte[] NO_PREFIX = "NO ".getBytes(); 
     1781    private static final byte[] BAD_PREFIX = "BAD ".getBytes(); 
    16331782    private static String CHAR_SP = " "; 
    1634     private static String CHAR_ASTERISK = "*"; 
    1635     private static String CHAR_PLUS = "+"; 
     1783    private static final byte CHAR_PLUS = (byte) '+'; 
    16361784    private static String CHAR_COLON = ":"; 
    1637     private static String CHAR_ASTERISK_SP = "* "; 
     1785    private static final byte CHAR_ASTERISK = (byte)'*'; 
     1786    private static String ASTERISK = "*"; 
    16381787    private static String CHAR_QUOTE = "\""; 
    16391788    private static String CHAR_COLON_ASTERISK = ":*"; 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/pop/PopProtocol.java

    r658 r689  
    265265        if(execute(command, errorFatal) == null) { return null; } 
    266266         
    267         String buffer = connection.receive(); 
     267        String buffer = new String(connection.receive()); 
    268268        int postCount = connection.getBytesReceived(); 
    269269        if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, (postCount - preCount), -1); } 
     
    273273            Arrays.add(lines, buffer); 
    274274            preCount = postCount; 
    275             buffer = connection.receive(); 
     275            buffer = new String(connection.receive()); 
    276276            postCount = connection.getBytesReceived(); 
    277277            if(progressHandler != null) { progressHandler.mailProgress(MailProgressHandler.TYPE_NETWORK, (postCount - preCount), -1); } 
     
    308308        } 
    309309         
    310         String result = connection.receive(); 
     310        String result = new String(connection.receive()); 
    311311         
    312312        if((result.length() > 1) && (result.charAt(0) == '-')) { 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/smtp/SmtpProtocol.java

    r677 r689  
    397397        } 
    398398         
    399         String result = connection.receive(); 
     399        String result = new String(connection.receive()); 
    400400         
    401401        return result; 
     
    414414        execute(command); 
    415415             
    416         String buffer = connection.receive(); 
     416        String buffer = new String(connection.receive()); 
    417417        String[] lines = new String[0]; 
    418418        while(buffer != null) { 
    419             buffer = connection.receive(); 
     419            buffer = new String(connection.receive()); 
    420420            Arrays.add(lines, buffer); 
    421421            if(buffer.length() >=4 && buffer.charAt(3) == ' ') { 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/ApplicationContent.java

    r674 r689  
    3333import java.io.IOException; 
    3434 
    35 import net.rim.device.api.io.Base64InputStream; 
    36  
    3735public class ApplicationContent extends MimeMessageContent { 
    3836        private byte[] rawData; 
    3937         
    40         public ApplicationContent(ApplicationPart applicationPart, String encoding, String data) throws UnsupportedContentException { 
     38        public ApplicationContent(ApplicationPart applicationPart, String encoding, byte[] data) throws UnsupportedContentException { 
    4139                super(applicationPart); 
    4240        // Decode the binary data 
    43         if (encoding.equalsIgnoreCase("base64")) { 
     41        if (encoding.equalsIgnoreCase(ENCODING_BASE64)) { 
    4442                try { 
    45                         this.rawData = Base64InputStream.decode(data); 
     43                        this.rawData = decodeBase64(data); 
    4644                } catch (IOException e) { 
    4745                        throw new UnsupportedContentException("Unable to decode"); 
     
    5452    public ApplicationContent(ApplicationPart applicationPart, byte[] rawData) throws UnsupportedContentException { 
    5553        super(applicationPart); 
    56         applicationPart.setEncoding("base64"); 
     54        applicationPart.setEncoding(ENCODING_BASE64); 
    5755        this.rawData = rawData; 
    5856    } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/AudioContent.java

    r674 r689  
    3333import java.io.IOException; 
    3434 
    35 import net.rim.device.api.io.Base64InputStream; 
    36  
    3735public class AudioContent extends MimeMessageContent { 
    3836        private byte[] rawData; 
    3937         
    40         public AudioContent(AudioPart audioPart, String encoding, String data) throws UnsupportedContentException { 
     38        public AudioContent(AudioPart audioPart, String encoding, byte[] data) throws UnsupportedContentException { 
    4139                super(audioPart); 
    4240        // Decode the binary data 
    43         if (encoding.equalsIgnoreCase("base64")) { 
     41        if (encoding.equalsIgnoreCase(ENCODING_BASE64)) { 
    4442                try { 
    45                         this.rawData = Base64InputStream.decode(data); 
     43                        this.rawData = decodeBase64(data); 
    4644                } catch (IOException e) { 
    4745                        throw new UnsupportedContentException("Unable to decode"); 
     
    5452        public AudioContent(AudioPart audioPart, byte[] rawData) { 
    5553            super(audioPart); 
    56             audioPart.setEncoding("base64"); 
     54            audioPart.setEncoding(ENCODING_BASE64); 
    5755            this.rawData = rawData; 
    5856        } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/ImageContent.java

    r674 r689  
    3333import java.io.IOException; 
    3434 
    35 import net.rim.device.api.io.Base64InputStream; 
    3635import net.rim.device.api.system.EncodedImage; 
    3736 
     
    5251        } 
    5352 
    54         public ImageContent(ImagePart imagePart, String encoding, String data) throws UnsupportedContentException { 
     53        public ImageContent(ImagePart imagePart, String encoding, byte[] data) throws UnsupportedContentException { 
    5554                super(imagePart); 
    5655        // Decode the binary data, and create an image 
    57         if (encoding.equalsIgnoreCase("base64")) { 
     56        if (encoding.equalsIgnoreCase(ENCODING_BASE64) && data != null && data.length > 0) { 
    5857                try { 
    5958                        String mimeSubtype = imagePart.getMimeSubtype(); 
    60                         byte[] imgBytes = Base64InputStream.decode(data); 
     59                         
     60                        byte[] imgBytes = decodeBase64(data); 
     61                         
    6162                        this.image = EncodedImage.createEncodedImage( 
    6263                                        imgBytes, 
     
    7475        public ImageContent(ImagePart imagePart, byte[] rawData) { 
    7576        super(imagePart); 
    76         imagePart.setEncoding("base64"); 
     77        imagePart.setEncoding(ENCODING_BASE64); 
    7778        this.rawData = rawData; 
    7879        } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/MessageContent.java

    r674 r689  
    3333import java.io.IOException; 
    3434 
    35 import net.rim.device.api.io.Base64InputStream; 
    36  
    3735public class MessageContent extends MimeMessageContent { 
    3836        private byte[] rawData; 
    3937         
    40         public MessageContent(MessagePart messagePart, String encoding, String data) throws UnsupportedContentException { 
     38        public MessageContent(MessagePart messagePart, String encoding, byte[] data) throws UnsupportedContentException { 
    4139                super(messagePart); 
    4240        // Decode the binary data 
    43         if (encoding.equalsIgnoreCase("base64")) { 
     41        if (encoding.equalsIgnoreCase(ENCODING_BASE64)) { 
    4442                try { 
    45                         this.rawData = Base64InputStream.decode(data); 
     43                        this.rawData = decodeBase64(data); 
    4644                } catch (IOException e) { 
    4745                        throw new UnsupportedContentException("Unable to decode"); 
    4846                } 
    4947        } else { 
    50                 rawData = data.getBytes(); 
     48                rawData = data; 
    5149        } 
    5250        } 
     
    5452    public MessageContent(MessagePart messagePart, byte[] rawData) { 
    5553        super(messagePart); 
    56         messagePart.setEncoding("base64"); 
     54        messagePart.setEncoding(ENCODING_BASE64); 
    5755        this.rawData = rawData; 
    5856    }    
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/MimeMessageContent.java

    r551 r689  
    3131package org.logicprobe.LogicMail.message; 
    3232 
     33import java.io.ByteArrayInputStream; 
     34import java.io.ByteArrayOutputStream; 
    3335import java.io.DataInput; 
    3436import java.io.DataOutput; 
    3537import java.io.IOException; 
     38 
     39import net.rim.device.api.io.Base64InputStream; 
    3640 
    3741import org.logicprobe.LogicMail.util.Serializable; 
     
    4751    private long uniqueId; 
    4852    private ContentPart messagePart; 
     53    protected static String ENCODING_BASE64 = "base64"; 
    4954 
    5055    /** 
     
    9297    protected abstract void putRawData(byte[] rawData); 
    9398 
     99    /** 
     100     * Decode the provided data as Base64. 
     101     *  
     102     * @param data byte array representing a Base64-encoded string 
     103     * @return decoded form of the input data 
     104     * @throws IOException thrown if a decoding error occurred. 
     105     */ 
     106    protected static byte[] decodeBase64(byte[] data) throws IOException { 
     107        if(data == null || data.length == 0) { 
     108            return new byte[0]; 
     109        } 
     110         
     111        byte[] decodedData; 
     112        if(data.length < 32768) { 
     113            decodedData = Base64InputStream.decode(data, 0, data.length); 
     114        } 
     115        else { 
     116            Base64InputStream inputStream = new Base64InputStream(new ByteArrayInputStream(data, 0, data.length)); 
     117            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(65536); 
     118             
     119            byte[] buf = new byte[1024]; 
     120            int count; 
     121            while ((count = inputStream.read(buf)) >= 0) 
     122            { 
     123                outputStream.write(buf, 0, count); 
     124            } 
     125            inputStream.close(); 
     126             
     127            decodedData = outputStream.toByteArray(); 
     128        } 
     129        return decodedData; 
     130    } 
     131     
    94132    /* (non-Javadoc) 
    95133     * @see org.logicprobe.LogicMail.util.Serializable#getUniqueId() 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/MimeMessageContentFactory.java

    r674 r689  
    3535 */ 
    3636public class MimeMessageContentFactory { 
    37         // TODO: Refactor encoding/param up into the MessagePart classes 
    38          
    3937    /** 
    4038         * Creates a new MessageContent object. 
     
    4745         * @throws UnsupportedContentException Thrown if the content type was not supported or the data could not be decoded. 
    4846         */ 
    49         public static MimeMessageContent createContent(MimeMessagePart mimeMessagePart, String encodedData) throws UnsupportedContentException { 
     47        public static MimeMessageContent createContentEncoded(MimeMessagePart mimeMessagePart, byte[] encodedData) throws UnsupportedContentException { 
    5048        MimeMessageContent content; 
    5149        if(mimeMessagePart instanceof TextPart) { 
     
    8987     * @throws UnsupportedContentException Thrown if the content type was not supported or the data could not be decoded. 
    9088     */ 
    91         public static MimeMessageContent createContent(MimeMessagePart mimeMessagePart, byte[] rawData) throws UnsupportedContentException { 
     89        public static MimeMessageContent createContentRaw(MimeMessagePart mimeMessagePart, byte[] rawData) throws UnsupportedContentException { 
    9290            MimeMessageContent content; 
    9391        if(mimeMessagePart instanceof TextPart) { 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/TextContent.java

    r674 r689  
    3434import java.io.UnsupportedEncodingException; 
    3535 
    36 import net.rim.device.api.io.Base64InputStream; 
    37  
    3836import org.logicprobe.LogicMail.util.StringFactory; 
    3937import org.logicprobe.LogicMail.util.StringParser; 
     
    5452            String encoding, 
    5553            String charset, 
    56             String data) throws UnsupportedContentException { 
     54            byte[] data) throws UnsupportedContentException { 
    5755        super(textPart); 
    5856        String mimeSubtype = textPart.getMimeSubtype(); 
    5957         
     58        // Check for a supported text sub-type 
     59        if (!mimeSubtype.equalsIgnoreCase("plain") && 
     60                !mimeSubtype.equalsIgnoreCase("html")) { 
     61            throw new UnsupportedContentException("Unsupported subtype"); 
     62        } 
     63         
    6064        // Check for any encodings that need to be handled 
    6165        if (encoding.equalsIgnoreCase("quoted-printable")) { 
    62             data = StringParser.decodeQuotedPrintable(data); 
     66            this.text = StringParser.decodeQuotedPrintable(data); 
    6367        } 
    64         else if (encoding.equalsIgnoreCase("base64")) { 
     68        else if (encoding.equalsIgnoreCase(ENCODING_BASE64)) { 
    6569                byte[] textBytes; 
    6670 
    6771            try { 
    68                 textBytes = Base64InputStream.decode(data); 
     72                textBytes = decodeBase64(data); 
    6973            } catch (IOException exp) { 
    7074                throw new UnsupportedContentException("Unable to decode"); 
     
    7781                } 
    7882 
    79                 data = StringFactory.create(textBytes, charset); 
     83                this.text = StringFactory.create(textBytes, charset); 
    8084            } catch (UnsupportedEncodingException exp) { 
    8185                // If encoding type is bad, attempt with the default encoding 
    8286                // so the user will at least see something. 
    83                 data = new String(textBytes); 
     87                this.text = new String(textBytes); 
    8488            } 
    8589        } 
    86         else if ((charset != null) && 
    87                 !charset.equalsIgnoreCase("ISO-8859-1") && 
    88                 !charset.equalsIgnoreCase("US-ASCII")) { 
     90        else if (charset != null) { 
    8991            // If the text is not encoded (i.e. 7bit or 8bit) and uses a 
    9092            // non-Latin charset, then bring the text back to a byte array 
    9193            // and attempt to decode it based on the charset parameter. 
    92             byte[] textBytes = data.getBytes(); 
    9394 
    9495            try { 
    95                 data = StringFactory.create(textBytes, charset); 
     96                this.text = StringFactory.create(data, charset); 
    9697            } catch (UnsupportedEncodingException exp) { 
    97                 // If encoding type is bad, leave the message text as 
    98                 // it was originally.  This may result in the user seeing 
    99                 // garbage, but at least they'll know there was a 
    100                 // decoding problem. 
     98                // If encoding type is bad, use the default platform charset. 
     99                // This may result in the user seeing garbage, but at least 
     100                // they'll know there was a decoding problem. 
     101                this.text = new String(data); 
    101102            } 
    102         } 
    103  
    104         // Check for a supported text sub-type and decode if necessary 
    105         if (mimeSubtype.equalsIgnoreCase("plain") || 
    106                 mimeSubtype.equalsIgnoreCase("html")) { 
    107             this.text = data; 
    108         } 
    109         else { 
    110                 throw new UnsupportedContentException("Unsupported subtype"); 
    111103        } 
    112104    } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/message/VideoContent.java

    r674 r689  
    3333import java.io.IOException; 
    3434 
    35 import net.rim.device.api.io.Base64InputStream; 
    36  
    3735public class VideoContent extends MimeMessageContent { 
    3836        private byte[] rawData; 
    3937         
    40         public VideoContent(VideoPart videoPart, String encoding, String data) throws UnsupportedContentException { 
     38        public VideoContent(VideoPart videoPart, String encoding, byte[] data) throws UnsupportedContentException { 
    4139                super(videoPart); 
    4240        // Decode the binary data 
    43         if (encoding.equalsIgnoreCase("base64")) { 
     41        if (encoding.equalsIgnoreCase(ENCODING_BASE64)) { 
    4442                try { 
    45                         this.rawData = Base64InputStream.decode(data); 
     43                        this.rawData = decodeBase64(data); 
    4644                } catch (IOException e) { 
    4745                        throw new UnsupportedContentException("Unable to decode"); 
     
    5452    public VideoContent(VideoPart videoPart, byte[] rawData) { 
    5553        super(videoPart); 
    56         videoPart.setEncoding("base64"); 
     54        videoPart.setEncoding(ENCODING_BASE64); 
    5755        this.rawData = rawData; 
    5856    } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/ui/CompositionScreen.java

    r675 r689  
    659659            MimeMessageContent bodyContent; 
    660660            try { 
    661                         bodyContent = MimeMessageContentFactory.createContent( 
    662                                         bodyPart, contentText); 
     661                        bodyContent = MimeMessageContentFactory.createContentEncoded( 
     662                                        bodyPart, contentText.getBytes()); 
    663663                } catch (UnsupportedContentException e) { 
    664664                        bodyContent = null; 
     
    763763                    try { 
    764764                        MimeMessageContent attachmentContent = 
    765                             MimeMessageContentFactory.createContent(attachmentPart, data); 
     765                            MimeMessageContentFactory.createContentRaw(attachmentPart, data); 
    766766                        MultiPart multiPart = (MultiPart)pendingMessage.getStructure(); 
    767767                        multiPart.addPart(attachmentPart); 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/util/Connection.java

    r685 r689  
    9797    private int bytesSent = 0; 
    9898    private int bytesReceived = 0; 
     99    private final Object socketLock = new Object(); 
    99100     
    100101    /** 
     
    103104     */ 
    104105    private final ByteArrayOutputStream byteStream = new NoCopyByteArrayOutputStream(1024); 
    105  
     106     
     107    /** 
     108     * Temporary read buffer used as an intermediary between the socket and 
     109     * the byteStream. 
     110     */ 
     111    private final byte[] readBuffer = new byte[1024]; 
     112     
    106113    /** 
    107114     * Initializes a new connection object. 
     
    163170     * Opens a connection. 
    164171     */ 
    165     public synchronized void open() throws IOException { 
     172    public void open() throws IOException { 
    166173        if ((input != null) || (output != null) || (socket != null)) { 
    167174            close(); 
     
    170177        utilFactory.addOpenConnection(this); 
    171178 
    172         socket = openStreamConnection(); 
    173         if(socket == null) { 
    174             throw new IOException(resources.getString(LogicMailResource.ERROR_UNABLE_TO_OPEN_CONNECTION)); 
    175         } 
    176          
    177         input = socket.openDataInputStream(); 
    178         output = socket.openDataOutputStream(); 
    179         localAddress = ((SocketConnection) socket).getLocalAddress(); 
    180         bytesSent = 0; 
    181         bytesReceived = 0; 
    182  
     179        synchronized(socketLock) { 
     180            socket = openStreamConnection(); 
     181            if(socket == null) { 
     182                throw new IOException(resources.getString(LogicMailResource.ERROR_UNABLE_TO_OPEN_CONNECTION)); 
     183            } 
     184             
     185            input = socket.openDataInputStream(); 
     186            output = socket.openDataOutputStream(); 
     187            localAddress = ((SocketConnection) socket).getLocalAddress(); 
     188            bytesSent = 0; 
     189            bytesReceived = 0; 
     190        } 
     191         
    183192        if (EventLogger.getMinimumLevel() >= EventLogger.INFORMATION) { 
    184193            String msg = "Connection established:\r\n" + "Socket: " + 
     
    224233     * Closes a connection. 
    225234     */ 
    226     public synchronized void close() throws IOException { 
    227         try { 
    228             if (input != null) { 
    229                 input.close(); 
     235    public void close() throws IOException { 
     236        synchronized(socketLock) { 
     237            try { 
     238                if (input != null) { 
     239                    input.close(); 
     240                    input = null; 
     241                } 
     242            } catch (Exception exp) { 
    230243                input = null; 
    231244            } 
    232         } catch (Exception exp) { 
    233             input = null; 
    234         } 
    235  
    236         try { 
    237             if (output != null) { 
    238                 output.close(); 
     245     
     246            try { 
     247                if (output != null) { 
     248                    output.close(); 
     249                    output = null; 
     250                } 
     251            } catch (Exception exp) { 
    239252                output = null; 
    240253            } 
    241         } catch (Exception exp) { 
    242             output = null; 
    243         } 
    244  
    245         try { 
    246             if (socket != null) { 
    247                 socket.close(); 
     254     
     255            try { 
     256                if (socket != null) { 
     257                    socket.close(); 
     258                    socket = null; 
     259                } 
     260            } catch (Exception exp) { 
    248261                socket = null; 
    249262            } 
    250         } catch (Exception exp) { 
    251             socket = null; 
    252         } 
    253  
     263            setConnectionUrl(null); 
     264        } 
     265         
    254266        utilFactory.removeOpenConnection(this); 
    255  
    256         setConnectionUrl(null); 
    257267         
    258268        EventLogger.logEvent(AppInfo.GUID, "Connection closed".getBytes(), 
     
    321331     * is a prepared protocol command. 
    322332     */ 
    323     public synchronized void sendCommand(String s) throws IOException { 
     333    public void sendCommand(String s) throws IOException { 
    324334        if (globalConfig.getConnDebug()) { 
    325335            EventLogger.logEvent(AppInfo.GUID, ("[SEND CMD] " + s).getBytes(), 
     
    327337        } 
    328338 
    329         if (s == null) { 
    330             output.write(CRLF, 0, 2); 
    331             bytesSent += 2; 
    332         } else { 
    333             byte[] buf = (s + strCRLF).getBytes(); 
    334             output.write(buf); 
    335             bytesSent += buf.length; 
    336         } 
    337  
    338         output.flush(); 
     339        synchronized(socketLock) { 
     340            if (s == null) { 
     341                output.write(CRLF, 0, 2); 
     342                bytesSent += 2; 
     343            } else { 
     344                byte[] buf = (s + strCRLF).getBytes(); 
     345                output.write(buf); 
     346                bytesSent += buf.length; 
     347            } 
     348     
     349            output.flush(); 
     350        } 
    339351    } 
    340352 
     
    347359     * @see #send 
    348360     */ 
    349     public synchronized void sendRaw(String s) throws IOException { 
     361    public void sendRaw(String s) throws IOException { 
    350362        byte[] buf = s.getBytes(); 
    351363 
     
    355367        } 
    356368 
    357         output.write(buf, 0, buf.length); 
    358         bytesSent += buf.length; 
    359  
    360         output.flush(); 
     369        synchronized(socketLock) { 
     370            output.write(buf, 0, buf.length); 
     371            bytesSent += buf.length; 
     372     
     373            output.flush(); 
     374        } 
    361375    } 
    362376 
     
    374388        } 
    375389    } 
    376      
     390 
    377391    /** 
    378392     * Receives a string from the server. This method is used internally for 
     
    382396     * returned as part of the result. 
    383397     * 
    384      * @see #send 
    385      */ 
    386     public synchronized String receive() throws IOException { 
    387         // Check existing data for a usable line 
    388         String line = checkForLine(); 
    389         if(line != null) { 
    390             return line; 
    391         } 
    392  
    393         // Read from the socket 
    394         int firstByte = input.read(); 
    395         if(firstByte != -1) { 
    396             byteStream.write((byte)firstByte); 
    397             bytesReceived++; 
    398             int bytesAvailable = input.available(); 
    399             while(bytesAvailable > 0) { 
    400                 byte[] buf = new byte[bytesAvailable]; 
    401                 int len = input.read(buf); 
    402                 byteStream.write(buf, 0, len); 
    403                 bytesReceived += len; 
     398     * @return the complete line, minus the CRLF, as a byte array 
     399     */ 
     400    public byte[] receive() throws IOException { 
     401        return receive(lineResponseTester); 
     402    } 
     403     
     404     
     405    /** 
     406     * Receives a string from the server. This method is used internally for 
     407     * incoming communication from the server. 
     408     * 
     409     * @param responseTester class to determine when a complete response has 
     410     *   been read from the network, and whether to trim it prior to returning 
     411     * @return the complete response, as a byte array 
     412     */ 
     413    public byte[] receive(ConnectionResponseTester responseTester) throws IOException { 
     414        byte[] result = receiveImpl(responseTester); 
     415         
     416        if(result != null && globalConfig.getConnDebug()) { 
     417                EventLogger.logEvent(AppInfo.GUID, 
     418                        ("[RECV] " + responseTester.logString(result)).getBytes(), 
     419                        EventLogger.DEBUG_INFO); 
     420        } 
     421         
     422        return result; 
     423    } 
     424     
     425    private byte[] receiveImpl(ConnectionResponseTester responseTester) throws IOException { 
     426        synchronized(socketLock) { 
     427            // Check existing data for a usable line 
     428            byte[] line = checkForLine(responseTester); 
     429            if(line != null) { 
     430                return line; 
     431            } 
     432     
     433            // Read from the socket 
     434            int firstByte = input.read(); 
     435            if(firstByte != -1) { 
     436                byteStream.write((byte)firstByte); 
     437                bytesReceived++; 
     438                int bytesAvailable = input.available(); 
     439                while(bytesAvailable > 0) { 
     440                    int len = input.read(readBuffer); 
     441                    byteStream.write(readBuffer, 0, len); 
     442                    bytesReceived += len; 
     443                     
     444                    // Check read data for a usable line 
     445                    line = checkForLine(responseTester); 
     446                    if(line != null) { 
     447                        return line; 
     448                    } 
     449                     
     450                    bytesAvailable = input.available(); 
     451     
     452                    // If no bytes are reported as being available, but we have 
     453                    // not yet received a full line, then we need to attempt 
     454                    // another single-byte blocking read. 
     455                    if(bytesAvailable == 0) { 
     456                        firstByte = input.read(); 
     457                        byteStream.write((byte)firstByte); 
     458                        bytesReceived++; 
     459                        bytesAvailable = input.available(); 
     460                    } 
     461                } 
     462            } 
     463            else { 
     464                // If we got here, that means that the InputStream is either closed 
     465                // or we are in some otherwise unrecoverable state.  This means we 
     466                // will try to close the connection, ignore any errors from the 
     467                // close operation, and throw an IOException. 
    404468                 
    405                 // Check read data for a usable line 
    406                 line = checkForLine(); 
    407                 if(line != null) { 
    408                     return line; 
    409                 } 
    410                  
    411                 bytesAvailable = input.available(); 
    412  
    413                 // If no bytes are reported as being available, but we have 
    414                 // not yet received a full line, then we need to attempt 
    415                 // another single-byte blocking read. 
    416                 if(bytesAvailable == 0) { 
    417                     firstByte = input.read(); 
    418                     byteStream.write((byte)firstByte); 
    419                     bytesReceived++; 
    420                     bytesAvailable = input.available(); 
    421                 } 
    422             } 
    423         } 
    424         else { 
    425             // If we got here, that means that the InputStream is either closed 
    426             // or we are in some otherwise unrecoverable state.  This means we 
    427             // will try to close the connection, ignore any errors from the 
    428             // close operation, and throw an IOException. 
    429              
    430             EventLogger.logEvent(AppInfo.GUID, 
    431                     "Unable to read from socket, closing connection".getBytes(), 
    432                     EventLogger.INFORMATION); 
    433  
    434             try { 
    435                 close(); 
    436             } catch (IOException e) { } 
    437  
    438             throw new IOException("Connection closed"); 
    439         } 
    440          
     469                EventLogger.logEvent(AppInfo.GUID, 
     470                        "Unable to read from socket, closing connection".getBytes(), 
     471                        EventLogger.INFORMATION); 
     472     
     473                try { 
     474                    close(); 
     475                } catch (IOException e) { } 
     476     
     477                throw new IOException("Connection closed"); 
     478            } 
     479        } 
    441480        // This should never normally happen 
    442481        return null; 
     
    450489     * @return the trimmed string which ended in a CRLF in the source data 
    451490     */ 
    452     private String checkForLine() throws IOException { 
    453         String result; 
     491    private byte[] checkForLine(ConnectionResponseTester responseTester) throws IOException { 
     492        byte[] result; 
    454493         
    455494        byte[] buf = byteStream.toByteArray(); 
    456495        int size = byteStream.size(); 
    457496         
    458         int p = Arrays.getIndex(buf, LF); 
    459         if(p != -1 && p < size) { 
    460             int q = p + 1; 
    461             if(p > 0 && buf[p - 1] == CR) { 
    462                 p--; 
    463             } 
    464             result = new String(buf, 0, p); 
     497        int p = responseTester.checkForCompleteResponse(buf, size); 
     498         
     499        if(p != -1) { 
     500            int trimCount = responseTester.trimCount(); 
    465501             
    466             if (globalConfig.getConnDebug()) { 
    467                 EventLogger.logEvent(AppInfo.GUID, 
    468                         ("[RECV] " + result).getBytes(), 
    469                         EventLogger.DEBUG_INFO); 
    470             } 
     502            result = Arrays.copy(buf, 0, p - trimCount); 
    471503             
    472             if(q < size) { 
    473                 buf = Arrays.copy(buf, q, size - q); 
     504            if(p < size) { 
     505                buf = Arrays.copy(buf, p, size - p); 
    474506                byteStream.reset(); 
    475507                byteStream.write(buf); 
     
    488520    } 
    489521 
     522    private static ConnectionResponseTester lineResponseTester = new ConnectionResponseTester() { 
     523        private int trimCount; 
     524         
     525        public int checkForCompleteResponse(byte[] buf, int len) { 
     526            trimCount = 0; 
     527            int p = Arrays.getIndex(buf, LF); 
     528            if(p != -1 && p < len) { 
     529                if(p > 0 && buf[p - 1] == CR) { 
     530                    trimCount = 2; 
     531                } 
     532                else { 
     533                    trimCount = 1; 
     534                } 
     535                return ++p; 
     536            } 
     537            else { 
     538                return -1; 
     539            } 
     540        } 
     541 
     542        public int trimCount() { 
     543            return trimCount; 
     544        } 
     545         
     546        public String logString(byte[] result) { 
     547            return new String(result); 
     548        }; 
     549    }; 
     550     
    490551    /** 
    491552     * Switches the underlying connection to SSL mode, as commonly done after 
     
    495556     */ 
    496557    public void startTLS() throws IOException { 
    497         // Shortcut the method if we're already in SSL mode 
    498         if(socket instanceof TLS10Connection) { return; } 
    499          
    500         if(socket == null || connectionUrl == null) { 
    501             throw new IOException("Connection has not been opened"); 
    502         } 
    503  
    504         try { 
    505             TLS10Connection tlsSocket = new TLS10Connection( 
    506                     new StreamConnectionWrapper( 
    507                             socket, 
    508                             (DataInputStream)input, 
    509                             (DataOutputStream)output), 
    510                             connectionUrl, 
    511                             true); 
    512  
    513             socket = tlsSocket; 
    514             input = socket.openDataInputStream(); 
    515             output = socket.openDataOutputStream(); 
    516         } catch (IOException e) { 
    517             EventLogger.logEvent(AppInfo.GUID, 
    518                     ("Unable to switch to TLS mode: " + e.getMessage()).getBytes(), EventLogger.ERROR); 
    519             throw new IOException("Unable to switch to TLS mode"); 
    520         } catch (TLSException e) { 
    521             EventLogger.logEvent(AppInfo.GUID, 
    522                     ("Unable to switch to TLS mode: " + e.getMessage()).getBytes(), EventLogger.ERROR); 
    523             throw new IOException("Unable to switch to TLS mode"); 
     558        synchronized(socketLock) { 
     559            // Shortcut the method if we're already in SSL mode 
     560            if(socket instanceof TLS10Connection) { return; } 
     561             
     562            if(socket == null || connectionUrl == null) { 
     563                throw new IOException("Connection has not been opened"); 
     564            } 
     565     
     566            try { 
     567                TLS10Connection tlsSocket = new TLS10Connection( 
     568                        new StreamConnectionWrapper( 
     569                                socket, 
     570                                (DataInputStream)input, 
     571                                (DataOutputStream)output), 
     572                                connectionUrl, 
     573                                true); 
     574     
     575                socket = tlsSocket; 
     576                input = socket.openDataInputStream(); 
     577                output = socket.openDataOutputStream(); 
     578            } catch (IOException e) { 
     579                EventLogger.logEvent(AppInfo.GUID, 
     580                        ("Unable to switch to TLS mode: " + e.getMessage()).getBytes(), EventLogger.ERROR); 
     581                throw new IOException("Unable to switch to TLS mode"); 
     582            } catch (TLSException e) { 
     583                EventLogger.logEvent(AppInfo.GUID, 
     584                        ("Unable to switch to TLS mode: " + e.getMessage()).getBytes(), EventLogger.ERROR); 
     585                throw new IOException("Unable to switch to TLS mode"); 
     586            } 
    524587        } 
    525588    } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/util/MailMessageParser.java

    r640 r689  
    3434import net.rim.device.api.mime.MIMEInputStream; 
    3535import net.rim.device.api.mime.MIMEParsingException; 
     36import net.rim.device.api.util.Arrays; 
    3637 
    3738import org.logicprobe.LogicMail.AppInfo; 
     
    275276                int size = buffer.length - offset; 
    276277 
    277                 String data = new String(buffer, offset, size); 
     278                byte[] data = Arrays.copy(buffer, offset, size); 
    278279                MimeMessagePart part = MimeMessagePartFactory.createMimeMessagePart( 
    279280                                type, subtype, name, encoding, charset, disposition, contentId, size); 
    280281                try { 
    281                                         contentMap.put(part, MimeMessageContentFactory.createContent(part, data)); 
     282                                        contentMap.put(part, MimeMessageContentFactory.createContentEncoded(part, data)); 
    282283                                } catch (UnsupportedContentException e) { 
    283284                                        System.err.println("UnsupportedContentException: " + e.getMessage()); 
     
    287288                buffer = StringParser.readWholeStream(mimeInputStream); 
    288289 
    289                 String data = new String(buffer); 
    290290                MimeMessagePart part = MimeMessagePartFactory.createMimeMessagePart( 
    291                                 type, subtype, name, encoding, charset, disposition, contentId, data.length()); 
     291                                type, subtype, name, encoding, charset, disposition, contentId, buffer.length); 
    292292                try { 
    293                                         contentMap.put(part, MimeMessageContentFactory.createContent(part, data)); 
     293                                        contentMap.put(part, MimeMessageContentFactory.createContentEncoded(part, buffer)); 
    294294                                } catch (UnsupportedContentException e) { 
    295295                                        System.err.println("UnsupportedContentException: " + e.getMessage()); 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/util/StringParser.java

    r643 r689  
    4949import java.util.Hashtable; 
    5050import java.util.TimeZone; 
    51 import java.util.Vector; 
    5251 
    5352import org.logicprobe.LogicMail.AppInfo; 
     
    469468 
    470469    /** 
    471      * Recursively parse a nested paren string. 
    472      * Parses through a string of the form "(A (B C (D) E F))" and 
    473      * returns a tree of Vector and String objects representing its 
    474      * contents.  This is useful for parsing the response to the 
    475      * IMAP "ENVELOPE" fetch command. 
    476      * 
    477      * @param rawText The raw text to be parsed 
    478      * @return A tree of Vector and String objects 
    479      */ 
    480     public static Vector nestedParenStringLexer(String rawText) { 
    481         Vector parsedText = new Vector(); 
    482  
    483         // Sanity checking 
    484         if (!((rawText.charAt(0) == '(') && 
    485                 (rawText.charAt(rawText.length() - 1) == ')'))) { 
    486             return null; 
    487         } 
    488  
    489         int p = 1; 
    490         int q = p; 
    491         int len; 
    492         String tmpText; 
    493         boolean inQuote = false; 
    494  
    495         while (q < rawText.length()) { 
    496             if (isQuoteChar(rawText, q, p)) { 
    497                 if (!inQuote) { 
    498                     inQuote = true; 
    499                     p = q; 
    500                 } else { 
    501                     parsedText.addElement(rawText.substring(p + 1, q)); 
    502                     p = q + 1; 
    503                     inQuote = false; 
    504                 } 
    505             } else if ((rawText.charAt(q) == '{') && !inQuote) { 
    506                 p = rawText.indexOf('}', q); 
    507                 len = Integer.parseInt(rawText.substring(q + 1, p)); 
    508                 p++; 
    509  
    510                 while ((rawText.charAt(p) == '\r') || 
    511                         (rawText.charAt(p) == '\n')) 
    512                     p++; 
    513  
    514                 // Quick kludge for length miscalculation due to the way 
    515                 // line breaks are currently handled 
    516                 tmpText = rawText.substring(p, p + len); 
    517  
    518                 if (tmpText.endsWith(" NIL")) { 
    519                     len -= 4; 
    520                 } else if (tmpText.endsWith(" NI")) { 
    521                     len -= 3; 
    522                 } else if (tmpText.endsWith(" N")) { 
    523                     len -= 2; 
    524                 } else if (tmpText.endsWith(" ")) { 
    525                     len -= 1; 
    526                 } 
    527  
    528                 parsedText.addElement(rawText.substring(p, p + len)); 
    529                 q = p + len; 
    530             } else if (((rawText.charAt(q) == ' ') && !inQuote) || 
    531                     (q == (rawText.length() - 1))) { 
    532                 if ((q - p) > 0) { 
    533                     parsedText.addElement(rawText.substring(p, q).trim()); 
    534                     p = q; 
    535                 } else { 
    536                     p++; 
    537                 } 
    538             } else if ((rawText.charAt(q) == '(') && !inQuote) { 
    539                 p = q; 
    540  
    541                 // paren matching 
    542                 int level = 0; 
    543                 boolean subInQuote = false; 
    544  
    545                 for (int i = q + 1; i < rawText.length(); i++) { 
    546                     if ((rawText.charAt(i) == '{') && !subInQuote) { 
    547                         int matchIndex = rawText.indexOf('}', i); 
    548  
    549                         if ((matchIndex > (i + 1)) && 
    550                                 (rawText.charAt(matchIndex + 1) != ' ')) { 
    551                             int matchLen = Integer.parseInt(rawText.substring(i + 
    552                                         1, matchIndex)); 
    553                             matchIndex++; 
    554  
    555                             while ((rawText.charAt(matchIndex) == '\r') || 
    556                                     (rawText.charAt(matchIndex) == '\n')) { 
    557                                 matchIndex++; 
    558                             } 
    559  
    560                             i = matchIndex + matchLen; 
    561                         } 
    562                     } 
    563  
    564                     if (isQuoteChar(rawText, i, q + 1) && !subInQuote) { 
    565                         subInQuote = true; 
    566                     } else if (isQuoteChar(rawText, i, q + 1) && subInQuote) { 
    567                         subInQuote = false; 
    568                     } 
    569  
    570                     if ((rawText.charAt(i) == '(') && !subInQuote) { 
    571                         level++; 
    572                     } else if ((rawText.charAt(i) == ')') && !subInQuote) { 
    573                         if (level == 0) { 
    574                             q = i; 
    575  
    576                             break; 
    577                         } else { 
    578                             level--; 
    579                         } 
    580                     } 
    581                 } 
    582  
    583                 if ((q == 1) || (q < p)) { 
    584                     return null; 
    585                 } else { 
    586                     parsedText.addElement(nestedParenStringLexer( 
    587                             rawText.substring(p, q + 1))); 
    588                 } 
    589  
    590                 p = q + 1; 
    591             } 
    592  
    593             q++; 
    594         } 
    595  
    596         return parsedText; 
    597     } 
    598  
    599     /** 
    600      * Helper method to determine if a character is a quote. 
    601      */ 
    602     private static boolean isQuoteChar(String rawText, int index, int startIndex) { 
    603         if (index == startIndex) { 
    604             return rawText.charAt(index) == '\"'; 
    605         } else if (rawText.charAt(index) == '\"') { 
    606             if (rawText.charAt(index - 1) == '\\') { 
    607                 if (((index - 2) < startIndex) || 
    608                         (rawText.charAt(index - 2) == '\\')) { 
    609                     return true; 
    610                 } else { 
    611                     return false; 
    612                 } 
    613             } else { 
    614                 return true; 
    615             } 
    616         } else { 
    617             return false; 
    618         } 
    619     } 
    620  
    621     /** 
    622470     * This method iterates through the raw lines that make up 
    623471     * standard E-Mail headers, and parses them out into hash 
     
    799647                // Quoted-Printable 
    800648                result = new String( 
    801                         decodeQuotedPrintable(encodedText).getBytes(), 
     649                        decodeQuotedPrintable(encodedText.getBytes()).getBytes(), 
    802650                        charset); 
    803651            } catch (UnsupportedEncodingException ex) { 
     
    12711119     * Decode a quoted-printable string 
    12721120     */ 
    1273     public static String decodeQuotedPrintable(String text) { 
     1121    public static String decodeQuotedPrintable(byte[] text) { 
    12741122        StringBuffer buffer = new StringBuffer(); 
    12751123        int index = 0; 
    1276         int length = text.length(); 
     1124        int length = text.length; 
    12771125 
    12781126        while (index < length) { 
    1279             if (text.charAt(index) == '=') { 
     1127            if (text[index] == (byte)'=') { 
    12801128                if ((index + 2) >= length) { 
    12811129                    break; 
    12821130                } else { 
    1283                     char ch1 = text.charAt(index + 1); 
    1284                     char ch2 = text.charAt(index + 2); 
    1285  
    1286                     if ((ch1 == '\r') && (ch2 == '\n')) { 
     1131                    byte ch1 = text[index + 1]; 
     1132                    byte ch2 = text[index + 2]; 
     1133 
     1134                    if ((ch1 == (byte)'\r') && (ch2 == (byte)'\n')) { 
    12871135                        index += 3; 
    1288                     } else if (ch1 == '\n') { 
     1136                    } else if (ch1 == (byte)'\n') { 
    12891137                        index += 2; 
    12901138                    } else { 
    12911139                        try { 
    1292                             int charVal = Integer.parseInt(text.substring(index + 
    1293                                         1, index + 3), 16); 
     1140                            int charVal = StringArrays.parseHexInt(text, index + 1, 2); 
    12941141                            buffer.append((char) charVal); 
    1295                         } catch (NumberFormatException exp) { 
    1296                         } 
     1142                        } catch (NumberFormatException exp) { } 
    12971143 
    12981144                        index += 3; 
    12991145                    } 
    13001146                } 
    1301             } else if (text.charAt(index) == '_') { 
     1147            } else if (text[index] == (byte)'_') { 
    13021148                buffer.append(' '); 
    13031149                index++; 
    13041150            } else { 
    1305                 buffer.append(text.charAt(index)); 
     1151                buffer.append((char)text[index]); 
    13061152                index++; 
    13071153            } 
  • trunk/LogicMailTests/src/org/logicprobe/LogicMail/mail/imap/ImapParserTest.java

    r196 r689  
    11/*- 
    2  * Copyright (c) 2008, Derek Konigsberg 
     2 * Copyright (c) 2010, Derek Konigsberg 
    33 * All rights reserved. 
    44 * 
     
    88 * 
    99 * 1. Redistributions of source code must retain the above copyright 
    10  *    notice, this list of conditions and the following disclaimer.  
     10 *    notice, this list of conditions and the following disclaimer. 
    1111 * 2. Redistributions in binary form must reproduce the above copyright 
    1212 *    notice, this list of conditions and the following disclaimer in the 
    13  *    documentation and/or other materials provided with the distribution.  
     13 *    documentation and/or other materials provided with the distribution. 
    1414 * 3. Neither the name of the project nor the names of its 
    1515 *    contributors may be used to endorse or promote products derived 
     
    2929 * OF THE POSSIBILITY OF SUCH DAMAGE. 
    3030 */ 
    31  
    3231package org.logicprobe.LogicMail.mail.imap; 
    3332 
     
    3736import j2meunit.framework.TestSuite; 
    3837 
     38import java.util.Vector; 
     39 
     40 
    3941/** 
    4042 * Unit test for ImapParser 
    4143 */ 
    4244public class ImapParserTest extends TestCase { 
    43      
    4445    public ImapParserTest() { 
    4546    } 
     
    4849        super(testName, testMethod); 
    4950    } 
    50      
     51 
    5152    public void setUp() { 
    5253    } 
    53      
     54 
    5455    public void tearDown() { 
    5556    } 
    56      
     57 
    5758    public void testParseFolderName() { 
    5859        String result = ImapParser.parseFolderName("Hello"); 
     
    6869        assertEquals("Umlaut Test 2", "Gelöschte Objekte", result); 
    6970    } 
     71 
     72    public void testParenStringLexer1() { 
     73        String rawText = "(FLAGS (\\Answered \\Seen) " + 
     74            "ENVELOPE (\"Mon, 12 Mar 2007 19:38:31 -0700\" \"Re: Calm down! :-)\" " + 
     75            "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
     76            "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
     77            "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
     78            "((\"John Doe\" NIL \"jdoe\" \"generic.test\")) " + "NIL NIL " + 
     79            "\"<200703121933.25327.jdoe@generic.test>\" " + 
     80            "\"<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>\"))"; 
     81 
     82        byte[] data = rawText.getBytes(); 
     83        Vector result = ImapParser.parenListLexer(data, 0, data.length); 
     84        assertNotNull(result); 
     85 
     86        Character LPAREN = new Character('('); 
     87        Character RPAREN = new Character(')'); 
     88 
     89        Object[] expected = new Object[] { 
     90                LPAREN, "FLAGS", LPAREN, "\\Answered", "\\Seen", RPAREN, 
     91                "ENVELOPE", LPAREN, "Mon, 12 Mar 2007 19:38:31 -0700".getBytes(), 
     92                "Re: Calm down! :-)".getBytes(), LPAREN, LPAREN, "jim smith".getBytes(), "NIL", 
     93                "jsmith".getBytes(), "scratch.test".getBytes(), RPAREN, RPAREN, LPAREN, LPAREN, 
     94                "jim smith".getBytes(), "NIL", "jsmith".getBytes(), "scratch.test".getBytes(), RPAREN, RPAREN, 
     95                LPAREN, LPAREN, "jim smith".getBytes(), "NIL", "jsmith".getBytes(), "scratch.test".getBytes(), 
     96                RPAREN, RPAREN, LPAREN, LPAREN, "John Doe".getBytes(), "NIL", "jdoe".getBytes(), 
     97                "generic.test".getBytes(), RPAREN, RPAREN, "NIL", "NIL", 
     98                "<200703121933.25327.jdoe@generic.test>".getBytes(), 
     99                "<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>".getBytes(), 
     100                RPAREN, RPAREN 
     101            }; 
     102 
     103        assertEquals(expected.length, result.size()); 
     104 
     105        for (int i = 0; i < expected.length; i++) { 
     106            if(expected[i] instanceof byte[] && result.elementAt(i) instanceof byte[]) { 
     107                assertEquals(new String((byte[])expected[i]), new String((byte[])result.elementAt(i))); 
     108            } 
     109            else { 
     110                assertEquals(expected[i], result.elementAt(i)); 
     111            } 
     112        } 
     113    } 
     114 
     115    public void testParenStringLexer2() { 
     116        String rawText = "(FLAGS () ENVELOPE (\"Sun, 18 Mar 2007 09:04:29 -0700\" {23}\r\n" + 
     117            "[list] \"this is a test\" " + 
     118            "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
     119            "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
     120            "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
     121            "((NIL NIL \"jsmith\" \"XXXXXXXX\")) " + 
     122            "NIL NIL NIL \"<45FD630D.1040808@XXXXX>\"))"; 
     123 
     124        byte[] data = rawText.getBytes(); 
     125        Vector result = ImapParser.parenListLexer(data, 0, data.length); 
     126        assertNotNull(result); 
     127 
     128        Character LPAREN = new Character('('); 
     129        Character RPAREN = new Character(')'); 
     130 
     131        Object[] expected = new Object[] { 
     132                LPAREN, "FLAGS", LPAREN, RPAREN, "ENVELOPE", LPAREN, 
     133                "Sun, 18 Mar 2007 09:04:29 -0700".getBytes(), "[list] \"this is a test\"".getBytes(), 
     134                LPAREN, LPAREN, "Jim Smith".getBytes(), "NIL", "jsmith".getBytes(), "XXXX".getBytes(), RPAREN, 
     135                RPAREN, LPAREN, LPAREN, "Jim Smith".getBytes(), "NIL", "jsmith".getBytes(), "XXXX".getBytes(), 
     136                RPAREN, RPAREN, LPAREN, LPAREN, "Jim Smith".getBytes(), "NIL", "jsmith".getBytes(), 
     137                "XXXX".getBytes(), RPAREN, RPAREN, LPAREN, LPAREN, "NIL", "NIL", "jsmith".getBytes(), 
     138                "XXXXXXXX".getBytes(), RPAREN, RPAREN, "NIL", "NIL", "NIL", 
     139                "<45FD630D.1040808@XXXXX>".getBytes(), RPAREN, RPAREN 
     140            }; 
     141 
     142        assertEquals(expected.length, result.size()); 
     143 
     144        for (int i = 0; i < expected.length; i++) { 
     145            if(expected[i] instanceof byte[] && result.elementAt(i) instanceof byte[]) { 
     146                assertEquals(new String((byte[])expected[i]), new String((byte[])result.elementAt(i))); 
     147            } 
     148            else { 
     149                assertEquals(expected[i], result.elementAt(i)); 
     150            } 
     151        } 
     152    } 
     153 
     154    //    /** 
     155    //     * Prints the token list for debugging purposes 
     156    //     * 
     157    //     * @param tokenList the token list 
     158    //     */ 
     159    //    private void printTokenList(Vector tokenList) { 
     160    //        int size = tokenList.size(); 
     161    //        System.err.println("-->"); 
     162    //        for(int i=0; i<size; i++) { 
     163    //            Object element = tokenList.elementAt(i); 
     164    //            if(element instanceof Character) { 
     165    //                System.err.print("'" + element + "' "); 
     166    //            } 
     167    //            else if(element instanceof String) { 
     168    //                System.err.print("[" + element + "] "); 
     169    //            } 
     170    //            else if(element == null) { 
     171    //                System.err.print("<NIL> "); 
     172    //            } 
     173    //            else { 
     174    //                System.err.println("ERROR!!!!"); 
     175    //            } 
     176    //        } 
     177    //        System.err.println(); 
     178    //    } 
     179    public void testParenStringParserEnvelope1() { 
     180        String rawText = "(FLAGS (\\Answered \\Seen) " + 
     181            "ENVELOPE (\"Mon, 12 Mar 2007 19:38:31 -0700\" \"Re: Calm down! :-)\" " + 
     182            "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
     183            "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
     184            "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
     185            "((\"John Doe\" NIL \"jdoe\" \"generic.test\")) " + "NIL NIL " + 
     186            "\"<200703121933.25327.jdoe@generic.test>\" " + 
     187            "\"<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>\"))"; 
     188 
     189        Vector result = ImapParser.parenListParser(rawText.getBytes()); 
     190        Vector temp; 
     191 
     192        //printTree(result, 0); 
     193        assertEquals("FLAGS", (String) result.elementAt(0)); 
     194 
     195        Vector flags = (Vector) result.elementAt(1); 
     196        assertEquals("\\Answered", (String) flags.elementAt(0)); 
     197        assertEquals("\\Seen", (String) flags.elementAt(1)); 
     198 
     199        assertEquals("ENVELOPE", (String) result.elementAt(2)); 
     200 
     201        Vector envelope = (Vector) result.elementAt(3); 
     202        assertNotNull(envelope); 
     203        assertEquals("Mon, 12 Mar 2007 19:38:31 -0700", 
     204            (byte[]) envelope.elementAt(0)); 
     205        assertEquals("Re: Calm down! :-)", (byte[]) envelope.elementAt(1)); 
     206 
     207        temp = (Vector) envelope.elementAt(2); 
     208        temp = (Vector) temp.elementAt(0); 
     209        assertEquals("jim smith", (byte[]) temp.elementAt(0)); 
     210        assertEquals("NIL", (String) temp.elementAt(1)); 
     211        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     212        assertEquals("scratch.test", (byte[]) temp.elementAt(3)); 
     213 
     214        temp = (Vector) envelope.elementAt(3); 
     215        temp = (Vector) temp.elementAt(0); 
     216        assertEquals("jim smith", (byte[]) temp.elementAt(0)); 
     217        assertEquals("NIL", (String) temp.elementAt(1)); 
     218        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     219        assertEquals("scratch.test", (byte[]) temp.elementAt(3)); 
     220 
     221        temp = (Vector) envelope.elementAt(4); 
     222        temp = (Vector) temp.elementAt(0); 
     223        assertEquals("jim smith", (byte[]) temp.elementAt(0)); 
     224        assertEquals("NIL", (String) temp.elementAt(1)); 
     225        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     226        assertEquals("scratch.test", (byte[]) temp.elementAt(3)); 
     227 
     228        temp = (Vector) envelope.elementAt(5); 
     229        temp = (Vector) temp.elementAt(0); 
     230        assertEquals("John Doe", (byte[]) temp.elementAt(0)); 
     231        assertEquals("NIL", (String) temp.elementAt(1)); 
     232        assertEquals("jdoe", (byte[]) temp.elementAt(2)); 
     233        assertEquals("generic.test", (byte[]) temp.elementAt(3)); 
     234 
     235        assertEquals("NIL", (String) envelope.elementAt(6)); 
     236        assertEquals("NIL", (String) envelope.elementAt(7)); 
     237        assertEquals("<200703121933.25327.jdoe@generic.test>", 
     238            (byte[]) envelope.elementAt(8)); 
     239        assertEquals("<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>", 
     240            (byte[]) envelope.elementAt(9)); 
     241    } 
     242 
     243    public void testParenStringParserEnvelope2() { 
     244        String rawText = "(FLAGS () ENVELOPE (\"Sun, 18 Mar 2007 09:04:29 -0700\" {23}\r\n" + 
     245            "[list] \"this is a test\" " + 
     246            "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
     247            "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
     248            "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
     249            "((NIL NIL \"jsmith\" \"XXXXXXXX\")) " + 
     250            "NIL NIL NIL \"<45FD630D.1040808@XXXXX>\"))"; 
     251 
     252        Vector result = ImapParser.parenListParser(rawText.getBytes()); 
     253        Vector temp; 
     254 
     255        //printTree(result, 0); 
     256        assertEquals("FLAGS", (String) result.elementAt(0)); 
     257 
     258        Vector flags = (Vector) result.elementAt(1); 
     259        assertEquals(0, flags.size()); 
     260 
     261        assertEquals("ENVELOPE", (String) result.elementAt(2)); 
     262 
     263        Vector envelope = (Vector) result.elementAt(3); 
     264        assertNotNull(envelope); 
     265        assertEquals("Sun, 18 Mar 2007 09:04:29 -0700", 
     266            (byte[]) envelope.elementAt(0)); 
     267        assertEquals("[list] \"this is a test\"", (byte[]) envelope.elementAt(1)); 
     268 
     269        temp = (Vector) envelope.elementAt(2); 
     270        temp = (Vector) temp.elementAt(0); 
     271        assertEquals("Jim Smith", (byte[]) temp.elementAt(0)); 
     272        assertEquals("NIL", (String) temp.elementAt(1)); 
     273        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     274        assertEquals("XXXX", (byte[]) temp.elementAt(3)); 
     275 
     276        temp = (Vector) envelope.elementAt(3); 
     277        temp = (Vector) temp.elementAt(0); 
     278        assertEquals("Jim Smith", (byte[]) temp.elementAt(0)); 
     279        assertEquals("NIL", (String) temp.elementAt(1)); 
     280        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     281        assertEquals("XXXX", (byte[]) temp.elementAt(3)); 
     282 
     283        temp = (Vector) envelope.elementAt(4); 
     284        temp = (Vector) temp.elementAt(0); 
     285        assertEquals("Jim Smith", (byte[]) temp.elementAt(0)); 
     286        assertEquals("NIL", (String) temp.elementAt(1)); 
     287        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     288        assertEquals("XXXX", (byte[]) temp.elementAt(3)); 
     289 
     290        temp = (Vector) envelope.elementAt(5); 
     291        temp = (Vector) temp.elementAt(0); 
     292        assertEquals("NIL", (String) temp.elementAt(0)); 
     293        assertEquals("NIL", (String) temp.elementAt(1)); 
     294        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     295        assertEquals("XXXXXXXX", (byte[]) temp.elementAt(3)); 
     296 
     297        assertEquals("NIL", (String) envelope.elementAt(6)); 
     298        assertEquals("NIL", (String) envelope.elementAt(7)); 
     299        assertEquals("NIL", (String) envelope.elementAt(8)); 
     300        assertEquals("<45FD630D.1040808@XXXXX>", (byte[]) envelope.elementAt(9)); 
     301    } 
     302 
     303    public void testParenStringParserEnvelope3() { 
     304        String rawText = "(FLAGS (\\Seen) " + 
     305            "ENVELOPE (\"Fri, 15 Jun 2007 12:37:27 -0400\" {42}\r\n" + 
     306            "[Theelist] 19\" monitor free to a good home " + 
     307            "((\"Jim Smith\" NIL \"jsmith\" \"smith.test\")) " + 
     308            "((NIL NIL \"thelist-bounces\" \"thelist.test\")) " + 
     309            "((\"This is the list\" NIL \"thelist\" \"thelist.test\")) " + 
     310            "((\"This is the list\" NIL \"thelist\" \"thelist.test\")) " + 
     311            "NIL NIL NIL " + 
     312            "\"<1ECCDABD-5242-4180-9584-E5873C3FEA17@smith.test>\"))"; 
     313 
     314        Vector result = ImapParser.parenListParser(rawText.getBytes()); 
     315        Vector temp; 
     316 
     317        //printTree(result, 0); 
     318        assertEquals("FLAGS", (String) result.elementAt(0)); 
     319 
     320        Vector flags = (Vector) result.elementAt(1); 
     321        assertEquals("\\Seen", (String) flags.elementAt(0)); 
     322 
     323        assertEquals("ENVELOPE", (String) result.elementAt(2)); 
     324 
     325        Vector envelope = (Vector) result.elementAt(3); 
     326        assertNotNull(envelope); 
     327        assertEquals("Fri, 15 Jun 2007 12:37:27 -0400", 
     328            (byte[]) envelope.elementAt(0)); 
     329        assertEquals("[Theelist] 19\" monitor free to a good home", 
     330            (byte[]) envelope.elementAt(1)); 
     331 
     332        temp = (Vector) envelope.elementAt(2); 
     333        temp = (Vector) temp.elementAt(0); 
     334        assertEquals("Jim Smith", (byte[]) temp.elementAt(0)); 
     335        assertEquals("NIL", (String) temp.elementAt(1)); 
     336        assertEquals("jsmith", (byte[]) temp.elementAt(2)); 
     337        assertEquals("smith.test", (byte[]) temp.elementAt(3)); 
     338 
     339        temp = (Vector) envelope.elementAt(3); 
     340        temp = (Vector) temp.elementAt(0); 
     341        assertEquals("NIL", (String) temp.elementAt(0)); 
     342        assertEquals("NIL", (String) temp.elementAt(1)); 
     343        assertEquals("thelist-bounces", (byte[]) temp.elementAt(2)); 
     344        assertEquals("thelist.test", (byte[]) temp.elementAt(3)); 
     345 
     346        temp = (Vector) envelope.elementAt(4); 
     347        temp = (Vector) temp.elementAt(0); 
     348        assertEquals("This is the list", (byte[]) temp.elementAt(0)); 
     349        assertEquals("NIL", (String) temp.elementAt(1)); 
     350        assertEquals("thelist", (byte[]) temp.elementAt(2)); 
     351        assertEquals("thelist.test", (byte[]) temp.elementAt(3)); 
     352 
     353        temp = (Vector) envelope.elementAt(5); 
     354        temp = (Vector) temp.elementAt(0); 
     355        assertEquals("This is the list", (byte[]) temp.elementAt(0)); 
     356        assertEquals("NIL", (String) temp.elementAt(1)); 
     357        assertEquals("thelist", (byte[]) temp.elementAt(2)); 
     358        assertEquals("thelist.test", (byte[]) temp.elementAt(3)); 
     359 
     360        assertEquals("NIL", (String) envelope.elementAt(6)); 
     361        assertEquals("NIL", (String) envelope.elementAt(7)); 
     362        assertEquals("NIL", (String) envelope.elementAt(8)); 
     363        assertEquals("<1ECCDABD-5242-4180-9584-E5873C3FEA17@smith.test>", 
     364            (byte[]) envelope.elementAt(9)); 
     365    } 
     366 
     367    public void testParenStringParserBodyStructure() { 
     368        String rawText = "(BODYSTRUCTURE " + 
     369            "((\"TEXT\" \"PLAIN\" (\"CHARSET\" \"us-ascii\") NIL NIL \"7BIT\" 165 8 NIL NIL NIL) " + 
     370            "(\"TEXT\" \"HTML\" (\"CHARSET\" \"us-ascii\") NIL NIL \"7BIT\" 627 10 NIL NIL NIL) " + 
     371            "\"ALTERNATIVE\" (\"BOUNDARY\" \"Boundary-00=_y9RuEFduwo6YU42\") (\"INLINE\" NIL) NIL))"; 
     372 
     373        Vector result = ImapParser.parenListParser(rawText.getBytes()); 
     374        Vector temp1; 
     375        Vector temp2; 
     376        Vector temp3; 
     377 
     378        //printTree(result, 0); 
     379        assertEquals("BODYSTRUCTURE", (String) result.elementAt(0)); 
     380        temp1 = (Vector) result.elementAt(1); 
     381 
     382        temp2 = (Vector) temp1.elementAt(0); 
     383        assertEquals("TEXT", (byte[]) temp2.elementAt(0)); 
     384        assertEquals("PLAIN", (byte[]) temp2.elementAt(1)); 
     385        temp3 = (Vector) temp2.elementAt(2); 
     386        assertEquals("CHARSET", (byte[]) temp3.elementAt(0)); 
     387        assertEquals("us-ascii", (byte[]) temp3.elementAt(1)); 
     388        assertEquals("NIL", (String) temp2.elementAt(3)); 
     389        assertEquals("NIL", (String) temp2.elementAt(4)); 
     390        assertEquals("7BIT", (byte[]) temp2.elementAt(5)); 
     391        assertEquals("165", (String) temp2.elementAt(6)); 
     392        assertEquals("8", (String) temp2.elementAt(7)); 
     393        assertEquals("NIL", (String) temp2.elementAt(8)); 
     394        assertEquals("NIL", (String) temp2.elementAt(9)); 
     395        assertEquals("NIL", (String) temp2.elementAt(10)); 
     396 
     397        temp2 = (Vector) temp1.elementAt(1); 
     398        assertEquals("TEXT", (byte[]) temp2.elementAt(0)); 
     399        assertEquals("HTML", (byte[]) temp2.elementAt(1)); 
     400        temp3 = (Vector) temp2.elementAt(2); 
     401        assertEquals("CHARSET", (byte[]) temp3.elementAt(0)); 
     402        assertEquals("us-ascii", (byte[]) temp3.elementAt(1)); 
     403        assertEquals("NIL", (String) temp2.elementAt(3)); 
     404        assertEquals("NIL", (String) temp2.elementAt(4)); 
     405        assertEquals("7BIT", (byte[]) temp2.elementAt(5)); 
     406        assertEquals("627", (String) temp2.elementAt(6)); 
     407        assertEquals("10", (String) temp2.elementAt(7)); 
     408        assertEquals("NIL", (String) temp2.elementAt(8)); 
     409        assertEquals("NIL", (String) temp2.elementAt(9)); 
     410        assertEquals("NIL", (String) temp2.elementAt(10)); 
     411 
     412        assertEquals("ALTERNATIVE", (byte[]) temp1.elementAt(2)); 
     413 
     414        temp2 = (Vector) temp1.elementAt(3); 
     415        assertEquals("BOUNDARY", (byte[]) temp2.elementAt(0)); 
     416        assertEquals("Boundary-00=_y9RuEFduwo6YU42", (byte[]) temp2.elementAt(1)); 
     417 
     418        temp2 = (Vector) temp1.elementAt(4); 
     419        assertEquals("INLINE", (byte[]) temp2.elementAt(0)); 
     420        assertEquals("NIL", (String) temp2.elementAt(1)); 
     421 
     422        assertEquals("NIL", (String) temp1.elementAt(5)); 
     423    } 
     424 
     425    //    /** 
     426    //     * This method prints the parse tree for debugging purposes. 
     427    //     * @param node Node to start at. 
     428    //     * @param level Level to print from. 
     429    //     */ 
     430    //    private void printTree(Object node, int level) { 
     431    //        if(node instanceof Vector) { 
     432    //            Vector vec = (Vector)node; 
     433    //            int size = vec.size(); 
     434    //            for(int i=0; i<size; i++) 
     435    //                printTree(vec.elementAt(i), level + 1); 
     436    //        } 
     437    //        else { 
     438    //            StringBuffer buf = new StringBuffer(); 
     439    //            buf.append(level+">"); 
     440    //            for(int i=0; i<level; i++) 
     441    //                buf.append("    "); 
     442    //            if(node != null) { 
     443    //                buf.append(node.toString()); 
     444    //            } 
     445    //            else { 
     446    //                buf.append("null"); 
     447    //            } 
     448    //            System.err.println(buf.toString()); 
     449    //        } 
     450    //    } 
     451     
     452    protected void assertEquals(String expected, byte[] actual) { 
     453        assertEquals(expected, new String(actual)); 
     454    } 
    70455     
    71456    public Test suite() { 
     
    73458 
    74459        suite.addTest(new ImapParserTest("parseFolderName", new TestMethod() 
    75         { public void run(TestCase tc) {((ImapParserTest)tc).testParseFolderName(); } })); 
     460        { public void run(TestCase tc) { ((ImapParserTest) tc).testParseFolderName(); }})); 
     461 
     462        suite.addTest(new ImapParserTest("parenStringLexer1", new TestMethod() 
     463        { public void run(TestCase tc) { ((ImapParserTest) tc).testParenStringLexer1(); }})); 
     464 
     465        suite.addTest(new ImapParserTest("parenStringLexer2", new TestMethod() 
     466        { public void run(TestCase tc) { ((ImapParserTest) tc).testParenStringLexer2(); }})); 
     467 
     468        suite.addTest(new ImapParserTest("parenStringParserEnvelope1", new TestMethod() 
     469        { public void run(TestCase tc) { ((ImapParserTest) tc).testParenStringParserEnvelope1(); }})); 
     470 
     471        suite.addTest(new ImapParserTest("parenStringParserEnvelope2", new TestMethod() 
     472        { public void run(TestCase tc) { ((ImapParserTest) tc).testParenStringParserEnvelope2(); }})); 
     473 
     474        suite.addTest(new ImapParserTest("parenStringParserEnvelope3", new TestMethod() 
     475        { public void run(TestCase tc) { ((ImapParserTest) tc).testParenStringParserEnvelope3(); }})); 
     476 
     477        suite.addTest(new ImapParserTest("parenStringParserBodyStructure", new TestMethod() 
     478        { public void run(TestCase tc) { ((ImapParserTest) tc).testParenStringParserBodyStructure(); }})); 
    76479 
    77480        return suite; 
    78     }     
     481    } 
    79482} 
  • trunk/LogicMailTests/src/org/logicprobe/LogicMail/mail/imap/ImapProtocolTest.java

    r676 r689  
    3737import j2meunit.framework.TestSuite; 
    3838 
     39import org.logicprobe.LogicMail.mail.MailException; 
    3940import org.logicprobe.LogicMail.mail.MailProgressHandler; 
    4041import org.logicprobe.LogicMail.message.MessageEnvelope; 
    4142import org.logicprobe.LogicMail.util.StringParser; 
    4243 
     44import java.io.IOException; 
    4345import java.util.Calendar; 
    4446import java.util.Hashtable; 
    4547import java.util.TimeZone; 
    4648import java.util.Vector; 
     49 
    4750 
    4851/** 
     
    348351        } 
    349352    } 
    350      
     353 
    351354    public void testExecuteList7() { 
    352355        try { 
    353356            // Test specified-length encoding for path name, with spaces 
    354357            instance.addExecuteExpectation("LIST", "\"\" \"%\"", 
    355                     new String[] { 
     358                new String[] { 
    356359                    "* LIST (\\Noselect) \":\" {5}", "Marya", 
    357360                    "* LIST (\\Noselect) \":\" {11}", "Old Inboxes", 
    358                     "* LIST (\\Noinferiors) \":\" {17}", "Pre-filtered Junk" }); 
    359              
     361                    "* LIST (\\Noinferiors) \":\" {17}", "Pre-filtered Junk" 
     362                }); 
     363 
    360364            Vector result = instance.executeList("", "%", null); 
    361365            assertNotNull(result); 
     
    364368            assertTrue(result.elementAt(1) instanceof ImapProtocol.ListResponse); 
    365369            assertTrue(result.elementAt(2) instanceof ImapProtocol.ListResponse); 
    366              
     370 
    367371            ImapProtocol.ListResponse result1 = (ImapProtocol.ListResponse) result.elementAt(0); 
    368372            ImapProtocol.ListResponse result2 = (ImapProtocol.ListResponse) result.elementAt(1); 
    369373            ImapProtocol.ListResponse result3 = (ImapProtocol.ListResponse) result.elementAt(2); 
    370              
     374 
    371375            assertTrue(!result1.canSelect); 
    372376            assertTrue(!result1.noInferiors); 
    373377            assertEquals(":", result1.delim); 
    374378            assertEquals("Marya", result1.name); 
    375              
     379 
    376380            assertTrue(!result2.canSelect); 
    377381            assertTrue(!result2.noInferiors); 
    378382            assertEquals(":", result2.delim); 
    379383            assertEquals("Old Inboxes", result2.name); 
    380              
     384 
    381385            assertTrue(result3.canSelect); 
    382386            assertTrue(result3.noInferiors); 
    383387            assertEquals(":", result3.delim); 
    384388            assertEquals("Pre-filtered Junk", result3.name); 
    385              
    386389        } catch (AssertionFailedError e) { 
    387390            throw e; 
     
    391394        } 
    392395    } 
    393      
    394     private static class ShimCallback implements ImapProtocol.FetchEnvelopeCallback { 
    395         private Vector responses = new Vector(); 
    396          
    397         public void responseAvailable(ImapProtocol.FetchEnvelopeResponse response) { 
    398             if(response != null) { 
    399                 responses.addElement(response); 
    400             } 
    401         } 
    402          
    403         public ImapProtocol.FetchEnvelopeResponse[] getResponses() { 
    404             ImapProtocol.FetchEnvelopeResponse[] result = new ImapProtocol.FetchEnvelopeResponse[responses.size()]; 
    405             responses.copyInto(result); 
    406             return result; 
    407         } 
    408     } 
    409396 
    410397    public void testExecuteFetchEnvelope1() { 
    411398        try { 
    412             instance.addExecuteExpectation("FETCH", "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
     399            instance.addExecuteExpectation("FETCH", 
     400                "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
    413401                new String[] { 
    414402                    "* 1 FETCH (FLAGS (\\Answered \\Seen) UID 10 " + 
     
    425413            ShimCallback shim = new ShimCallback(); 
    426414            instance.executeFetchEnvelope(1, 1, shim, null); 
     415 
    427416            ImapProtocol.FetchEnvelopeResponse[] result = shim.getResponses(); 
    428              
     417 
    429418            assertNotNull(result); 
    430419            assertEquals(1, result.length); 
     
    482471            assertEquals("<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>", 
    483472                env.messageId); 
    484              
     473 
    485474            ImapParser.MessageSection structure = result[0].structure; 
    486475            assertNotNull(structure); 
     
    497486    public void testExecuteFetchEnvelope2() { 
    498487        try { 
    499             instance.addExecuteExpectation("FETCH", "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
     488            instance.addExecuteExpectation("FETCH", 
     489                "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
    500490                new String[] { 
    501491                    "* 1 FETCH (" + 
     
    512502            ShimCallback shim = new ShimCallback(); 
    513503            instance.executeFetchEnvelope(1, 1, shim, null); 
     504 
    514505            ImapProtocol.FetchEnvelopeResponse[] result = shim.getResponses(); 
    515              
     506 
    516507            assertNotNull(result); 
    517508            assertEquals(1, result.length); 
     
    583574    public void testExecuteFetchEnvelope3() { 
    584575        try { 
    585             instance.addExecuteExpectation("FETCH", "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
     576            instance.addExecuteExpectation("FETCH", 
     577                "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
    586578                new String[] { 
    587579                    "* 1 FETCH (" + "FLAGS (\\Seen) UID 10 " + 
     
    599591            ShimCallback shim = new ShimCallback(); 
    600592            instance.executeFetchEnvelope(1, 1, shim, null); 
     593 
    601594            ImapProtocol.FetchEnvelopeResponse[] result = shim.getResponses(); 
    602595 
     
    627620                StringParser.createDateString(env.date)); 
    628621 
    629             assertEquals("[LogicMail for BlackBerry] #93: Endless \\\"refresh folders\\\" loop when using qmail server", 
     622            assertEquals("[LogicMail for BlackBerry] #93: Endless \"refresh folders\" loop when using qmail server", 
    630623                env.subject); 
    631624 
     
    673666    public void testExecuteFetchEnvelope4() { 
    674667        try { 
    675             instance.addExecuteExpectation("FETCH", "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
     668            instance.addExecuteExpectation("FETCH", 
     669                "1:1 (FLAGS UID ENVELOPE BODYSTRUCTURE)", 
    676670                new String[] { 
    677671                    "* 1 FETCH (FLAGS (\\Seen) UID 10 " + 
     
    689683            ShimCallback shim = new ShimCallback(); 
    690684            instance.executeFetchEnvelope(1, 1, shim, null); 
     685 
    691686            ImapProtocol.FetchEnvelopeResponse[] result = shim.getResponses(); 
    692687 
     
    716711                StringParser.createDateString(env.date)); 
    717712 
    718             assertEquals("Re: [LogicMail for BlackBerry] #94: Message \\\"\\\"This message does not contain any sections that could be displayed\\\"", 
     713            assertEquals("Re: [LogicMail for BlackBerry] #94: Message \"\"This message does not contain any sections that could be displayed\"", 
    719714                env.subject); 
    720715 
     
    760755        } 
    761756    } 
    762      
     757 
    763758    public void testExecuteFetchFlags1() { 
    764759        try { 
    765760            instance.addExecuteExpectation("FETCH", "1:1 (FLAGS UID)", 
    766                     new String[] { 
    767                         "* 1 FETCH (FLAGS () UID 42)" 
    768                     }); 
    769  
    770                 ImapProtocol.FetchFlagsResponse[] result = instance.executeFetchFlags(1, 1, null); 
    771                  
    772                 assertNotNull(result); 
    773                 assertEquals(1, result.length); 
    774                 assertEquals(1, result[0].index); 
    775                 assertEquals(42, result[0].uid); 
    776                  
    777                 ImapProtocol.MessageFlags flags = result[0].flags; 
    778                 assertNotNull(flags); 
    779                 assertTrue("answered", !flags.answered); 
    780                 assertTrue("deleted", !flags.deleted); 
    781                 assertTrue("draft", !flags.draft); 
    782                 assertTrue("flagged", !flags.flagged); 
    783                 assertTrue("junk", !flags.junk); 
    784                 assertTrue("recent", !flags.recent); 
    785                 assertTrue("seen", !flags.seen); 
    786              
    787         } catch (Throwable t) { 
    788             fail("Exception thrown during test: " + t.toString()); 
    789             t.printStackTrace(); 
    790         } 
    791     } 
    792      
     761                new String[] { "* 1 FETCH (FLAGS () UID 42)" }); 
     762 
     763            ImapProtocol.FetchFlagsResponse[] result = instance.executeFetchFlags(1, 
     764                    1, null); 
     765 
     766            assertNotNull(result); 
     767            assertEquals(1, result.length); 
     768            assertEquals(1, result[0].index); 
     769            assertEquals(42, result[0].uid); 
     770 
     771            ImapProtocol.MessageFlags flags = result[0].flags; 
     772            assertNotNull(flags); 
     773            assertTrue("answered", !flags.answered); 
     774            assertTrue("deleted", !flags.deleted); 
     775            assertTrue("draft", !flags.draft); 
     776            assertTrue("flagged", !flags.flagged); 
     777            assertTrue("junk", !flags.junk); 
     778            assertTrue("recent", !flags.recent); 
     779            assertTrue("seen", !flags.seen); 
     780        } catch (Throwable t) { 
     781            fail("Exception thrown during test: " + t.toString()); 
     782            t.printStackTrace(); 
     783        } 
     784    } 
     785 
    793786    public void testExecuteFetchFlags2() { 
    794787        try { 
    795788            instance.addExecuteExpectation("FETCH", "1:1 (FLAGS UID)", 
    796                     new String[] { 
    797                         "* 1 FETCH (FLAGS (\\Seen) UID 42)" 
    798                     }); 
    799  
    800                 ImapProtocol.FetchFlagsResponse[] result = instance.executeFetchFlags(1, 1, null); 
    801                  
    802                 assertNotNull(result); 
    803                 assertEquals(1, result.length); 
    804                 assertEquals(1, result[0].index); 
    805                 assertEquals(42, result[0].uid); 
    806                  
    807                 ImapProtocol.MessageFlags flags = result[0].flags; 
    808                 assertNotNull(flags); 
    809                 assertTrue("answered", !flags.answered); 
    810                 assertTrue("deleted", !flags.deleted); 
    811                 assertTrue("draft", !flags.draft); 
    812                 assertTrue("flagged", !flags.flagged); 
    813                 assertTrue("junk", !flags.junk); 
    814                 assertTrue("recent", !flags.recent); 
    815                 assertTrue("seen", flags.seen); 
    816              
    817         } catch (Throwable t) { 
    818             fail("Exception thrown during test: " + t.toString()); 
    819             t.printStackTrace(); 
    820         } 
    821     } 
    822      
     789                new String[] { "* 1 FETCH (FLAGS (\\Seen) UID 42)" }); 
     790 
     791            ImapProtocol.FetchFlagsResponse[] result = instance.executeFetchFlags(1, 
     792                    1, null); 
     793 
     794            assertNotNull(result); 
     795            assertEquals(1, result.length); 
     796            assertEquals(1, result[0].index); 
     797            assertEquals(42, result[0].uid); 
     798 
     799            ImapProtocol.MessageFlags flags = result[0].flags; 
     800            assertNotNull(flags); 
     801            assertTrue("answered", !flags.answered); 
     802            assertTrue("deleted", !flags.deleted); 
     803            assertTrue("draft", !flags.draft); 
     804            assertTrue("flagged", !flags.flagged); 
     805            assertTrue("junk", !flags.junk); 
     806            assertTrue("recent", !flags.recent); 
     807            assertTrue("seen", flags.seen); 
     808        } catch (Throwable t) { 
     809            fail("Exception thrown during test: " + t.toString()); 
     810            t.printStackTrace(); 
     811        } 
     812    } 
     813 
    823814    public void testExecuteStore1() { 
    824815        try { 
     
    864855        } 
    865856    } 
    866      
     857 
    867858    public void testExecuteStore3() { 
    868859        try { 
    869860            instance.addExecuteExpectation("UID STORE", 
    870861                "36410 +FLAGS (\\Deleted)", 
    871                 new String[] { "* 5 FETCH (UID 36410 FLAGS (\\Deleted \\Seen $NotJunk NotJunk))" }); 
    872  
    873             ImapProtocol.MessageFlags result = instance.executeStore(36410, true, 
    874                     new String[] { "\\Deleted" }); 
     862                new String[] { 
     863                    "* 5 FETCH (UID 36410 FLAGS (\\Deleted \\Seen $NotJunk NotJunk))" 
     864                }); 
     865 
     866            ImapProtocol.MessageFlags result = instance.executeStore(36410, 
     867                    true, new String[] { "\\Deleted" }); 
    875868            assertNotNull(result); 
    876869 
     
    890883        TestSuite suite = new TestSuite("ImapProtocol"); 
    891884 
    892         suite.addTest(new ImapProtocolTest("executeCapability", new TestMethod() 
    893         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteCapability(); }})); 
    894          
    895         suite.addTest(new ImapProtocolTest("executeNamespace1", new TestMethod() 
    896         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteNamespace1(); }})); 
    897          
    898         suite.addTest(new ImapProtocolTest("executeNamespace2", new TestMethod() 
    899         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteNamespace2(); }})); 
    900          
    901         suite.addTest(new ImapProtocolTest("executeList1", new TestMethod() 
    902         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList1(); }})); 
    903          
    904         suite.addTest(new ImapProtocolTest("executeList2", new TestMethod() 
    905         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList2(); }})); 
    906          
    907         suite.addTest(new ImapProtocolTest("executeList3", new TestMethod() 
    908         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList3(); }})); 
    909          
    910         suite.addTest(new ImapProtocolTest("executeList4", new TestMethod() 
    911         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList4(); }})); 
    912          
    913         suite.addTest(new ImapProtocolTest("executeList5", new TestMethod() 
    914         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList5(); }})); 
    915          
    916         suite.addTest(new ImapProtocolTest("executeList6", new TestMethod() 
    917         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList6(); }})); 
    918          
    919         suite.addTest(new ImapProtocolTest("executeList7", new TestMethod() 
    920         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteList7(); }})); 
    921          
    922         suite.addTest(new ImapProtocolTest("executeFetchEnvelope1", new TestMethod() 
    923         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteFetchEnvelope1(); }})); 
    924          
    925         suite.addTest(new ImapProtocolTest("executeFetchEnvelope2", new TestMethod() 
    926         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteFetchEnvelope2(); }})); 
    927          
    928         suite.addTest(new ImapProtocolTest("executeFetchEnvelope3", new TestMethod() 
    929         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteFetchEnvelope3(); }})); 
    930          
    931         suite.addTest(new ImapProtocolTest("executeFetchEnvelope4", new TestMethod() 
    932         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteFetchEnvelope4(); }})); 
    933          
    934         suite.addTest(new ImapProtocolTest("executeFetchFlags1", new TestMethod() 
    935         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteFetchFlags1(); }})); 
    936          
    937         suite.addTest(new ImapProtocolTest("executeFetchFlags2", new TestMethod() 
    938         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteFetchFlags2(); }})); 
    939          
    940         suite.addTest(new ImapProtocolTest("executeStore1", new TestMethod() 
    941         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteStore1(); }})); 
    942          
    943         suite.addTest(new ImapProtocolTest("executeStore2", new TestMethod() 
    944         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteStore2(); }})); 
    945          
    946         suite.addTest(new ImapProtocolTest("executeStore3", new TestMethod() 
    947         { public void run(TestCase tc) { ((ImapProtocolTest) tc).testExecuteStore3(); }})); 
    948          
     885        suite.addTest(new ImapProtocolTest("executeCapability", 
     886                new TestMethod() { 
     887                public void run(TestCase tc) { 
     888                    ((ImapProtocolTest) tc).testExecuteCapability(); 
     889                } 
     890            })); 
     891 
     892        suite.addTest(new ImapProtocolTest("executeNamespace1", 
     893                new TestMethod() { 
     894                public void run(TestCase tc) { 
     895                    ((ImapProtocolTest) tc).testExecuteNamespace1(); 
     896                } 
     897            })); 
     898 
     899        suite.addTest(new ImapProtocolTest("executeNamespace2", 
     900                new TestMethod() { 
     901                public void run(TestCase tc) { 
     902                    ((ImapProtocolTest) tc).testExecuteNamespace2(); 
     903                } 
     904            })); 
     905 
     906        suite.addTest(new ImapProtocolTest("executeList1", 
     907                new TestMethod() { 
     908                public void run(TestCase tc) { 
     909                    ((ImapProtocolTest) tc).testExecuteList1(); 
     910                } 
     911            })); 
     912 
     913        suite.addTest(new ImapProtocolTest("executeList2", 
     914                new TestMethod() { 
     915                public void run(TestCase tc) { 
     916                    ((ImapProtocolTest) tc).testExecuteList2(); 
     917                } 
     918            })); 
     919 
     920        suite.addTest(new ImapProtocolTest("executeList3", 
     921                new TestMethod() { 
     922                public void run(TestCase tc) { 
     923                    ((ImapProtocolTest) tc).testExecuteList3(); 
     924                } 
     925            })); 
     926 
     927        suite.addTest(new ImapProtocolTest("executeList4", 
     928                new TestMethod() { 
     929                public void run(TestCase tc) { 
     930                    ((ImapProtocolTest) tc).testExecuteList4(); 
     931                } 
     932            })); 
     933 
     934        suite.addTest(new ImapProtocolTest("executeList5", 
     935                new TestMethod() { 
     936                public void run(TestCase tc) { 
     937                    ((ImapProtocolTest) tc).testExecuteList5(); 
     938                } 
     939            })); 
     940 
     941        suite.addTest(new ImapProtocolTest("executeList6", 
     942                new TestMethod() { 
     943                public void run(TestCase tc) { 
     944                    ((ImapProtocolTest) tc).testExecuteList6(); 
     945                } 
     946            })); 
     947 
     948        suite.addTest(new ImapProtocolTest("executeList7", 
     949                new TestMethod() { 
     950                public void run(TestCase tc) { 
     951                    ((ImapProtocolTest) tc).testExecuteList7(); 
     952                } 
     953            })); 
     954 
     955        suite.addTest(new ImapProtocolTest("executeFetchEnvelope1", 
     956                new TestMethod() { 
     957                public void run(TestCase tc) { 
     958                    ((ImapProtocolTest) tc).testExecuteFetchEnvelope1(); 
     959                } 
     960            })); 
     961 
     962        suite.addTest(new ImapProtocolTest("executeFetchEnvelope2", 
     963                new TestMethod() { 
     964                public void run(TestCase tc) { 
     965                    ((ImapProtocolTest) tc).testExecuteFetchEnvelope2(); 
     966                } 
     967            })); 
     968 
     969        suite.addTest(new ImapProtocolTest("executeFetchEnvelope3", 
     970                new TestMethod() { 
     971                public void run(TestCase tc) { 
     972                    ((ImapProtocolTest) tc).testExecuteFetchEnvelope3(); 
     973                } 
     974            })); 
     975 
     976        suite.addTest(new ImapProtocolTest("executeFetchEnvelope4", 
     977                new TestMethod() { 
     978                public void run(TestCase tc) { 
     979                    ((ImapProtocolTest) tc).testExecuteFetchEnvelope4(); 
     980                } 
     981            })); 
     982 
     983        suite.addTest(new ImapProtocolTest("executeFetchFlags1", 
     984                new TestMethod() { 
     985                public void run(TestCase tc) { 
     986                    ((ImapProtocolTest) tc).testExecuteFetchFlags1(); 
     987                } 
     988            })); 
     989 
     990        suite.addTest(new ImapProtocolTest("executeFetchFlags2", 
     991                new TestMethod() { 
     992                public void run(TestCase tc) { 
     993                    ((ImapProtocolTest) tc).testExecuteFetchFlags2(); 
     994                } 
     995            })); 
     996 
     997        suite.addTest(new ImapProtocolTest("executeStore1", 
     998                new TestMethod() { 
     999                public void run(TestCase tc) { 
     1000                    ((ImapProtocolTest) tc).testExecuteStore1(); 
     1001                } 
     1002            })); 
     1003 
     1004        suite.addTest(new ImapProtocolTest("executeStore2", 
     1005                new TestMethod() { 
     1006                public void run(TestCase tc) { 
     1007                    ((ImapProtocolTest) tc).testExecuteStore2(); 
     1008                } 
     1009            })); 
     1010 
     1011        suite.addTest(new ImapProtocolTest("executeStore3", 
     1012                new TestMethod() { 
     1013                public void run(TestCase tc) { 
     1014                    ((ImapProtocolTest) tc).testExecuteStore3(); 
     1015                } 
     1016            })); 
     1017 
    9491018        return suite; 
     1019    } 
     1020 
     1021    private static class ShimCallback implements ImapProtocol.FetchEnvelopeCallback { 
     1022        private Vector responses = new Vector(); 
     1023 
     1024        public void responseAvailable( 
     1025            ImapProtocol.FetchEnvelopeResponse response) { 
     1026            if (response != null) { 
     1027                responses.addElement(response); 
     1028            } 
     1029        } 
     1030 
     1031        public ImapProtocol.FetchEnvelopeResponse[] getResponses() { 
     1032            ImapProtocol.FetchEnvelopeResponse[] result = new ImapProtocol.FetchEnvelopeResponse[responses.size()]; 
     1033            responses.copyInto(result); 
     1034 
     1035            return result; 
     1036        } 
    9501037    } 
    9511038 
     
    9791066        } 
    9801067 
    981         protected String[] execute(String command, String arguments, MailProgressHandler progressHandler) { 
     1068        protected String[] execute(String command, String arguments, 
     1069            MailProgressHandler progressHandler) { 
    9821070            assertTrue("No expectations", !executeExpectations.isEmpty()); 
    9831071 
     
    9901078        } 
    9911079 
     1080        protected byte[][] executeResponse(String command, String arguments, 
     1081                MailProgressHandler progressHandler) throws IOException, MailException { 
     1082            assertTrue("No expectations", !executeExpectations.isEmpty()); 
     1083 
     1084            ExecuteExpectation expect = (ExecuteExpectation) executeExpectations.lastElement(); 
     1085            assertEquals("Bad command", expect.command, command); 
     1086            assertEquals("Bad arguments", expect.arguments, arguments); 
     1087            executeExpectations.removeElement(expect); 
     1088 
     1089            byte[][] result = new byte[expect.result.length][]; 
     1090            for(int i=0; i<expect.result.length; i++) { 
     1091                result[i] = expect.result[i].getBytes(); 
     1092            } 
     1093            return result; 
     1094        } 
     1095         
    9921096        private class ExecuteExpectation { 
    9931097            public String command; 
  • trunk/LogicMailTests/src/org/logicprobe/LogicMail/util/StringParserTest.java

    r643 r689  
    4040import java.util.Hashtable; 
    4141import java.util.TimeZone; 
    42 import java.util.Vector; 
    4342 
    4443/** 
     
    190189        assertEquals("GMT", expected, actual); 
    191190    } 
    192  
    193     /** 
    194      * Test of nestedParenStringLexer method, of class org.logicprobe.LogicMail.util.StringParser. 
    195      */ 
    196     public void testNestedParenStringLexerEnvelope1() { 
    197         System.out.println("nestedParenStringLexer (Envelope1)"); 
    198  
    199         String rawText = "(FLAGS (\\Answered \\Seen) " + 
    200             "ENVELOPE (\"Mon, 12 Mar 2007 19:38:31 -0700\" \"Re: Calm down! :-)\" " + 
    201             "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
    202             "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
    203             "((\"jim smith\" NIL \"jsmith\" \"scratch.test\")) " + 
    204             "((\"John Doe\" NIL \"jdoe\" \"generic.test\")) " + "NIL NIL " + 
    205             "\"<200703121933.25327.jdoe@generic.test>\" " + 
    206             "\"<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>\"))"; 
    207  
    208         Vector result = StringParser.nestedParenStringLexer(rawText); 
    209         Vector temp; 
    210  
    211         //printTree(result, 0); 
    212         assertEquals("FLAGS", (String) result.elementAt(0)); 
    213  
    214         Vector flags = (Vector) result.elementAt(1); 
    215         assertEquals("\\Answered", (String) flags.elementAt(0)); 
    216         assertEquals("\\Seen", (String) flags.elementAt(1)); 
    217  
    218         assertEquals("ENVELOPE", (String) result.elementAt(2)); 
    219  
    220         Vector envelope = (Vector) result.elementAt(3); 
    221         assertNotNull(envelope); 
    222         assertEquals("Mon, 12 Mar 2007 19:38:31 -0700", 
    223             (String) envelope.elementAt(0)); 
    224         assertEquals("Re: Calm down! :-)", (String) envelope.elementAt(1)); 
    225  
    226         temp = (Vector) envelope.elementAt(2); 
    227         temp = (Vector) temp.elementAt(0); 
    228         assertEquals("jim smith", (String) temp.elementAt(0)); 
    229         assertEquals("NIL", (String) temp.elementAt(1)); 
    230         assertEquals("jsmith", (String) temp.elementAt(2)); 
    231         assertEquals("scratch.test", (String) temp.elementAt(3)); 
    232  
    233         temp = (Vector) envelope.elementAt(3); 
    234         temp = (Vector) temp.elementAt(0); 
    235         assertEquals("jim smith", (String) temp.elementAt(0)); 
    236         assertEquals("NIL", (String) temp.elementAt(1)); 
    237         assertEquals("jsmith", (String) temp.elementAt(2)); 
    238         assertEquals("scratch.test", (String) temp.elementAt(3)); 
    239  
    240         temp = (Vector) envelope.elementAt(4); 
    241         temp = (Vector) temp.elementAt(0); 
    242         assertEquals("jim smith", (String) temp.elementAt(0)); 
    243         assertEquals("NIL", (String) temp.elementAt(1)); 
    244         assertEquals("jsmith", (String) temp.elementAt(2)); 
    245         assertEquals("scratch.test", (String) temp.elementAt(3)); 
    246  
    247         temp = (Vector) envelope.elementAt(5); 
    248         temp = (Vector) temp.elementAt(0); 
    249         assertEquals("John Doe", (String) temp.elementAt(0)); 
    250         assertEquals("NIL", (String) temp.elementAt(1)); 
    251         assertEquals("jdoe", (String) temp.elementAt(2)); 
    252         assertEquals("generic.test", (String) temp.elementAt(3)); 
    253  
    254         assertEquals("NIL", (String) envelope.elementAt(6)); 
    255         assertEquals("NIL", (String) envelope.elementAt(7)); 
    256         assertEquals("<200703121933.25327.jdoe@generic.test>", 
    257             (String) envelope.elementAt(8)); 
    258         assertEquals("<7b02460f0703121938sff23a05xd3c2a37dc6b9eb7d@mail.scratch.test>", 
    259             (String) envelope.elementAt(9)); 
    260     } 
    261  
    262     /** 
    263      * Test of nestedParenStringLexer method, of class org.logicprobe.LogicMail.util.StringParser. 
    264      */ 
    265     public void testNestedParenStringLexerEnvelope2() { 
    266         System.out.println("nestedParenStringLexer (Envelope2)"); 
    267  
    268         String rawText = "(FLAGS () ENVELOPE (\"Sun, 18 Mar 2007 09:04:29 -0700\" {23}\r\n" + 
    269             "[list] \"this is a test\" " + 
    270             "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
    271             "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
    272             "((\"Jim Smith\" NIL \"jsmith\" \"XXXX\")) " + 
    273             "((NIL NIL \"jsmith\" \"XXXXXXXX\")) " + 
    274             "NIL NIL NIL \"<45FD630D.1040808@XXXXX>\"))"; 
    275  
    276         Vector result = StringParser.nestedParenStringLexer(rawText); 
    277         Vector temp; 
    278  
    279         //printTree(result, 0); 
    280         assertEquals("FLAGS", (String) result.elementAt(0)); 
    281  
    282         Vector flags = (Vector) result.elementAt(1); 
    283         assertEquals(0, flags.size()); 
    284  
    285         assertEquals("ENVELOPE", (String) result.elementAt(2)); 
    286  
    287         Vector envelope = (Vector) result.elementAt(3); 
    288         assertNotNull(envelope); 
    289         assertEquals("Sun, 18 Mar 2007 09:04:29 -0700", 
    290             (String) envelope.elementAt(0)); 
    291         assertEquals("[list] \"this is a test\"", (String) envelope.elementAt(1)); 
    292  
    293         temp = (Vector) envelope.elementAt(2); 
    294         temp = (Vector) temp.elementAt(0); 
    295         assertEquals("Jim Smith", (String) temp.elementAt(0)); 
    296         assertEquals("NIL", (String) temp.elementAt(1)); 
    297         assertEquals("jsmith", (String) temp.elementAt(2)); 
    298         assertEquals("XXXX", (String) temp.elementAt(3)); 
    299  
    300         temp = (Vector) envelope.elementAt(3); 
    301         temp = (Vector) temp.elementAt(0); 
    302         assertEquals("Jim Smith", (String) temp.elementAt(0)); 
    303         assertEquals("NIL", (String) temp.elementAt(1)); 
    304         assertEquals("jsmith", (String) temp.elementAt(2)); 
    305         assertEquals("XXXX", (String) temp.elementAt(3)); 
    306  
    307         temp = (Vector) envelope.elementAt(4); 
    308         temp = (Vector) temp.elementAt(0); 
    309         assertEquals("Jim Smith", (String) temp.elementAt(0)); 
    310         assertEquals("NIL", (String) temp.elementAt(1)); 
    311         assertEquals("jsmith", (String) temp.elementAt(2)); 
    312         assertEquals("XXXX", (String) temp.elementAt(3)); 
    313  
    314         temp = (Vector) envelope.elementAt(5); 
    315         temp = (Vector) temp.elementAt(0); 
    316         assertEquals("NIL", (String) temp.elementAt(0)); 
    317         assertEquals("NIL", (String) temp.elementAt(1)); 
    318         assertEquals("jsmith", (String) temp.elementAt(2)); 
    319         assertEquals("XXXXXXXX", (String) temp.elementAt(3)); 
    320  
    321         assertEquals("NIL", (String) envelope.elementAt(6)); 
    322         assertEquals("NIL", (String) envelope.elementAt(7)); 
    323         assertEquals("NIL", (String) envelope.elementAt(8)); 
    324         assertEquals("<45FD630D.1040808@XXXXX>", (String) envelope.elementAt(9)); 
    325     } 
    326  
    327     /** 
    328      * Test of nestedParenStringLexer method, of class org.logicprobe.LogicMail.util.StringParser. 
    329      */ 
    330     public void testNestedParenStringLexerEnvelope3() { 
    331         System.out.println("nestedParenStringLexer (Envelope3)"); 
    332  
    333         String rawText = "(FLAGS (\\Seen) " + 
    334             "ENVELOPE (\"Fri, 15 Jun 2007 12:37:27 -0400\" {42}\r\n" + 
    335             "[Theelist] 19\" monitor free to a good home " + 
    336             "((\"Jim Smith\" NIL \"jsmith\" \"smith.test\")) " + 
    337             "((NIL NIL \"thelist-bounces\" \"thelist.test\")) " + 
    338             "((\"This is the list\" NIL \"thelist\" \"thelist.test\")) " + 
    339             "((\"This is the list\" NIL \"thelist\" \"thelist.test\")) " + 
    340             "NIL NIL NIL " + 
    341             "\"<1ECCDABD-5242-4180-9584-E5873C3FEA17@smith.test>\"))"; 
    342  
    343         Vector result = StringParser.nestedParenStringLexer(rawText); 
    344         Vector temp; 
    345  
    346         //printTree(result, 0); 
    347         assertEquals("FLAGS", (String) result.elementAt(0)); 
    348  
    349         Vector flags = (Vector) result.elementAt(1); 
    350         assertEquals("\\Seen", (String) flags.elementAt(0)); 
    351  
    352         assertEquals("ENVELOPE", (String) result.elementAt(2)); 
    353  
    354         Vector envelope = (Vector) result.elementAt(3); 
    355         assertNotNull(envelope); 
    356         assertEquals("Fri, 15 Jun 2007 12:37:27 -0400", 
    357             (String) envelope.elementAt(0)); 
    358         assertEquals("[Theelist] 19\" monitor free to a good home", 
    359             (String) envelope.elementAt(1)); 
    360  
    361         temp = (Vector) envelope.elementAt(2); 
    362         temp = (Vector) temp.elementAt(0); 
    363         assertEquals("Jim Smith", (String) temp.elementAt(0)); 
    364         assertEquals("NIL", (String) temp.elementAt(1)); 
    365         assertEquals("jsmith", (String) temp.elementAt(2)); 
    366         assertEquals("smith.test", (String) temp.elementAt(3)); 
    367  
    368         temp = (Vector) envelope.elementAt(3); 
    369         temp = (Vector) temp.elementAt(0); 
    370         assertEquals("NIL", (String) temp.elementAt(0)); 
    371         assertEquals("NIL", (String) temp.elementAt(1)); 
    372         assertEquals("thelist-bounces", (String) temp.elementAt(2)); 
    373         assertEquals("thelist.test", (String) temp.elementAt(3)); 
    374  
    375         temp = (Vector) envelope.elementAt(4); 
    376         temp = (Vector) temp.elementAt(0); 
    377         assertEquals("This is the list", (String) temp.elementAt(0)); 
    378         assertEquals("NIL", (String) temp.elementAt(1)); 
    379         assertEquals("thelist", (String) temp.elementAt(2)); 
    380         assertEquals("thelist.test", (String) temp.elementAt(3)); 
    381  
    382         temp = (Vector) envelope.elementAt(5); 
    383         temp = (Vector) temp.elementAt(0); 
    384         assertEquals("This is the list", (String) temp.elementAt(0)); 
    385         assertEquals("NIL", (String) temp.elementAt(1)); 
    386         assertEquals("thelist", (String) temp.elementAt(2)); 
    387         assertEquals("thelist.test", (String) temp.elementAt(3)); 
    388  
    389         assertEquals("NIL", (String) envelope.elementAt(6)); 
    390         assertEquals("NIL", (String) envelope.elementAt(7)); 
    391         assertEquals("NIL", (String) envelope.elementAt(8)); 
    392         assertEquals("<1ECCDABD-5242-4180-9584-E5873C3FEA17@smith.test>", 
    393             (String) envelope.elementAt(9)); 
    394     } 
    395  
    396     /** 
    397      * Test of nestedParenStringLexer method, of class org.logicprobe.LogicMail.util.StringParser. 
    398      */ 
    399     public void testNestedParenStringLexerBodyStructure() { 
    400         System.out.println("nestedParenStringLexer (BodyStructure)"); 
    401  
    402         String rawText = "(BODYSTRUCTURE " + 
    403             "((\"TEXT\" \"PLAIN\" (\"CHARSET\" \"us-ascii\") NIL NIL \"7BIT\" 165 8 NIL NIL NIL) " + 
    404             "(\"TEXT\" \"HTML\" (\"CHARSET\" \"us-ascii\") NIL NIL \"7BIT\" 627 10 NIL NIL NIL) " + 
    405             "\"ALTERNATIVE\" (\"BOUNDARY\" \"Boundary-00=_y9RuEFduwo6YU42\") (\"INLINE\" NIL) NIL))"; 
    406  
    407         Vector result = StringParser.nestedParenStringLexer(rawText); 
    408         Vector temp1; 
    409         Vector temp2; 
    410         Vector temp3; 
    411  
    412         //printTree(result, 0); 
    413         assertEquals("BODYSTRUCTURE", (String) result.elementAt(0)); 
    414         temp1 = (Vector) result.elementAt(1); 
    415  
    416         temp2 = (Vector) temp1.elementAt(0); 
    417         assertEquals("TEXT", (String) temp2.elementAt(0)); 
    418         assertEquals("PLAIN", (String) temp2.elementAt(1)); 
    419         temp3 = (Vector) temp2.elementAt(2); 
    420         assertEquals("CHARSET", (String) temp3.elementAt(0)); 
    421         assertEquals("us-ascii", (String) temp3.elementAt(1)); 
    422         assertEquals("NIL", (String) temp2.elementAt(3)); 
    423         assertEquals("NIL", (String) temp2.elementAt(4)); 
    424         assertEquals("7BIT", (String) temp2.elementAt(5)); 
    425         assertEquals("165", (String) temp2.elementAt(6)); 
    426         assertEquals("8", (String) temp2.elementAt(7)); 
    427         assertEquals("NIL", (String) temp2.elementAt(8)); 
    428         assertEquals("NIL", (String) temp2.elementAt(9)); 
    429         assertEquals("NIL", (String) temp2.elementAt(10)); 
    430  
    431         temp2 = (Vector) temp1.elementAt(1); 
    432         assertEquals("TEXT", (String) temp2.elementAt(0)); 
    433         assertEquals("HTML", (String) temp2.elementAt(1)); 
    434         temp3 = (Vector) temp2.elementAt(2); 
    435         assertEquals("CHARSET", (String) temp3.elementAt(0)); 
    436         assertEquals("us-ascii", (String) temp3.elementAt(1)); 
    437         assertEquals("NIL", (String) temp2.elementAt(3)); 
    438         assertEquals("NIL", (String) temp2.elementAt(4)); 
    439         assertEquals("7BIT", (String) temp2.elementAt(5)); 
    440         assertEquals("627", (String) temp2.elementAt(6)); 
    441         assertEquals("10", (String) temp2.elementAt(7)); 
    442         assertEquals("NIL", (String) temp2.elementAt(8)); 
    443         assertEquals("NIL", (String) temp2.elementAt(9)); 
    444         assertEquals("NIL", (String) temp2.elementAt(10)); 
    445  
    446         assertEquals("ALTERNATIVE", (String) temp1.elementAt(2)); 
    447  
    448         temp2 = (Vector) temp1.elementAt(3); 
    449         assertEquals("BOUNDARY", (String) temp2.elementAt(0)); 
    450         assertEquals("Boundary-00=_y9RuEFduwo6YU42", (String) temp2.elementAt(1)); 
    451  
    452         temp2 = (Vector) temp1.elementAt(4); 
    453         assertEquals("INLINE", (String) temp2.elementAt(0)); 
    454         assertEquals("NIL", (String) temp2.elementAt(1)); 
    455  
    456         assertEquals("NIL", (String) temp1.elementAt(5)); 
    457     } 
    458  
    459     //    /** 
    460     //     * This method prints the parse tree for debugging purposes. 
    461     //     * @param node Node to start at. 
    462     //     * @param level Level to print from. 
    463     //     */ 
    464     //    private void printTree(Object node, int level) { 
    465     //        if(node instanceof Vector) { 
    466     //            Vector vec = (Vector)node; 
    467     //            int size = vec.size(); 
    468     //            for(int i=0; i<size; i++) 
    469     //                printTree(vec.elementAt(i), level + 1); 
    470     //        } 
    471     //        else { 
    472     //            StringBuffer buf = new StringBuffer(); 
    473     //            buf.append(level+">"); 
    474     //            for(int i=0; i<level; i++) 
    475     //                buf.append("    "); 
    476     //            if(node != null) { 
    477     //                buf.append(node.toString()); 
    478     //            } 
    479     //            else { 
    480     //                buf.append("null"); 
    481     //            } 
    482     //            System.err.println(buf.toString()); 
    483     //        } 
    484     //    } 
    485191 
    486192    /** 
     
    839545        String text = "=A1Hol=E1 Se=F1or!"; 
    840546        String expectedResult = "¡Holá Señor!"; 
    841         String result = StringParser.decodeQuotedPrintable(text); 
     547        String result = StringParser.decodeQuotedPrintable(text.getBytes()); 
    842548        assertEquals(expectedResult, result); 
    843549    } 
     
    853559            "ow=20are=20you=20today?"; 
    854560        String expectedResult = "¡Holá Señor!  How are you today?"; 
    855         String result = StringParser.decodeQuotedPrintable(text); 
     561        String result = StringParser.decodeQuotedPrintable(text.getBytes()); 
    856562        assertEquals(expectedResult, result); 
    857563    } 
     
    969675        { public void run(TestCase tc) { ((StringParserTest) tc).testCreateDateString(); }})); 
    970676         
    971         testSuite.addTest(new StringParserTest("nestedParenStringLexerEnvelope1", new TestMethod() 
    972         { public void run(TestCase tc) { ((StringParserTest) tc).testNestedParenStringLexerEnvelope1(); }})); 
    973          
    974         testSuite.addTest(new StringParserTest("nestedParenStringLexerEnvelope2", new TestMethod() 
    975         { public void run(TestCase tc) { ((StringParserTest) tc).testNestedParenStringLexerEnvelope2(); }})); 
    976          
    977         testSuite.addTest(new StringParserTest("nestedParenStringLexerEnvelope3", new TestMethod() 
    978         { public void run(TestCase tc) { ((StringParserTest) tc).testNestedParenStringLexerEnvelope3(); }})); 
    979          
    980         testSuite.addTest(new StringParserTest("nestedParenStringLexerBodyStructure", new TestMethod() 
    981         { public void run(TestCase tc) { ((StringParserTest) tc).testNestedParenStringLexerBodyStructure(); }})); 
    982          
    983677        testSuite.addTest(new StringParserTest("parseMailHeaders", new TestMethod() 
    984678        { public void run(TestCase tc) { ((StringParserTest) tc).testParseMailHeaders(); }})); 
  • trunk/LogicMailTests/src/org/logicprobe/LogicMail/util/UtilTests.java

    r670 r689  
    4848        TestSuite testSuite = new TestSuite("LogicMail.util"); 
    4949        testSuite.addTest(new StringParserTest().suite()); 
     50        testSuite.addTest(new StringArraysTest().suite()); 
    5051        testSuite.addTest(new SerializableHashtableTest().suite()); 
    5152        testSuite.addTest(new EventListenerListTest().suite()); 
Note: See TracChangeset for help on using the changeset viewer.