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)); }
/// <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; }
/// <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)); } } }
/// <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); } } }
/// <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; }
static void ThreadMatches(ImapEngine engine, ImapCommand ic, int index, ImapToken tok) { ic.UserData = ImapUtils.ParseThreads (engine, ic.CancellationToken); }
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); }
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); }
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; }
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; } }
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); }
static void QResyncFetch(ImapEngine engine, ImapCommand ic, int index, ImapToken tok) { ic.Folder.OnFetch (engine, index, ic.CancellationToken); }
/// <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); }
/// <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); }
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); }
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)); }