void ClearLoginTokenState ()
		{
			literalState = ImapLiteralState.None;
			qstringState = ImapQStringState.None;
			tokenType = ImapLoginTokenType.None;
			literalOctets = 0;
			literalSeen = 0;
		}
		bool SkipLiteralToken (List<AuthenticationSecret> secrets, byte[] buffer, ref int index, int endIndex, byte sentinel)
		{
			if (literalState == ImapLiteralState.Octets) {
				while (index < endIndex && buffer[index] != (byte) '+' && buffer[index] != (byte) '}') {
					int digit = buffer[index] - (byte) '0';
					literalOctets = literalOctets * 10 + digit;
					index++;
				}

				if (index < endIndex) {
					if (buffer[index] == (byte) '+') {
						literalState = ImapLiteralState.Plus;
						textIndex = 0;
					} else {
						literalState = ImapLiteralState.CloseBrace;
						textIndex = 1;
					}

					index++;
				}

				if (index >= endIndex)
					return false;
			}

			if (literalState < ImapLiteralState.Literal) {
				if (SkipText ("}\r\n", buffer, ref index, endIndex))
					literalState = ImapLiteralState.Literal;
			}

			if (index >= endIndex || commandState == ImapAuthCommandState.Error)
				return false;

			if (literalState == ImapLiteralState.Literal) {
				int skip = Math.Min (literalOctets - literalSeen, endIndex - index);

				secrets.Add (new AuthenticationSecret (index, skip));

				literalSeen += skip;
				index += skip;

				if (literalSeen == literalOctets)
					literalState = ImapLiteralState.Complete;
			}

			if (literalState == ImapLiteralState.Complete && index < endIndex && buffer[index] == sentinel) {
				index++;
				return true;
			}

			return false;
		}
		bool SkipLoginToken (List<AuthenticationSecret> secrets, byte[] buffer, ref int index, int endIndex, byte sentinel)
		{
			int startIndex;

			if (tokenType == ImapLoginTokenType.None) {
				switch ((char) buffer[index]) {
				case '{':
					literalState = ImapLiteralState.Octets;
					tokenType = ImapLoginTokenType.Literal;
					index++;
					break;
				case '"':
					tokenType = ImapLoginTokenType.QString;
					index++;
					break;
				default:
					tokenType = ImapLoginTokenType.Atom;
					break;
				}
			}

			switch (tokenType) {
			case ImapLoginTokenType.Literal:
				return SkipLiteralToken (secrets, buffer, ref index, endIndex, sentinel);
			case ImapLoginTokenType.QString:
				if (qstringState != ImapQStringState.Complete) {
					startIndex = index;

					while (index < endIndex) {
						if (qstringState == ImapQStringState.Escaped) {
							qstringState = ImapQStringState.None;
						} else if (buffer[index] == (byte) '\\') {
							qstringState = ImapQStringState.Escaped;
						} else if (buffer[index] == (byte) '"') {
							qstringState = ImapQStringState.EndQuote;
							break;
						}
						index++;
					}

					if (index > startIndex)
						secrets.Add (new AuthenticationSecret (startIndex, index - startIndex));

					if (qstringState == ImapQStringState.EndQuote) {
						qstringState = ImapQStringState.Complete;
						index++;
					}
				}

				if (index >= endIndex)
					return false;

				if (buffer[index] != sentinel) {
					commandState = ImapAuthCommandState.Error;
					return false;
				}

				index++;

				return true;
			default:
				startIndex = index;

				while (index < endIndex && buffer[index] != sentinel)
					index++;

				if (index > startIndex)
					secrets.Add (new AuthenticationSecret (startIndex, index - startIndex));

				if (index >= endIndex)
					return false;
				
				index++;

				return true;
			}
		}