コード例 #1
0
ファイル: processresponse.cs プロジェクト: bacome/imapclient
                private bool ZProcessDataResponse(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZProcessDataResponse));

                    if (!pCursor.SkipBytes(kProcessResponseAsteriskSpace))
                    {
                        return(false);
                    }

                    lContext.TraceVerbose("got data");

                    if (pCursor.SkipBytes(kProcessResponseOKSpace))
                    {
                        lContext.TraceVerbose("got information");
                        mResponseTextProcessor.Process(eResponseTextContext.information, pCursor, mActiveCommands, lContext);
                        return(true);
                    }

                    if (pCursor.SkipBytes(kProcessResponseNoSpace))
                    {
                        lContext.TraceVerbose("got a warning");
                        mResponseTextProcessor.Process(eResponseTextContext.warning, pCursor, mActiveCommands, lContext);
                        return(true);
                    }

                    if (pCursor.SkipBytes(kProcessResponseBadSpace))
                    {
                        lContext.TraceVerbose("got a protocol error");
                        mResponseTextProcessor.Process(eResponseTextContext.protocolerror, pCursor, mActiveCommands, lContext);
                        return(true);
                    }

                    if (pCursor.SkipBytes(kProcessResponseCapabilitySpace))
                    {
                        if (mState == eState.connected)
                        {
                            if (pCursor.ProcessCapability(out var lCapabilities, out var lAuthenticationMechanisms, lContext) && pCursor.Position.AtEnd)
                            {
                                lContext.TraceVerbose("got capabilities: {0} {1}", lCapabilities, lAuthenticationMechanisms);
                                mCapabilities             = lCapabilities;
                                mAuthenticationMechanisms = lAuthenticationMechanisms;
                            }
                            else
                            {
                                lContext.TraceWarning("likely malformed capability");
                            }
                        }
                        else
                        {
                            lContext.TraceWarning("capability response received at the wrong time - not processed");
                        }

                        return(true);
                    }
コード例 #2
0
                public override eProcessDataResult ProcessData(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cNamespaceDataProcessor), nameof(ProcessData));

                    if (!pCursor.SkipBytes(kNamespaceSpace))
                    {
                        return(eProcessDataResult.notprocessed);
                    }

                    if (ZProcessData(pCursor, out var lPersonal, lContext) &&
                        pCursor.SkipByte(cASCII.SPACE) &&
                        ZProcessData(pCursor, out var lOtherUsers, lContext) &&
                        pCursor.SkipByte(cASCII.SPACE) &&
                        ZProcessData(pCursor, out var lShared, lContext) &&
                        pCursor.Position.AtEnd
                        )
                    {
                        lContext.TraceVerbose("got namespaces");
                        NamespaceNames = new cNamespaceNames(lPersonal, lOtherUsers, lShared);
                        mSynchroniser.InvokePropertyChanged(nameof(cIMAPClient.Namespaces), lContext);
                        return(eProcessDataResult.processed);
                    }

                    lContext.TraceWarning("likely malformed namespace");
                    return(eProcessDataResult.notprocessed);
                }
コード例 #3
0
ファイル: lsub.cs プロジェクト: bacome/imapclient
                public bool Process(cBytesCursor pCursor, out cResponseData rResponseData, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cResponseDataParserLSub), nameof(Process));

                    if (!pCursor.SkipBytes(kLSubSpace))
                    {
                        rResponseData = null; return(false);
                    }

                    if (!pCursor.GetFlags(out var lFlags) ||
                        !pCursor.SkipByte(cASCII.SPACE) ||
                        !pCursor.GetMailboxDelimiter(out var lDelimiter) ||
                        !pCursor.SkipByte(cASCII.SPACE) ||
                        !pCursor.GetAString(out IList <byte> lEncodedMailboxPath) ||
                        !pCursor.Position.AtEnd ||
                        !cMailboxName.TryConstruct(lEncodedMailboxPath, lDelimiter, mUTF8Enabled, out var lMailboxName))
                    {
                        lContext.TraceWarning("likely malformed lsub response");
                        rResponseData = null;
                        return(true);
                    }

                    rResponseData = new cResponseDataLSub(lMailboxName, !lFlags.Contains(@"\Noselect", StringComparer.InvariantCultureIgnoreCase));
                    return(true);
                }
コード例 #4
0
                private static bool ZGetId(cBytesCursor pCursor, out cId rServerId, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cIdDataProcessor), nameof(ZGetId));

                    if (pCursor.SkipBytes(cBytesCursor.Nil))
                    {
                        rServerId = null; return(true);
                    }

                    if (!pCursor.SkipByte(cASCII.LPAREN))
                    {
                        rServerId = null; return(false);
                    }

                    Dictionary <string, string> lDictionary = new Dictionary <string, string>();

                    try
                    {
                        bool lFirst = true;

                        while (true)
                        {
                            if (pCursor.SkipByte(cASCII.RPAREN))
                            {
                                break;
                            }

                            if (lFirst)
                            {
                                lFirst = false;
                            }
                            else if (!pCursor.SkipByte(cASCII.SPACE))
                            {
                                rServerId = null; return(false);
                            }

                            if (!pCursor.GetString(out string lField) || !pCursor.SkipByte(cASCII.SPACE))
                            {
                                rServerId = null; return(false);
                            }
                            if (!pCursor.GetNString(out string lValue))
                            {
                                rServerId = null; return(false);
                            }

                            lDictionary[lField] = lValue;
                        }

                        rServerId = new cId(lDictionary);
                        return(true);
                    }
                    catch (Exception e)
                    {
                        lContext.TraceException("error when constructing the id dictionary", e);
                        rServerId = null;
                        return(false);
                    }
                }
