示例#1
0
        internal async Task <ImapToken> ReadTokenAsync(string specials, bool doAsync, CancellationToken cancellationToken)
        {
            CheckDisposed();

            if (nextToken != null)
            {
                var token = nextToken;
                nextToken = null;
                return(token);
            }

            input[inputEnd] = (byte)'\n';

            // skip over white space between tokens...
            do
            {
                while (IsWhiteSpace(input[inputIndex]))
                {
                    inputIndex++;
                }

                if (inputIndex < inputEnd)
                {
                    break;
                }

                await ReadAheadAsync(1, doAsync, cancellationToken).ConfigureAwait(false);

                input[inputEnd] = (byte)'\n';
            } while (true);

            char c = (char)input[inputIndex];

            if (c == '"')
            {
                return(await ReadQuotedStringTokenAsync(doAsync, cancellationToken).ConfigureAwait(false));
            }

            if (c == '{')
            {
                return(await ReadLiteralTokenAsync(doAsync, cancellationToken).ConfigureAwait(false));
            }

            if (c == '\\')
            {
                return(await ReadFlagTokenAsync(specials, doAsync, cancellationToken).ConfigureAwait(false));
            }

            if (IsAtom(input[inputIndex], specials))
            {
                return(await ReadAtomTokenAsync(specials, doAsync, cancellationToken).ConfigureAwait(false));
            }

            // special character token
            inputIndex++;

            return(new ImapToken((ImapTokenType)c, c));
        }
示例#2
0
        /// <summary>
        /// Ungets a token.
        /// </summary>
        /// <param name="token">The token.</param>
        public void UngetToken(ImapToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }

            nextToken = token;
        }
示例#3
0
        /// <summary>
        /// Reads the next available token from the stream.
        /// </summary>
        /// <returns>The token.</returns>
        /// <param name="specials">A list of characters that are not legal in bare string tokens.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ObjectDisposedException">
        /// The stream has been disposed.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        public ImapToken ReadToken(string specials, CancellationToken cancellationToken)
        {
            CheckDisposed();

            if (nextToken != null)
            {
                var token = nextToken;
                nextToken = null;
                return(token);
            }

            unsafe
            {
                fixed(byte *inbuf = input)
                {
                    byte *inptr = inbuf + inputIndex;
                    byte *inend = inbuf + inputEnd;

                    *inend = (byte)'\n';

                    // skip over white space between tokens...
                    do
                    {
                        while (IsWhiteSpace(*inptr))
                        {
                            inptr++;
                        }

                        if (inptr < inend)
                        {
                            break;
                        }

                        inputIndex = (int)(inptr - inbuf);

                        ReadAhead(1, cancellationToken);

                        inptr = inbuf + inputIndex;
                        inend = inbuf + inputEnd;

                        *inend = (byte)'\n';
                    } while (true);

                    inputIndex = (int)(inptr - inbuf);
                    char c = (char)*inptr;

                    if (c == '"')
                    {
                        return(ReadQuotedStringToken(inbuf, cancellationToken));
                    }

                    if (c == '{')
                    {
                        return(ReadLiteralToken(inbuf, cancellationToken));
                    }

                    if (c == '\\')
                    {
                        return(ReadFlagToken(inbuf, specials, cancellationToken));
                    }

                    if (IsAtom(*inptr, specials))
                    {
                        return(ReadAtomToken(inbuf, specials, cancellationToken));
                    }

                    // special character token
                    inputIndex++;

                    return(new ImapToken((ImapTokenType)c, c));
                }
            }
        }