コード例 #5
0
ファイル: idle.cs プロジェクト: bacome/imapclient
                private async Task <eIdleProcessResponsesTerminatedBy> ZIdleProcessResponsesAsync(bool pMonitorBackgroundReleaser, Task pCountdownTask, cCommandTag pTag, bool pExpectContinueRequest, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZIdleProcessResponsesAsync), pMonitorBackgroundReleaser, pTag, pExpectContinueRequest);

                    Task lBackgroundReleaserTask;

                    if (pMonitorBackgroundReleaser)
                    {
                        lBackgroundReleaserTask = mBackgroundReleaser.GetAwaitReleaseTask(lContext);
                    }
                    else
                    {
                        lBackgroundReleaserTask = null;
                    }

                    while (true)
                    {
                        Task lBuildResponseTask = mConnection.GetBuildResponseTask(lContext);

                        Task lTask = await mBackgroundAwaiter.AwaitAny(lBuildResponseTask, lBackgroundReleaserTask, pCountdownTask).ConfigureAwait(false);

                        if (ReferenceEquals(lTask, lBackgroundReleaserTask))
                        {
                            return(eIdleProcessResponsesTerminatedBy.backgroundreleaser);
                        }
                        if (ReferenceEquals(lTask, pCountdownTask))
                        {
                            return(eIdleProcessResponsesTerminatedBy.countdowntask);
                        }

                        var lResponse = mConnection.GetResponse(lContext);
                        mSynchroniser.InvokeNetworkReceive(lResponse, lContext);
                        var lCursor = new cBytesCursor(lResponse);

                        if (lCursor.SkipBytes(kPlusSpace))
                        {
                            if (!pExpectContinueRequest)
                            {
                                throw new cUnexpectedServerActionException(fCapabilities.idle, "unexpected continuation request", lContext);
                            }
                            mResponseTextProcessor.Process(eResponseTextContext.continuerequest, lCursor, null, lContext);
                            return(eIdleProcessResponsesTerminatedBy.continuerequest);
                        }

                        if (ZProcessDataResponse(lCursor, lContext))
                        {
                            continue;
                        }

                        if (pTag != null && ZProcessCommandCompletionResponse(lCursor, pTag, false, null, lContext) != null)
                        {
                            return(eIdleProcessResponsesTerminatedBy.commandcompletion);
                        }

                        lContext.TraceError("unrecognised response: {0}", lResponse);
                    }
                }
コード例 #6
0
ファイル: backgroundtask.cs プロジェクト: bacome/imapclient
                private async Task ZBackgroundTaskProcessResponseAsync(cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZBackgroundTaskProcessResponseAsync));

                    var lResponse = mConnection.GetResponse(lContext);

                    mSynchroniser.InvokeNetworkReceive(lResponse, lContext);
                    var lCursor = new cBytesCursor(lResponse);

                    if (lCursor.SkipBytes(kPlusSpace))
                    {
                        var lCurrentCommand = mCurrentCommand;

                        if (lCurrentCommand == null || !lCurrentCommand.WaitingForContinuationRequest)
                        {
                            throw new cUnexpectedServerActionException(0, "unexpected continuation request", lContext);
                        }

                        if (lCurrentCommand.IsAuthentication)
                        {
                            await ZProcessChallengeAsync(lCursor, lContext).ConfigureAwait(false);
                        }
                        else
                        {
                            mResponseTextProcessor.Process(eResponseTextContext.continuerequest, lCursor, lCurrentCommand.Hook, lContext);
                            lCurrentCommand.WaitingForContinuationRequest = false;
                        }

                        return;
                    }

                    lock (mPipelineLock)
                    {
                        if (ZProcessDataResponse(lCursor, lContext))
                        {
                            return;
                        }

                        if (ZBackgroundTaskProcessActiveCommandCompletion(lCursor, lContext))
                        {
                            return;
                        }

                        if (mCurrentCommand != null && ZBackgroundTaskProcessCommandCompletion(lCursor, mCurrentCommand, lContext))
                        {
                            if (mCurrentCommand.IsAuthentication)
                            {
                                mCurrentCommand = null;
                            }
                            return;
                        }
                    }

                    lContext.TraceError("unrecognised response: {0}", lResponse);
                }
コード例 #7
0
ファイル: headerfields.cs プロジェクト: bacome/imapclient
        internal static bool TryConstruct(IList <byte> pValue, out cHeaderFieldImportance rImportance)
        {
            if (pValue == null)
            {
                rImportance = null; return(false);
            }

            eImportance lImportance;

            cBytesCursor lCursor = new cBytesCursor(pValue);

            lCursor.SkipRFC822CFWS();

            if (lCursor.SkipBytes(kLow))
            {
                lImportance = eImportance.low;
            }
            else if (lCursor.SkipBytes(kNormal))
            {
                lImportance = eImportance.normal;
            }
            else if (lCursor.SkipBytes(kHigh))
            {
                lImportance = eImportance.high;
            }
            else
            {
                rImportance = null; return(false);
            }

            lCursor.SkipRFC822CFWS();

            if (lCursor.Position.AtEnd)
            {
                rImportance = new cHeaderFieldImportance(new cBytes(pValue), lImportance);
                return(true);
            }

            rImportance = null;
            return(false);
        }