示例#4
0
        /// <summary>
        /// Reads the next available token from the stream.
        /// </summary>
        /// <returns>The token.</returns>
        /// <exception cref="System.ObjectDisposedException">
        /// The stream has been disposed.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        public ImapToken ReadToken(CancellationToken cancellationToken)
        {
            CheckDisposed ();

            if (nextToken != null) {
                var token = nextToken;
                nextToken = null;
                return token;
            }

            unsafe {
                fixed (byte* inbuf = input) {
                    byte* inptr = inbuf + inputIndex;
                    byte* inend = inbuf + inputEnd;

                    *inend = (byte) '\n';

                    // skip over white space between tokens...
                    do {
                        while (IsWhiteSpace (*inptr))
                            inptr++;

                        if (inptr < inend)
                            break;

                        inputIndex = (int) (inptr - inbuf);

                        cancellationToken.ThrowIfCancellationRequested ();
                        ReadAhead (inbuf, 1);

                        inptr = inbuf + inputIndex;
                        inend = inbuf + inputEnd;

                        *inend = (byte) '\n';
                    } while (true);

                    inputIndex = (int) (inptr - inbuf);
                    char c = (char) *inptr;

                    if (c == '"')
                        return ReadQuotedStringToken (inbuf, cancellationToken);

                    if (c == '{')
                        return ReadLiteralToken (inbuf, cancellationToken);

                    if (c == '\\')
                        return ReadFlagToken (inbuf, cancellationToken);

                    if (c != '+' && IsAtom (*inptr))
                        return ReadAtomToken (inbuf, cancellationToken);

                    // special character token
                    inputIndex++;

                    return new ImapToken ((ImapTokenType) c, c);
                }
            }
        }
示例#5
0
        /// <summary>
        /// Ungets a token.
        /// </summary>
        /// <param name="token">The token.</param>
        public void UngetToken(ImapToken token)
        {
            if (token == null)
                throw new ArgumentNullException ("token");

            nextToken = token;
        }
示例#6
0
 static void ThreadMatches(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
 {
     ic.UserData = ImapUtils.ParseThreads (engine, ic.CancellationToken);
 }
示例#7
0
        internal static ImapProtocolException UnexpectedToken(ImapToken token, bool greeting)
        {
            string message;

            if (greeting)
                message = string.Format ("Unexpected token in IMAP greeting: {0}", token);
            else
                message = string.Format ("Unexpected token in IMAP response: {0}", token);

            return new ImapProtocolException (message);
        }
示例#8
0
        static void FetchSummaryItems(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var token = engine.ReadToken (ic.CancellationToken);

            if (token.Type != ImapTokenType.OpenParen)
                throw ImapEngine.UnexpectedToken (token, false);

            var results = (SortedDictionary<int, MessageSummary>) ic.UserData;
            MessageSummary summary;

            if (!results.TryGetValue (index, out summary)) {
                summary = new MessageSummary (index);
                results.Add (index, summary);
            }

            do {
                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
                    break;

                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                var atom = (string) token.Value;
                ulong value64;
                uint value;

                switch (atom) {
                case "INTERNALDATE":
                    token = engine.ReadToken (ic.CancellationToken);

                    switch (token.Type) {
                    case ImapTokenType.QString:
                    case ImapTokenType.Atom:
                        summary.InternalDate = ImapUtils.ParseInternalDate ((string) token.Value);
                        break;
                    case ImapTokenType.Nil:
                        summary.InternalDate = null;
                        break;
                    default:
                        throw ImapEngine.UnexpectedToken (token, false);
                    }
                    break;
                case "RFC822.SIZE":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value) || value == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.MessageSize = value;
                    break;
                case "BODYSTRUCTURE":
                case "BODY":
                    summary.Body = ImapUtils.ParseBody (engine, string.Empty, ic.CancellationToken);
                    break;
                case "ENVELOPE":
                    summary.Envelope = ImapUtils.ParseEnvelope (engine, ic.CancellationToken);
                    break;
                case "FLAGS":
                    summary.Flags = ImapUtils.ParseFlagsList (engine, ic.CancellationToken);
                    break;
                case "MODSEQ":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.CloseParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.ModSeq = value64;
                    break;
                case "UID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value) || value == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.Uid = new UniqueId (value);
                    break;
                case "X-GM-MSGID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.GMailMessageId = value64;
                    break;
                case "X-GM-THRID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.GMailThreadId = value64;
                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }
            } while (true);

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);
        }
示例#9
0
        static void SearchMatches(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var matches = new HashSet<UniqueId> ();
            UniqueId[] uids;
            ImapToken token;
            uint uid;

            do {
                token = engine.PeekToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.Eoln)
                    break;

                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out uid) || uid == 0)
                    throw ImapEngine.UnexpectedToken (token, false);

                matches.Add (new UniqueId (uid));
            } while (true);

            uids = matches.ToArray ();
            Array.Sort (uids);

            ic.UserData = uids;
        }