コード例 #8
0
ファイル: processing.cs プロジェクト: bacome/imapclient
                public eProcessDataResult ProcessData(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(ProcessData));

                    if (mSelectedMailbox != null)
                    {
                        var lBookmark = pCursor.Position;
                        var lResult   = mSelectedMailbox.ProcessData(pCursor, lContext);
                        if (lResult != eProcessDataResult.notprocessed)
                        {
                            return(lResult);
                        }
                        pCursor.Position = lBookmark;
                    }

                    if (pCursor.SkipBytes(kStatusSpace))
                    {
                        if (!pCursor.GetAString(out string lEncodedMailboxPath) ||
                            !pCursor.SkipBytes(cBytesCursor.SpaceLParen) ||
                            !ZProcessDataStatusAttributes(pCursor, out var lStatus, lContext) ||
                            !pCursor.SkipByte(cASCII.RPAREN) ||
                            !pCursor.Position.AtEnd)
                        {
                            lContext.TraceWarning("likely malformed status response");
                            return(eProcessDataResult.notprocessed);
                        }

                        var lItem = ZItem(lEncodedMailboxPath);
                        lItem.UpdateStatus(lStatus, lContext);
                        if (!ReferenceEquals(mSelectedMailbox?.MailboxHandle, lItem))
                        {
                            lItem.UpdateMailboxStatus(lContext);
                        }

                        return(eProcessDataResult.processed);
                    }

                    return(eProcessDataResult.notprocessed);
                }
コード例 #9
0
ファイル: processing.cs プロジェクト: bacome/imapclient
                public eProcessDataResult ProcessData(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cSelectedMailboxCache), nameof(ProcessData));

                    if (pCursor.GetNZNumber(out _, out var lNumber) && pCursor.SkipBytes(kSpaceExpunge) && pCursor.Position.AtEnd)
                    {
                        lContext.TraceVerbose("got expunge: {0}", lNumber);
                        ZExpunge((int)lNumber, lContext);
                        return(eProcessDataResult.processed);
                    }

                    return(eProcessDataResult.notprocessed);
                }
コード例 #10
0
                public override eProcessDataResult ProcessData(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cEnableCommandHook), nameof(ProcessData));

                    if (!pCursor.SkipBytes(kEnabled))
                    {
                        return(eProcessDataResult.notprocessed);
                    }

                    fEnableableExtensions lEnabledExtensions = fEnableableExtensions.none;

                    while (true)
                    {
                        if (!pCursor.SkipByte(cASCII.SPACE))
                        {
                            break;
                        }

                        if (!pCursor.GetToken(cCharset.Atom, null, null, out cByteList lAtom))
                        {
                            lContext.TraceWarning("likely malformed enabled: not an atom list?");
                            return(eProcessDataResult.notprocessed);
                        }

                        lContext.TraceVerbose("got an enabled for {0}", lAtom);

                        if (cASCII.Compare(lAtom, kEnableExtensionUTF8, false))
                        {
                            lEnabledExtensions = lEnabledExtensions | fEnableableExtensions.utf8;
                        }
                        // more here as required
                        else
                        {
                            lContext.TraceError("unknown extension enabled: {0}", lAtom);
                        }
                    }

                    if (!pCursor.Position.AtEnd)
                    {
                        lContext.TraceWarning("likely malformed enabled: not at end?");
                        return(eProcessDataResult.notprocessed);
                    }

                    mEnabledExtensions |= lEnabledExtensions;
                    return(eProcessDataResult.processed);
                }
コード例 #11
0
                private bool ZProcessData(cBytesCursor pCursor, out List <cNamespaceName> rNames, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cNamespaceDataProcessor), nameof(ZProcessData));

                    if (pCursor.SkipBytes(cBytesCursor.Nil))
                    {
                        rNames = null;
                        return(true);
                    }

                    if (!pCursor.SkipByte(cASCII.LPAREN))
                    {
                        rNames = null; return(false);
                    }

                    rNames = new List <cNamespaceName>();

                    while (true)
                    {
                        if (!pCursor.SkipByte(cASCII.LPAREN) ||
                            !pCursor.GetString(out IList <byte> lEncodedPrefix) ||
                            !pCursor.SkipByte(cASCII.SPACE) ||
                            !pCursor.GetMailboxDelimiter(out var lDelimiter) ||
                            !ZProcessNamespaceExtension(pCursor) ||
                            !pCursor.SkipByte(cASCII.RPAREN)
                            )
                        {
                            rNames = null;
                            return(false);
                        }

                        if (!cNamespaceName.TryConstruct(lEncodedPrefix, lDelimiter, mUTF8Enabled, out var lNamespaceName))
                        {
                            rNames = null;
                            return(false);
                        }

                        rNames.Add(lNamespaceName);

                        if (pCursor.SkipByte(cASCII.RPAREN))
                        {
                            return(true);
                        }
                    }
                }
コード例 #12
0
ファイル: select_data.cs プロジェクト: bacome/imapclient
                public bool Process(cBytesCursor pCursor, out cResponseData rResponseData, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cResponseDataParserSelect), nameof(Process));

                    if (pCursor.SkipBytes(kFlagsSpace))
                    {
                        if (pCursor.GetFlags(out var lRawFlags) && pCursor.Position.AtEnd && cFetchableFlags.TryConstruct(lRawFlags, out var lFlags))
                        {
                            rResponseData = new cResponseDataFlags(lFlags);
                        }
                        else
                        {
                            lContext.TraceWarning("likely malformed flags response");
                            rResponseData = null;
                        }

                        return(true);
                    }
コード例 #13
0
                public override eProcessDataResult ProcessData(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandHookBaseSearch), nameof(ProcessData));

                    if (!pCursor.SkipBytes(kSearch))
                    {
                        return(eProcessDataResult.notprocessed);
                    }

                    cUIntList lMSNs = new cUIntList();

                    while (true)
                    {
                        if (!pCursor.SkipByte(cASCII.SPACE))
                        {
                            break;
                        }

                        if (!pCursor.GetNZNumber(out _, out var lMSN))
                        {
                            lContext.TraceWarning("likely malformed search: not an nz-number list?");
                            return(eProcessDataResult.notprocessed);
                        }

                        lMSNs.Add(lMSN);
                    }

                    if (!pCursor.Position.AtEnd)
                    {
                        lContext.TraceWarning("likely malformed search: not at end?");
                        return(eProcessDataResult.notprocessed);
                    }

                    if (mMSNs == null)
                    {
                        mMSNs = lMSNs;
                    }
                    else
                    {
                        mMSNs.AddRange(lMSNs);
                    }

                    return(eProcessDataResult.processed);
                }