示例#10
0
        static void ESearchMatches(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var token = engine.ReadToken (ic.CancellationToken);
            UniqueId[] uids = null;
            uint min, max, count;
            bool uid = false;
            string atom;
            string tag;

            if (token.Type == ImapTokenType.OpenParen) {
                // optional search correlator
                do {
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type == ImapTokenType.CloseParen)
                        break;

                    if (token.Type != ImapTokenType.Atom)
                        throw ImapEngine.UnexpectedToken (token, false);

                    atom = (string) token.Value;

                    if (atom == "TAG") {
                        token = engine.ReadToken (ic.CancellationToken);

                        if (token.Type != ImapTokenType.Atom && token.Type != ImapTokenType.QString)
                            throw ImapEngine.UnexpectedToken (token, false);

                        tag = (string) token.Value;

                        if (tag != ic.Tag)
                            throw new ImapProtocolException ("Unexpected TAG value in untagged ESEARCH response: " + tag);
                    }
                } while (true);

                token = engine.ReadToken (ic.CancellationToken);
            }

            if (token.Type == ImapTokenType.Atom && ((string) token.Value) == "UID") {
                token = engine.ReadToken (ic.CancellationToken);
                uid = true;
            }

            do {
                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                atom = (string) token.Value;

                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                switch (atom) {
                case "COUNT":
                    if (!uint.TryParse ((string) token.Value, out count))
                        throw ImapEngine.UnexpectedToken (token, false);
                    break;
                case "MIN":
                    if (!uint.TryParse ((string) token.Value, out min))
                        throw ImapEngine.UnexpectedToken (token, false);
                    break;
                case "MAX":
                    if (!uint.TryParse ((string) token.Value, out max))
                        throw ImapEngine.UnexpectedToken (token, false);
                    break;
                case "ALL":
                    if (!ImapUtils.TryParseUidSet ((string) token.Value, out uids))
                        throw ImapEngine.UnexpectedToken (token, false);
                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }

                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.Eoln) {
                    // unget the eoln token
                    engine.Stream.UngetToken (token);
                    break;
                }
            } while (true);

            if (!uid && uids != null) {
                var indexes = new int[uids.Length];
                for (int i = 0; i < uids.Length; i++)
                    indexes[i] = (int) uids[i].Id - 1;

                ic.UserData = indexes;
            } else {
                ic.UserData = uids;
            }
        }
示例#11
0
        static void FetchMessageBody(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var token = engine.ReadToken (ic.CancellationToken);
            var args = new MessageFlagsChangedEventArgs (index);
            var type = FetchReturnType.MimeMessage;
            bool emit = false;

            if (token.Type != ImapTokenType.OpenParen)
                throw ImapEngine.UnexpectedToken (token, false);

            do {
                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
                    break;

                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                var atom = (string) token.Value;
                ulong modseq;
                uint uid;

                switch (atom) {
                case "BODY":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenBracket)
                        throw ImapEngine.UnexpectedToken (token, false);

                    do {
                        token = engine.ReadToken (ic.CancellationToken);

                        if (token.Type == ImapTokenType.CloseBracket)
                            break;

                        if (token.Type == ImapTokenType.OpenParen) {
                            type = FetchReturnType.Stream;

                            do {
                                token = engine.ReadToken (ic.CancellationToken);

                                if (token.Type == ImapTokenType.CloseParen)
                                    break;

                                if (token.Type != ImapTokenType.Atom)
                                    throw ImapEngine.UnexpectedToken (token, false);
                            } while (true);
                        } else if (token.Type != ImapTokenType.Atom) {
                            throw ImapEngine.UnexpectedToken (token, false);
                        } else {
                            type = FetchReturnType.MimeEntity;
                        }
                    } while (true);

                    if (token.Type != ImapTokenType.CloseBracket)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type == ImapTokenType.Atom) {
                        var region = (string) token.Value;

                        if (region[0] != '<' || region[region.Length - 1] != '>')
                            throw ImapEngine.UnexpectedToken (token, false);

                        token = engine.ReadToken (ic.CancellationToken);

                        type = FetchReturnType.Stream;
                    }

                    if (token.Type != ImapTokenType.Literal)
                        throw ImapEngine.UnexpectedToken (token, false);

                    switch (type) {
                    case FetchReturnType.MimeMessage:
                        ic.UserData = MimeMessage.Load (engine.Stream, ic.CancellationToken);
                        break;
                    case FetchReturnType.MimeEntity:
                        ic.UserData = MimeEntity.Load (engine.Stream, ic.CancellationToken);
                        break;
                    default:
                        var stream = new MemoryBlockStream ();
                        var buf = new byte[4096];
                        int nread;

                        ic.CancellationToken.ThrowIfCancellationRequested ();
                        while ((nread = engine.Stream.Read (buf, 0, buf.Length)) > 0) {
                            ic.CancellationToken.ThrowIfCancellationRequested ();
                            stream.Write (buf, 0, nread);
                        }

                        ic.UserData = stream;
                        break;
                    }

                    break;
                case "UID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out uid) || uid == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    args.Uid = new UniqueId (uid);
                    break;
                case "MODSEQ":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out modseq) || modseq == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.CloseParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    args.ModSeq = modseq;
                    break;
                case "FLAGS":
                    // even though we didn't request this piece of information, the IMAP server
                    // may send it if another client has recently modified the message flags.
                    args.Flags = ImapUtils.ParseFlagsList (engine, ic.CancellationToken);
                    emit = true;
                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }
            } while (true);

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);

            if (emit)
                ic.Folder.OnFlagsChanged (args);
        }