コード例 #14
0
                public override eProcessDataResult ProcessData(cBytesCursor pCursor, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cIdDataProcessor), nameof(ProcessData));

                    if (pCursor.SkipBytes(kIdSpace))
                    {
                        if (ZGetId(pCursor, out var lServerId, lContext) && pCursor.Position.AtEnd)
                        {
                            lContext.TraceVerbose("got id: {0}", lServerId);
                            mServerId = lServerId;
                            mSynchroniser.InvokePropertyChanged(nameof(cIMAPClient.ServerId), lContext);
                            return(eProcessDataResult.processed);
                        }

                        lContext.TraceWarning("likely malformed id response");
                    }

                    return(eProcessDataResult.notprocessed);
                }
コード例 #15
0
ファイル: processing.cs プロジェクト: bacome/imapclient
                private static eProcessStatusAttributeResult ZProcessDataStatusAttribute(cBytesCursor pCursor, cBytes pAttributeSpace, ref ulong?rNumber, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(ZProcessDataStatusAttribute));

                    if (!pCursor.SkipBytes(pAttributeSpace))
                    {
                        return(eProcessStatusAttributeResult.notprocessed);
                    }

                    if (pCursor.GetNumber(out var lNumber))
                    {
                        lContext.TraceVerbose("got {0}", lNumber);
                        rNumber = lNumber;
                        return(eProcessStatusAttributeResult.processed);
                    }

                    lContext.TraceWarning("likely malformed status-att-list-item: no number?");
                    return(eProcessStatusAttributeResult.error);
                }
コード例 #16
0
ファイル: initialisation.cs プロジェクト: bacome/imapclient
                public async Task <sGreeting> ConnectAsync(cMethodControl pMC, cServer pServer, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ConnectAsync), pMC, pServer);

                    if (mDisposed)
                    {
                        throw new ObjectDisposedException(nameof(cCommandPipeline));
                    }

                    if (mState != eState.notconnected)
                    {
                        throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnconnected);
                    }
                    mState = eState.connecting;

                    try
                    {
                        await mConnection.ConnectAsync(pMC, pServer, lContext).ConfigureAwait(false);

                        using (var lAwaiter = new cAwaiter(pMC))
                        {
                            while (true)
                            {
                                lContext.TraceVerbose("waiting");
                                await lAwaiter.AwaitAny(mConnection.GetBuildResponseTask(lContext)).ConfigureAwait(false);

                                var lResponse = mConnection.GetResponse(lContext);
                                mSynchroniser.InvokeNetworkReceive(lResponse, lContext);
                                var lCursor = new cBytesCursor(lResponse);

                                if (lCursor.SkipBytes(kGreetingAsteriskSpaceOKSpace))
                                {
                                    var lHook = new cCommandHookInitial();

                                    cResponseText lResponseText = mResponseTextProcessor.Process(eResponseTextContext.greetingok, lCursor, lHook, lContext);
                                    lContext.TraceVerbose("got ok: {0}", lResponseText);

                                    mState          = eState.connected;
                                    mBackgroundTask = ZBackgroundTaskAsync(lContext);

                                    mCapabilities             = lHook.Capabilities;
                                    mAuthenticationMechanisms = lHook.AuthenticationMechanisms;

                                    return(new sGreeting(eGreetingType.ok, null));
                                }

                                if (lCursor.SkipBytes(kGreetingAsteriskSpacePreAuthSpace))
                                {
                                    var lHook = new cCommandHookInitial();

                                    cResponseText lResponseText = mResponseTextProcessor.Process(eResponseTextContext.greetingpreauth, lCursor, lHook, lContext);
                                    lContext.TraceVerbose("got preauth: {0}", lResponseText);

                                    mState          = eState.connected;
                                    mBackgroundTask = ZBackgroundTaskAsync(lContext);

                                    mCapabilities             = lHook.Capabilities;
                                    mAuthenticationMechanisms = lHook.AuthenticationMechanisms;

                                    return(new sGreeting(eGreetingType.preauth, lResponseText));
                                }

                                if (lCursor.SkipBytes(kGreetingAsteriskSpaceBYESpace))
                                {
                                    cResponseText lResponseText = mResponseTextProcessor.Process(eResponseTextContext.greetingbye, lCursor, null, lContext);
                                    lContext.TraceError("got bye: {0}", lResponseText);

                                    mConnection.Disconnect(lContext);

                                    mState = eState.stopped;
                                    return(new sGreeting(eGreetingType.bye, lResponseText));
                                }

                                lContext.TraceError("unrecognised response: {0}", lResponse);
                            }
                        }
                    }
                    catch (Exception)
                    {
                        mConnection.Disconnect(lContext);
                        mState = eState.stopped;
                        throw;
                    }
                }