示例#12
0
 static void QResyncFetch(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
 {
     ic.Folder.OnFetch (engine, index, ic.CancellationToken);
 }
示例#13
0
        /// <summary>
        /// Parses an untagged LIST or LSUB response.
        /// </summary>
        /// <param name="engine">The IMAP engine.</param>
        /// <param name="ic">The IMAP command.</param>
        /// <param name="index">The index.</param>
        /// <param name="tok">The token.</param>
        public static void ParseFolderList(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var        token = engine.ReadToken(ic.CancellationToken);
            var        list  = (List <ImapFolder>)ic.UserData;
            var        attrs = FolderAttributes.None;
            string     encodedName;
            ImapFolder folder;
            char       delim;

            // parse the folder attributes list
            if (token.Type != ImapTokenType.OpenParen)
            {
                throw ImapEngine.UnexpectedToken(token, false);
            }

            token = engine.ReadToken(ic.CancellationToken);

            while (token.Type == ImapTokenType.Flag || token.Type == ImapTokenType.Atom)
            {
                string atom = (string)token.Value;

                switch (atom)
                {
                case "\\NoInferiors":   attrs |= FolderAttributes.NoInferiors; break;

                case "\\Noselect":      attrs |= FolderAttributes.NoSelect; break;

                case "\\Marked":        attrs |= FolderAttributes.Marked; break;

                case "\\Unmarked":      attrs |= FolderAttributes.Unmarked; break;

                case "\\NonExistent":   attrs |= FolderAttributes.NonExistent; break;

                case "\\Subscribed":    attrs |= FolderAttributes.Subscribed; break;

                case "\\Remote":        attrs |= FolderAttributes.Remote; break;

                case "\\HasChildren":   attrs |= FolderAttributes.HasChildren; break;

                case "\\HasNoChildren": attrs |= FolderAttributes.HasNoChildren; break;

                case "\\All":           attrs |= FolderAttributes.All; break;

                case "\\Archive":       attrs |= FolderAttributes.Archive; break;

                case "\\Drafts":        attrs |= FolderAttributes.Drafts; break;

                case "\\Flagged":       attrs |= FolderAttributes.Flagged; break;

                case "\\Junk":          attrs |= FolderAttributes.Junk; break;

                case "\\Sent":          attrs |= FolderAttributes.Sent; break;

                case "\\Trash":         attrs |= FolderAttributes.Trash; break;

                // XLIST flags:
                case "\\AllMail":       attrs |= FolderAttributes.All; break;

                case "\\Important":     attrs |= FolderAttributes.Flagged; break;

                case "\\Inbox":         break;

                case "\\Spam":          attrs |= FolderAttributes.Junk; break;

                case "\\Starred":       attrs |= FolderAttributes.Flagged; break;
                }

                token = engine.ReadToken(ic.CancellationToken);
            }

            if (token.Type != ImapTokenType.CloseParen)
            {
                throw ImapEngine.UnexpectedToken(token, false);
            }

            // parse the path delimeter
            token = engine.ReadToken(ic.CancellationToken);

            if (token.Type == ImapTokenType.QString)
            {
                var qstring = (string)token.Value;

                delim = qstring[0];
            }
            else if (token.Type == ImapTokenType.Nil)
            {
                delim = '\0';
            }
            else
            {
                throw ImapEngine.UnexpectedToken(token, false);
            }

            // parse the folder name
            token = engine.ReadToken(ic.CancellationToken);

            switch (token.Type)
            {
            case ImapTokenType.Literal:
                encodedName = engine.ReadLiteral(ic.CancellationToken);
                break;

            case ImapTokenType.QString:
            case ImapTokenType.Atom:
                encodedName = (string)token.Value;
                break;

            default:
                throw ImapEngine.UnexpectedToken(token, false);
            }

            if (engine.FolderCache.TryGetValue(encodedName, out folder))
            {
                folder.Attributes = (folder.Attributes & ~(FolderAttributes.Marked | FolderAttributes.Unmarked)) | attrs;
            }
            else
            {
                folder = new ImapFolder(engine, encodedName, attrs, delim);
                engine.FolderCache.Add(encodedName, folder);
            }

            list.Add(folder);
        }
示例#14
0
        /// <summary>
        /// Parses an untagged LIST or LSUB response.
        /// </summary>
        /// <param name="engine">The IMAP engine.</param>
        /// <param name="ic">The IMAP command.</param>
        /// <param name="index">The index.</param>
        /// <param name="tok">The token.</param>
        public static void ParseFolderList(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var token = engine.ReadToken (ic.CancellationToken);
            var list = (List<ImapFolder>) ic.UserData;
            var attrs = FolderAttributes.None;
            string encodedName;
            ImapFolder folder;
            char delim;

            // parse the folder attributes list
            if (token.Type != ImapTokenType.OpenParen)
                throw ImapEngine.UnexpectedToken (token, false);

            token = engine.ReadToken (ic.CancellationToken);

            while (token.Type == ImapTokenType.Flag || token.Type == ImapTokenType.Atom) {
                string atom = (string) token.Value;

                switch (atom) {
                case "\\NoInferiors":   attrs |= FolderAttributes.NoInferiors; break;
                case "\\Noselect":      attrs |= FolderAttributes.NoSelect; break;
                case "\\Marked":        attrs |= FolderAttributes.Marked; break;
                case "\\Unmarked":      attrs |= FolderAttributes.Unmarked; break;
                case "\\NonExistent":   attrs |= FolderAttributes.NonExistent; break;
                case "\\Subscribed":    attrs |= FolderAttributes.Subscribed; break;
                case "\\Remote":        attrs |= FolderAttributes.Remote; break;
                case "\\HasChildren":   attrs |= FolderAttributes.HasChildren; break;
                case "\\HasNoChildren": attrs |= FolderAttributes.HasNoChildren; break;
                case "\\All":           attrs |= FolderAttributes.All; break;
                case "\\Archive":       attrs |= FolderAttributes.Archive; break;
                case "\\Drafts":        attrs |= FolderAttributes.Drafts; break;
                case "\\Flagged":       attrs |= FolderAttributes.Flagged; break;
                case "\\Junk":          attrs |= FolderAttributes.Junk; break;
                case "\\Sent":          attrs |= FolderAttributes.Sent; break;
                case "\\Trash":         attrs |= FolderAttributes.Trash; break;
                    // XLIST flags:
                case "\\AllMail":       attrs |= FolderAttributes.All; break;
                case "\\Important":     attrs |= FolderAttributes.Flagged; break;
                case "\\Inbox":         break;
                case "\\Spam":          attrs |= FolderAttributes.Junk; break;
                case "\\Starred":       attrs |= FolderAttributes.Flagged; break;
                }

                token = engine.ReadToken (ic.CancellationToken);
            }

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);

            // parse the path delimeter
            token = engine.ReadToken (ic.CancellationToken);

            if (token.Type == ImapTokenType.QString) {
                var qstring = (string) token.Value;

                delim = qstring[0];
            } else if (token.Type == ImapTokenType.Nil) {
                delim = '\0';
            } else {
                throw ImapEngine.UnexpectedToken (token, false);
            }

            // parse the folder name
            token = engine.ReadToken (ic.CancellationToken);

            switch (token.Type) {
            case ImapTokenType.Literal:
                encodedName = engine.ReadLiteral (ic.CancellationToken);
                break;
            case ImapTokenType.QString:
            case ImapTokenType.Atom:
                encodedName = (string) token.Value;
                break;
            default:
                throw ImapEngine.UnexpectedToken (token, false);
            }

            if (engine.FolderCache.TryGetValue (encodedName, out folder)) {
                folder.Attributes = (folder.Attributes & ~(FolderAttributes.Marked | FolderAttributes.Unmarked)) | attrs;
            } else {
                folder = new ImapFolder (engine, encodedName, attrs, delim);
                engine.FolderCache.Add (encodedName, folder);
            }

            list.Add (folder);
        }