コード例 #17
0
ファイル: headerfields.cs プロジェクト: bacome/imapclient
        private static bool ZTryConstruct(cHeaderFieldNames pNames, bool pNot, IList <byte> pBytes, out cHeaderFields rFields)
        {
            if (pBytes == null)
            {
                rFields = null; return(false);
            }

            cBytesCursor        lCursor = new cBytesCursor(pBytes);
            List <cHeaderField> lFields = new List <cHeaderField>();

            while (true)
            {
                if (!lCursor.GetRFC822FieldName(out var lName))
                {
                    break;
                }
                lCursor.SkipRFC822WSP();
                if (!lCursor.SkipByte(cASCII.COLON))
                {
                    rFields = null; return(false);
                }
                if (!lCursor.GetRFC822FieldValue(out var lValue))
                {
                    rFields = null; return(false);
                }

                if (lName.Equals(kHeaderFieldName.References, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (cHeaderFieldMsgIds.TryConstruct(lName, lValue, out var lReferences))
                    {
                        lFields.Add(lReferences);
                    }
                    else
                    {
                        lFields.Add(new cHeaderField(lName, new cBytes(lValue)));
                    }
                }
                else if (lName.Equals(kHeaderFieldName.Importance, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (cHeaderFieldImportance.TryConstruct(lValue, out var lImportance))
                    {
                        lFields.Add(lImportance);
                    }
                    else
                    {
                        lFields.Add(new cHeaderField(lName, new cBytes(lValue)));
                    }
                }
                else
                {
                    lFields.Add(new cHeaderField(lName, new cBytes(lValue)));
                }
            }

            if (!lCursor.Position.AtEnd && !lCursor.SkipBytes(cBytesCursor.CRLF))
            {
                rFields = null; return(false);
            }

            rFields = new cHeaderFields(pNames, pNot, lFields);
            return(true);
        }
コード例 #18
0
ファイル: tests.cs プロジェクト: bacome/imapclient
        public static void _Tests_RFC822(cTrace.cContext pParentContext)
        {
            cBytesCursor lCursor;
            string       lString;
            DateTime     lDate;
            cByteList    lByteList;


            // tests for WSP

            lCursor = new cBytesCursor("x \t y \t\r\n\tz");
            if (!lCursor.SkipByte(cASCII.x) || !lCursor.SkipRFC822WSP() || lCursor.SkipRFC822WSP() || !lCursor.SkipByte(cASCII.y) || !lCursor.SkipRFC822FWS() || lCursor.SkipRFC822FWS() || !lCursor.SkipByte(cASCII.z))
            {
                throw new cTestsException("skip wsp 1");
            }
            lCursor = new cBytesCursor("x \t y \t\r\n\tz");
            if (!lCursor.SkipByte(cASCII.x) || !lCursor.SkipRFC822FWS() || lCursor.SkipRFC822FWS() || !lCursor.SkipByte(cASCII.y) || !lCursor.SkipRFC822FWS() || !lCursor.SkipByte(cASCII.z))
            {
                throw new cTestsException("skip wsp 2");
            }
            lCursor = new cBytesCursor("x \t\r\ny \t\r\n\t\r\n z");
            if (!lCursor.SkipByte(cASCII.x) || !lCursor.SkipRFC822FWS() || lCursor.SkipRFC822FWS() || !lCursor.SkipBytes(new cBytes("\r\ny")) || !lCursor.SkipRFC822FWS() || !lCursor.SkipByte(cASCII.z))
            {
                throw new cTestsException("skip wsp 3");
            }

            lCursor = new cBytesCursor("Muhammed.(I am  the greatest) Ali\r\n @(the)Vegas.WBA");
            if (!lCursor.GetToken(cCharset.Atom, null, null, out lString) || lString != "Muhammed." || !lCursor.SkipRFC822CFWS() || !lCursor.GetToken(cCharset.Atom, null, null, out lString) || lString != "Ali" || !lCursor.SkipRFC822CFWS() || !lCursor.SkipByte(cASCII.AT) || !lCursor.SkipRFC822CFWS() || !lCursor.GetToken(cCharset.Atom, null, null, out lString) || lString != "Vegas.WBA")
            {
                throw new cTestsException("skip cfws 1");
            }
            lCursor = new cBytesCursor("(I am \r\n the(xx\\)\\\\\\() gre \t() \tatest)");
            if (!lCursor.SkipRFC822CFWS() || !lCursor.Position.AtEnd)
            {
                throw new cTestsException("skip cfws 2");
            }

            // TODO: more tests for failure cases



            // tests for IMF date (these examples from rfc 5322)

            lCursor = new cBytesCursor("Fri, 21 Nov 1997 09:55:06 -0600  x  Tue, 1 Jul 2003 10:52:37 +0200    x    Thu, 13 Feb 1969 23:32:54 -0330    x  Thu,\r\n\t13\r\n\t  Feb\r\n\t    1969\r\n\t23:32\r\n\t\t\t-0330 (Newfoundland Time)   x   21 Nov 97 09:55:06 GMT    x     Fri, 21 Nov 1997 09(comment):   55  :  06 -0600    x");

            if (!lCursor.GetRFC822DateTime(out lDate) || lDate != new DateTime(1997, 11, 21, 15, 55, 06) || !lCursor.SkipByte(cASCII.x))
            {
                throw new cTestsException("imf date 1");
            }
            if (!lCursor.GetRFC822DateTime(out lDate) || lDate != new DateTime(2003, 7, 1, 8, 52, 37) || !lCursor.SkipByte(cASCII.x))
            {
                throw new cTestsException("imf date 2");
            }
            if (!lCursor.GetRFC822DateTime(out lDate) || lDate != new DateTime(1969, 2, 14, 3, 02, 54) || !lCursor.SkipByte(cASCII.x))
            {
                throw new cTestsException("imf date 3");
            }
            if (!lCursor.GetRFC822DateTime(out lDate) || lDate != new DateTime(1969, 2, 14, 3, 02, 00) || !lCursor.SkipByte(cASCII.x))
            {
                throw new cTestsException("imf date 4");
            }
            if (!lCursor.GetRFC822DateTime(out lDate) || lDate != new DateTime(1997, 11, 21, 9, 55, 06) || !lCursor.SkipByte(cASCII.x))
            {
                throw new cTestsException("imf date 5");
            }
            if (!lCursor.GetRFC822DateTime(out lDate) || lDate != new DateTime(1997, 11, 21, 15, 55, 06) || !lCursor.SkipByte(cASCII.x))
            {
                throw new cTestsException("imf date 6");
            }

            // TODO: more tests for failure cases and alphanumeric zones
            //   Wed, 17 Jul 1996 02:23:25 -0700 (PDT)



            // header values
            lCursor = new cBytesCursor("   \t  \r\nHeader    \t:      \r\n\t       \t\r\n\r\n");

            if (lCursor.GetRFC822FieldName(out lString) || !lCursor.GetRFC822FieldValue(out lByteList) || cTools.UTF8BytesToString(lByteList) != "   \t  ")
            {
                throw new cTestsException("header 1.1");
            }
            if (!lCursor.GetRFC822FieldName(out lString) || lString != "Header" || !lCursor.SkipRFC822WSP() || !lCursor.SkipByte(cASCII.COLON) || !lCursor.GetRFC822FieldValue(out lByteList) || cTools.UTF8BytesToString(lByteList) != "      \t       \t")
            {
                throw new cTestsException("header 1.2");
            }

            lCursor = new cBytesCursor("Header  \t  :      \r\n        \t\r\nFred");
            if (!lCursor.GetRFC822FieldName(out lString) || lString != "Header" || !lCursor.SkipRFC822WSP() || !lCursor.SkipByte(cASCII.COLON) || !lCursor.GetRFC822FieldValue(out lByteList) || cTools.UTF8BytesToString(lByteList) != "              \t")
            {
                throw new cTestsException("header 2.1");
            }

            lCursor = new cBytesCursor("Header:\r\n  this  is  \r\n   the\tvalue     \t\r\n");
            if (!lCursor.GetRFC822FieldName(out lString) || lString != "Header" || lCursor.SkipRFC822WSP() || !lCursor.SkipByte(cASCII.COLON) || !lCursor.GetRFC822FieldValue(out lByteList) || cTools.UTF8BytesToString(lByteList) != "  this  is     the\tvalue     \t")
            {
                throw new cTestsException("header 3.1");
            }

            lCursor = new cBytesCursor("Header:\r\n   should   \r\n    fail    \t\r\n more stuff");
            if (!lCursor.GetRFC822FieldName(out lString) || lString != "Header" || lCursor.SkipRFC822WSP() || !lCursor.SkipByte(cASCII.COLON) || lCursor.GetRFC822FieldValue(out lByteList))
            {
                throw new cTestsException("header 4.1");
            }


            // atoms
            lCursor = new cBytesCursor("   \t  \r\n Header    \tAtom(comment)      \r\nAt?Om\tAt!om:{Atom}       \t\r\n\r\n");

            if (!lCursor.GetRFC822Atom(out lString) || lString != "Header" || !lCursor.GetRFC822Atom(out lString) || lString != "Atom")
            {
                throw new cTestsException("atom 1.1");
            }
            if (!lCursor.SkipByte(cASCII.CR) || !lCursor.SkipByte(cASCII.LF))
            {
                throw new cTestsException("atom 1.2");
            }
            if (!lCursor.GetRFC822Atom(out lString) || lString != "At?Om")
            {
                throw new cTestsException("atom 1.3");
            }
            if (!lCursor.GetRFC822Atom(out lString) || lString != "At!om")
            {
                throw new cTestsException("atom 1.4");
            }
            if (lCursor.GetRFC822Atom(out lString))
            {
                throw new cTestsException("atom 1.5.1");
            }
            if (!lCursor.SkipByte(cASCII.COLON))
            {
                throw new cTestsException("atom 1.5.2");
            }
            if (!lCursor.GetRFC822Atom(out lString) || lString != "{Atom}")
            {
                throw new cTestsException("atom 1.6");
            }
            if (!lCursor.SkipByte(cASCII.CR) || !lCursor.SkipByte(cASCII.LF) || !lCursor.SkipByte(cASCII.CR) || !lCursor.SkipByte(cASCII.LF) || !lCursor.Position.AtEnd)
            {
                throw new cTestsException("atom 1.7");
            }

            // quoted strings
            lCursor = new cBytesCursor("   \t  \r\n \"Header\r\n with FWS\"    \t\"Atom(not a \\\"comment\\\")\"      \r\n\"At?Om\"\t\"At!om:{Atom}\"    \"\r\n\tFWS beginning and end\r\n\t\"   \t\r\n\r\n");

            if (!lCursor.GetRFC822QuotedString(out lString) || lString != "Header with FWS" || !lCursor.GetRFC822QuotedString(out lString) || lString != "Atom(not a \"comment\")")
            {
                throw new cTestsException("quoted string 1.1");
            }
            if (!lCursor.SkipByte(cASCII.CR) || !lCursor.SkipByte(cASCII.LF))
            {
                throw new cTestsException("quoted string 1.2");
            }
            if (!lCursor.GetRFC822QuotedString(out lString) || lString != "At?Om")
            {
                throw new cTestsException("quoted string 1.3");
            }
            if (!lCursor.GetRFC822QuotedString(out lString) || lString != "At!om:{Atom}")
            {
                throw new cTestsException("quoted string 1.4");
            }
            if (!lCursor.GetRFC822QuotedString(out lString) || lString != "\tFWS beginning and end\t")
            {
                throw new cTestsException("quoted string 1.5");
            }
            if (lCursor.GetRFC822QuotedString(out lString))
            {
                throw new cTestsException("quoted string 1.6.1");
            }
            if (!lCursor.SkipByte(cASCII.CR) || !lCursor.SkipByte(cASCII.LF) || !lCursor.SkipByte(cASCII.CR) || !lCursor.SkipByte(cASCII.LF) || !lCursor.Position.AtEnd)
            {
                throw new cTestsException("quoted string 1.6.2");
            }

            // mix
            lCursor = new cBytesCursor("   \t  \r\n Header    \tA");
            if (lCursor.GetRFC822QuotedString(out lString) || lCursor.Position.Byte != 0 || !lCursor.GetRFC822Atom(out lString) || lString != "Header" || !lCursor.SkipByte(cASCII.A))
            {
                throw new cTestsException("mix 1.1");
            }
            lCursor = new cBytesCursor("   \t  \r\n \"Header\"    \tA");
            if (lCursor.GetRFC822Atom(out lString) || lCursor.Position.Byte != 0 || !lCursor.GetRFC822QuotedString(out lString) || lString != "Header" || !lCursor.SkipByte(cASCII.A))
            {
                throw new cTestsException("mix 1.2");
            }

            // domain literal
            lCursor = new cBytesCursor("   \t (there is a domain\r\n literal coming up(and\tit'll\r\n\tbe a good one))  \r\n [Header]      \r\n ( now with with FWS ) [  \t  \r\n\t the.name.com  \r\n     ]    (now with embedded FWS)  [  \t  \r\n\t the \t   name   \r\n   com  \r\n     ]   (with quotes and utf8)    [     \\[   fr€d     ]     (something invalid)     [    [   ]   \r\n");

            if (!lCursor.GetDomainLiteral(out lString) || lString != "[Header]")
            {
                throw new cTestsException("domain literal 1.1");
            }
            if (!lCursor.GetDomainLiteral(out lString) || lString != "[the.name.com]")
            {
                throw new cTestsException("domain literal 1.2");
            }
            if (!lCursor.GetDomainLiteral(out lString) || lString != "[the name com]")
            {
                throw new cTestsException("domain literal 1.3");
            }
            if (!lCursor.GetDomainLiteral(out lString) || lString != "[[ fr€d]")
            {
                throw new cTestsException("domain literal 1.4");
            }
            if (lCursor.GetDomainLiteral(out lString))
            {
                throw new cTestsException("domain literal 1.5");
            }
            if (!lCursor.GetRFC822FieldValue(out lByteList) || cTools.UTF8BytesToString(lByteList) != "[    [   ]   ")
            {
                throw new cTestsException("domain literal 1.6");
            }

            // domain
            lCursor = new cBytesCursor("    \t   (first a dot-atom form)   fred.angus.bart   (now a obs form)    frxd  \t   .       angxs     .   \t  bxrt      (now a\r\n literal)     [    192.168.1.1     ]       \r\nNextHeader");

            if (!lCursor.GetRFC822Domain(out lString) || lString != "fred.angus.bart")
            {
                throw new cTestsException("domain 1.1");
            }
            if (!lCursor.GetRFC822Domain(out lString) || lString != "frxd.angxs.bxrt")
            {
                throw new cTestsException("domain 1.2");
            }
            if (!lCursor.GetRFC822Domain(out lString) || lString != "[192.168.1.1]")
            {
                throw new cTestsException("domain 1.3");
            }
            if (!lCursor.GetRFC822FieldValue(out lByteList) || lByteList.Count != 0)
            {
                throw new cTestsException("domain 1.4");
            }
            if (lCursor.GetRestAsString() != "NextHeader")
            {
                throw new cTestsException("domain 1.5");
            }

            // local part
            lCursor = new cBytesCursor("    \t   (first a dot-atom form)   fred.angus.bart   (now a obs form)    frxd  \t   .       angxs     .   \t  bxrt      (now a\r\n quoted string)     \"th€ local part as a string\"       (then a second obsolete form)     \"fr€d\"  \t   .       angxs     .   \t  \"bzrt\"        \r\n ");

            if (!lCursor.GetRFC822LocalPart(out lString) || lString != "fred.angus.bart")
            {
                throw new cTestsException("local part 1.1");
            }
            if (!lCursor.GetRFC822LocalPart(out lString) || lString != "frxd.angxs.bxrt")
            {
                throw new cTestsException("local part 1.2");
            }
            if (!lCursor.GetRFC822LocalPart(out lString) || lString != "th€ local part as a string")
            {
                throw new cTestsException("local part 1.3");
            }
            if (!lCursor.GetRFC822LocalPart(out lString) || lString != "fr€d.angxs.bzrt")
            {
                throw new cTestsException("local part 1.4");
            }
            if (!lCursor.Position.AtEnd)
            {
                throw new cTestsException("local part 1.5");
            }

            lCursor = new cBytesCursor("    \t   (edge case)   fred.angus.bart    .    []         \r\nNextHeader");
            if (!lCursor.GetRFC822LocalPart(out lString) || lString != "fred.angus.bart")
            {
                throw new cTestsException("local part 2.1");
            }
            if (!lCursor.GetRFC822FieldValue(out lByteList) || cTools.UTF8BytesToString(lByteList) != ".    []         ")
            {
                throw new cTestsException("local part 2.2");
            }

            // message id
            lCursor = new cBytesCursor("     \r\n\t   (one)  <*****@*****.**>      <*****@*****.**>    <*****@*****.**>     <1234   @   local(blah)  .machine .example>    ");

            if (!lCursor.GetRFC822MsgId(out lString) || lString != "*****@*****.**")
            {
                throw new cTestsException("msgid 1.1");
            }
            if (!lCursor.GetRFC822MsgId(out lString) || lString != "*****@*****.**")
            {
                throw new cTestsException("msgid 1.2");
            }
            if (!lCursor.GetRFC822MsgId(out lString) || lString != "*****@*****.**")
            {
                throw new cTestsException("msgid 1.3");
            }
            if (!lCursor.GetRFC822MsgId(out lString) || lString != "*****@*****.**")
            {
                throw new cTestsException("msgid 1.4");
            }
        }
コード例 #19
0
ファイル: esearch.cs プロジェクト: bacome/imapclient
                public bool Process(cBytesCursor pCursor, out cResponseData rResponseData, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cResponseDataParserESearch), nameof(Process));

                    if (!pCursor.SkipBytes(kESearch))
                    {
                        rResponseData = null; return(false);
                    }

                    if (pCursor.Position.AtEnd)
                    {
                        rResponseData = new cResponseDataESearch(null, false, null);
                        return(true);
                    }

                    bool lSetParsedAs = false; // just in case there is another response that starts with the string "ESEARCH"

                    IList <byte> lTag;

                    if (pCursor.SkipBytes(kSpaceLParenTAGSpace))
                    {
                        if (!pCursor.GetString(out lTag) || !pCursor.SkipByte(cASCII.RPAREN))
                        {
                            rResponseData = null;
                            return(true);
                        }

                        lSetParsedAs = true;
                    }
                    else
                    {
                        lTag = null;
                    }

                    bool lUID;

                    if (pCursor.SkipBytes(kSpaceUID))
                    {
                        lUID         = true;
                        lSetParsedAs = true;
                    }
                    else
                    {
                        lUID = false;
                    }

                    cSequenceSet lSequenceSet = null;

                    while (true)
                    {
                        if (!pCursor.SkipByte(cASCII.SPACE))
                        {
                            break;
                        }

                        lSetParsedAs = true;

                        if (!pCursor.GetToken(cCharset.Atom, null, null, out cByteList lName) ||
                            !pCursor.SkipByte(cASCII.SPACE) ||
                            !pCursor.ProcessExtendedValue(out var lValue)
                            )
                        {
                            rResponseData = null;
                            return(true);
                        }

                        if (cASCII.Compare(lName, kAll, false) && lValue is cExtendedValue.cSequenceSetEV lSequenceSetEV)
                        {
                            lSequenceSet = lSequenceSetEV.SequenceSet;
                        }
                    }

                    if (!pCursor.Position.AtEnd)
                    {
                        rResponseData = null;
                        return(lSetParsedAs);
                    }

                    rResponseData = new cResponseDataESearch(lTag, lUID, lSequenceSet);
                    return(true);
                }