示例#15
0
        static void FetchSummaryItems(ImapEngine engine, ImapCommand ic, int index, ImapToken tok)
        {
            var token = engine.ReadToken (ic.CancellationToken);

            if (token.Type != ImapTokenType.OpenParen)
                throw ImapEngine.UnexpectedToken (token, false);

            var results = (SortedDictionary<int, MessageSummary>) ic.UserData;
            MessageSummary summary;

            if (!results.TryGetValue (index, out summary)) {
                summary = new MessageSummary (index);
                results.Add (index, summary);
            }

            do {
                token = engine.ReadToken (ic.CancellationToken);

                if (token.Type == ImapTokenType.CloseParen || token.Type == ImapTokenType.Eoln)
                    break;

                if (token.Type != ImapTokenType.Atom)
                    throw ImapEngine.UnexpectedToken (token, false);

                var atom = (string) token.Value;
                ulong value64;
                uint value;

                switch (atom) {
                case "INTERNALDATE":
                    token = engine.ReadToken (ic.CancellationToken);

                    switch (token.Type) {
                    case ImapTokenType.QString:
                    case ImapTokenType.Atom:
                        summary.InternalDate = ImapUtils.ParseInternalDate ((string) token.Value);
                        break;
                    case ImapTokenType.Nil:
                        summary.InternalDate = null;
                        break;
                    default:
                        throw ImapEngine.UnexpectedToken (token, false);
                    }
                    break;
                case "RFC822.SIZE":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value))
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.MessageSize = value;
                    break;
                case "BODYSTRUCTURE":
                    summary.Body = ImapUtils.ParseBody (engine, string.Empty, ic.CancellationToken);
                    break;
                case "BODY":
                    token = engine.PeekToken (ic.CancellationToken);

                    if (token.Type == ImapTokenType.OpenBracket) {
                        // consume the '['
                        token = engine.ReadToken (ic.CancellationToken);

                        if (token.Type != ImapTokenType.OpenBracket)
                            throw ImapEngine.UnexpectedToken (token, false);

                        // References were requested...

                        do {
                            token = engine.ReadToken (ic.CancellationToken);

                            if (token.Type == ImapTokenType.CloseBracket)
                                break;

                            if (token.Type == ImapTokenType.OpenParen) {
                                do {
                                    token = engine.ReadToken (ic.CancellationToken);

                                    if (token.Type == ImapTokenType.CloseParen)
                                        break;

                                    if (token.Type != ImapTokenType.Atom)
                                        throw ImapEngine.UnexpectedToken (token, false);
                                } while (true);
                            } else if (token.Type != ImapTokenType.Atom) {
                                throw ImapEngine.UnexpectedToken (token, false);
                            }
                        } while (true);

                        if (token.Type != ImapTokenType.CloseBracket)
                            throw ImapEngine.UnexpectedToken (token, false);

                        token = engine.ReadToken (ic.CancellationToken);

                        if (token.Type != ImapTokenType.Literal)
                            throw ImapEngine.UnexpectedToken (token, false);

                        var message = MimeMessage.Load (engine.Stream, ic.CancellationToken);

                        summary.References = message.References;
                    } else {
                        summary.Body = ImapUtils.ParseBody (engine, string.Empty, ic.CancellationToken);
                    }
                    break;
                case "ENVELOPE":
                    summary.Envelope = ImapUtils.ParseEnvelope (engine, ic.CancellationToken);
                    break;
                case "FLAGS":
                    summary.Flags = ImapUtils.ParseFlagsList (engine, ic.CancellationToken);
                    break;
                case "MODSEQ":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.OpenParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.CloseParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.ModSeq = value64;
                    break;
                case "UID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !uint.TryParse ((string) token.Value, out value) || value == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.UniqueId = new UniqueId (value);
                    break;
                case "X-GM-MSGID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.GMailMessageId = value64;
                    break;
                case "X-GM-THRID":
                    token = engine.ReadToken (ic.CancellationToken);

                    if (token.Type != ImapTokenType.Atom || !ulong.TryParse ((string) token.Value, out value64) || value64 == 0)
                        throw ImapEngine.UnexpectedToken (token, false);

                    summary.GMailThreadId = value64;
                    break;
                case "X-GM-LABELS":
                    token = engine.ReadToken (ic.CancellationToken);
                    if (token.Type != ImapTokenType.OpenParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    token = engine.ReadToken (ic.CancellationToken);

                    summary.GMailLabels = new List<string> ();

                    while (token.Type == ImapTokenType.Flag || token.Type == ImapTokenType.Atom || token.Type == ImapTokenType.QString) {
                        var label = ImapEncoding.Decode ((string) token.Value);

                        summary.GMailLabels.Add (label);

                        token = engine.ReadToken (ic.CancellationToken);
                    }

                    if (token.Type != ImapTokenType.CloseParen)
                        throw ImapEngine.UnexpectedToken (token, false);

                    break;
                default:
                    throw ImapEngine.UnexpectedToken (token, false);
                }
            } while (true);

            if (token.Type != ImapTokenType.CloseParen)
                throw ImapEngine.UnexpectedToken (token, false);
        }
示例#16
0
        public static ImapToken Create(ImapTokenType type, ByteArrayBuilder builder)
        {
            string value;

            if (type == ImapTokenType.Flag)
            {
                foreach (var token in CommonMessageFlagTokens)
                {
                    value = (string)token.Value;

                    if (builder.Equals(value, true))
                    {
                        return(token);
                    }
                }
            }
            else if (builder.Equals("NIL", true))
            {
                foreach (var token in NilTokens)
                {
                    value = (string)token.Value;

                    if (builder.Equals(value))
                    {
                        return(token);
                    }
                }

                var nil = new ImapToken(ImapTokenType.Nil, builder.ToString());
                NilTokens.Add(nil);

                return(nil);
            }
            else
            {
                if (builder.Equals("FETCH", false))
                {
                    return(Fetch);
                }
                if (builder.Equals("BODY", false))
                {
                    return(Body);
                }
                if (builder.Equals("BODYSTRUCTURE", false))
                {
                    return(BodyStructure);
                }
                if (builder.Equals("ENVELOPE", false))
                {
                    return(Envelope);
                }
                if (builder.Equals("FLAGS", false))
                {
                    return(Flags);
                }
                if (builder.Equals("INTERNALDATE", false))
                {
                    return(InternalDate);
                }
                if (builder.Equals("MODSEQ", false))
                {
                    return(ModSeq);
                }
                if (builder.Equals("RFC822.SIZE", false))
                {
                    return(Rfc822Size);
                }
                if (builder.Equals("UID", false))
                {
                    return(Uid);
                }
                if (builder.Equals("X-GM-LABELS", false))
                {
                    return(XGMLabels);
                }
                if (builder.Equals("X-GM-MSGID", false))
                {
                    return(XGMMsgId);
                }
                if (builder.Equals("X-GM-THRID", false))
                {
                    return(XGMThrId);
                }
            }

            value = builder.ToString();

            return(new ImapToken(type, value));
        }