コード例 #20
0
                public bool Process(cBytesCursor pCursor, out cResponseData rResponseData, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cResponseDataParserList), nameof(Process));

                    if (!pCursor.SkipBytes(kListSpace))
                    {
                        rResponseData = null; return(false);
                    }

                    if (!pCursor.GetFlags(out var lFlags) ||
                        !pCursor.SkipByte(cASCII.SPACE) ||
                        !pCursor.GetMailboxDelimiter(out var lDelimiter) ||
                        !pCursor.SkipByte(cASCII.SPACE) ||
                        !pCursor.GetAString(out IList <byte> lEncodedMailboxPath) ||
                        !ZProcessExtendedItems(pCursor, out var lExtendedItems) ||
                        !pCursor.Position.AtEnd)
                    {
                        lContext.TraceWarning("likely malformed list response");
                        rResponseData = null;
                        return(true);
                    }

                    if (lEncodedMailboxPath.Count == 0)
                    {
                        if (lFlags.Count == 0 && lExtendedItems.Count == 0)
                        {
                            if (lDelimiter == null)
                            {
                                rResponseData = new cResponseDataListDelimiter();
                            }
                            else
                            {
                                rResponseData = new cResponseDataListDelimiter((char)lDelimiter.Value);
                            }
                        }
                        else
                        {
                            lContext.TraceWarning("likely malformed list delimiter response");
                            rResponseData = null;
                        }
                    }
                    else
                    {
                        if (cMailboxName.TryConstruct(lEncodedMailboxPath, lDelimiter, mUTF8Enabled, out var lMailboxName))
                        {
                            fListFlags lListFlags = 0;

                            if (lFlags.Contains(@"\Noinferiors", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.noinferiors | fListFlags.hasnochildren;
                            }
                            if (lFlags.Contains(@"\Noselect", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.noselect;
                            }
                            if (lFlags.Contains(@"\Marked", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.marked;
                            }
                            if (lFlags.Contains(@"\Unmarked", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.unmarked;
                            }

                            if (lFlags.Contains(@"\NonExistent", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.noselect | fListFlags.nonexistent;
                            }
                            if (lFlags.Contains(@"\Subscribed", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.subscribed;
                            }
                            if (lFlags.Contains(@"\Remote", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.remote;
                            }
                            if (lFlags.Contains(@"\HasChildren", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.haschildren;
                            }
                            if (lFlags.Contains(@"\HasNoChildren", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.hasnochildren;
                            }

                            if (lFlags.Contains(@"\All", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.all;
                            }
                            if (lFlags.Contains(@"\Archive", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.archive;
                            }
                            if (lFlags.Contains(@"\Drafts", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.drafts;
                            }
                            if (lFlags.Contains(@"\Flagged", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.flagged;
                            }
                            if (lFlags.Contains(@"\Junk", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.junk;
                            }
                            if (lFlags.Contains(@"\Sent", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.sent;
                            }
                            if (lFlags.Contains(@"\Trash", StringComparer.InvariantCultureIgnoreCase))
                            {
                                lListFlags |= fListFlags.trash;
                            }

                            bool lHasSubscribedChildren = false;

                            foreach (var lItem in lExtendedItems)
                            {
                                if (lItem.Tag.Equals("childinfo", StringComparison.InvariantCultureIgnoreCase) && lItem.Value.Contains("subscribed", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    lHasSubscribedChildren = true;
                                    break;
                                }
                            }

                            rResponseData = new cResponseDataListMailbox(lMailboxName, lListFlags, lHasSubscribedChildren);
                        }
                        else
                        {
                            lContext.TraceWarning("likely malformed list mailbox response");
                            rResponseData = null;
                        }
                    }

                    return(true);
                }