Esempio n. 1
0
            public async Task <iMailboxHandle> RenameAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cMailboxName pMailboxName, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(RenameAsync), pMC, pMailboxHandle, pMailboxName);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pMailboxName == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxName));
                }

                var lItem = mMailboxCache.CheckHandle(pMailboxHandle);

                if (!mCommandPartFactory.TryAsMailbox(pMailboxName.Path, pMailboxName.Delimiter, out var lMailboxCommandPart, out _))
                {
                    throw new ArgumentOutOfRangeException(nameof(pMailboxName));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kRenameCommandPart, lItem.MailboxNameCommandPart, cCommandPart.Space, lMailboxCommandPart);

                    if (pMailboxHandle.MailboxName.IsInbox)
                    {
                        lItem = null;                                     // renaming the inbox has special behaviour
                    }
                    var lHook = new cRenameCommandHook(mMailboxCache, lItem, pMailboxName);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("rename success");
                        return(lHook.MailboxHandle);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 2
0
            public async Task CheckAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CheckAsync), pMC);

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

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    if (_ConnectionState != eConnectionState.selected)
                    {
                        return;
                    }

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.Add(kCheckCommandPart);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("check success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 3
0
            private async Task ZUIDStoreAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, uint pUIDValidity, cStoreFeedbackCollector pFeedbackCollector, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cUIDStoreFeedback pFeedback, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZStoreAsync), pMC, pMailboxHandle, pUIDValidity, pFeedbackCollector, pOperation, pFlags, pIfUnchangedSinceModSeq, pFeedback);

                // no validation ... all the parameters have been validated already by the cSession by the time we get here

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUIDValidity);
                    if (!lSelectedMailbox.SelectedForUpdate)
                    {
                        throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);
                    }

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.AddUIDValidity(pUIDValidity);                                                  // the command is sensitive to UIDValidity changes

                    // build the command
                    lBuilder.Add(kUIDStoreCommandPartUIDStoreSpace, new cTextCommandPart(cSequenceSet.FromUInts(pFeedbackCollector.UInts)), cCommandPart.Space);
                    if (pIfUnchangedSinceModSeq != null)
                    {
                        lBuilder.Add(kStoreCommandPartLParenUnchangedSinceSpace, new cTextCommandPart(pIfUnchangedSinceModSeq.Value), kStoreCommandPartRParenSpace);
                    }
                    lBuilder.Add(pOperation, pFlags);

                    // add the hook
                    var lHook = new cCommandHookStore(pFeedbackCollector, pFeedback, lSelectedMailbox);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    // note: the base spec states that non-existent UIDs are ignored without comment => a NO from a UID STORE is unexpected

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid store success");
                        return;
                    }

                    fCapabilities lTryIgnoring;
                    if (pIfUnchangedSinceModSeq == null)
                    {
                        lTryIgnoring = 0;
                    }
                    else
                    {
                        lTryIgnoring = fCapabilities.condstore;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Esempio n. 4
0
            public async Task NoOpAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(NoOpAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState < eConnectionState.notauthenticated || _ConnectionState > eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kNoOpCommandPart);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceVerbose("noop success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 5
0
            public async Task <Exception> LoginAsync(cMethodControl pMC, cAccountId pAccountId, cLogin pLogin, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LoginAsync), pMC, pAccountId);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notauthenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnauthenticated);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this is only called during connect

                    lBuilder.Add(kLoginCommandPartLogin, cCommandPartFactory.AsASCIILiteral(pLogin.UserId), cCommandPart.Space, cCommandPartFactory.AsASCIILiteral(pLogin.Password));

                    var lHook = new cCommandHookInitial();
                    lBuilder.Add(lHook);

                    var lCapabilities = mPipeline.Capabilities;

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("login success");
                        ZAuthenticated(lCapabilities, lHook, lResult.ResponseText, pAccountId, lContext);
                        return(null);
                    }

                    if (lHook.Capabilities != null)
                    {
                        lContext.TraceError("received capability on a failed login");
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        lContext.TraceInformation("login failed: {0}", lResult.ResponseText);

                        if (ZSetHomeServerReferral(lResult.ResponseText, lContext))
                        {
                            return(new cHomeServerReferralException(lResult.ResponseText, lContext));
                        }

                        if (lResult.ResponseText.Code == eResponseTextCode.authenticationfailed || lResult.ResponseText.Code == eResponseTextCode.authorizationfailed || lResult.ResponseText.Code == eResponseTextCode.expired)
                        {
                            return(new cCredentialsException(lResult.ResponseText, lContext));
                        }

                        return(null);
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 6
0
            public async Task IdAsync(cMethodControl pMC, cId pClientId, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(IdAsync), pMC, pClientId);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState < eConnectionState.notauthenticated || _ConnectionState > eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                // install the permanent response data processor
                if (mIdResponseDataProcessor == null)
                {
                    mIdResponseDataProcessor = new cIdDataProcessor(mSynchroniser);
                    mPipeline.Install(mIdResponseDataProcessor);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kIdCommandPart);

                    if (pClientId == null || pClientId.Count == 0)
                    {
                        lBuilder.Add(cCommandPart.Nil);
                    }
                    else
                    {
                        lBuilder.BeginList(eListBracketing.bracketed);

                        foreach (var lPair in pClientId)
                        {
                            lBuilder.Add(mCommandPartFactory.AsString(lPair.Key));
                            lBuilder.Add(mCommandPartFactory.AsNString(lPair.Value));
                        }

                        lBuilder.EndList();
                    }

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("id success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, fCapabilities.id, lContext);
                }
            }
Esempio n. 7
0
            public async Task <cMessageHandleList> SetUnseenCountAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SetUnseenCountAsync), pMC, pMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    var lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, null);

                    lBuilder.Add(await mSearchExclusiveAccess.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // search commands must be single threaded (so we can tell which result is which)

                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);                            // if a UIDValidity change happens while the command is running, disbelieve the results

                    lBuilder.Add(kSetUnseenCountCommandPart);

                    var lHook = new cSetUnseenCountCommandHook(lSelectedMailbox);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("setunseencount success");
                        if (lHook.MessageHandles == null)
                        {
                            throw new cUnexpectedServerActionException(0, "results not received on a successful setunseencount", lContext);
                        }
                        return(lHook.MessageHandles);
                    }

                    if (lHook.MessageHandles != null)
                    {
                        lContext.TraceError("results received on a failed setunseencount");
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 8
0
            public async Task <List <iMailboxHandle> > LSubAsync(cMethodControl pMC, string pListMailbox, char?pDelimiter, cMailboxPathPattern pPattern, bool pHasSubscribedChildren, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LSubAsync), pMC, pListMailbox, pDelimiter, pPattern, pHasSubscribedChildren);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pListMailbox == null)
                {
                    throw new ArgumentNullException(nameof(pListMailbox));
                }
                if (pPattern == null)
                {
                    throw new ArgumentNullException(nameof(pPattern));
                }

                if (!mCommandPartFactory.TryAsListMailbox(pListMailbox, pDelimiter, out var lListMailboxCommandPart))
                {
                    throw new ArgumentOutOfRangeException(nameof(pListMailbox));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kLSubCommandPart, lListMailboxCommandPart);

                    var lHook = new cCommandHookLSub(mMailboxCache, pPattern, pHasSubscribedChildren);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("lsub success");
                        return(lHook.MailboxHandles);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 9
0
            public async Task EnableAsync(cMethodControl pMC, fEnableableExtensions pExtensions, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(EnableAsync), pMC, pExtensions);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.authenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotAuthenticated);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this can only called during connect

                    lBuilder.BeginList(eListBracketing.none);
                    lBuilder.Add(kEnableCommandPartEnable);
                    if ((pExtensions & fEnableableExtensions.utf8) != 0)
                    {
                        lBuilder.Add(kEnableCommandPartUTF8);
                    }
                    // more here as required
                    lBuilder.EndList();

                    var lHook = new cEnableCommandHook();
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        var lEnabledExtensions = lHook.EnabledExtensions;
                        lContext.TraceInformation("enabled extensions {0}", lEnabledExtensions);
                        EnabledExtensions = EnabledExtensions | lEnabledExtensions;
                        lContext.TraceVerbose("current enabled extensions {0}", EnabledExtensions);
                        mSynchroniser.InvokePropertyChanged(nameof(cIMAPClient.EnabledExtensions), lContext);
                        return;
                    }

                    if (lHook.EnabledExtensions != fEnableableExtensions.none)
                    {
                        lContext.TraceError("received enabled on a failed enable");
                    }

                    throw new cProtocolErrorException(lResult, fCapabilities.enable, lContext);
                }
            }
Esempio n. 10
0
            public async Task LogoutAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LogoutAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState < eConnectionState.notauthenticated || _ConnectionState > eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kLogoutCommandPart);

                    var lHook = new cLogoutCommandHook(mPipeline);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("logout success");
                        if (!lHook.GotBye)
                        {
                            throw new cUnexpectedServerActionException(0, "bye not received", lContext);
                        }
                        Disconnect(lContext);
                        return;
                    }

                    if (lHook.GotBye)
                    {
                        lContext.TraceError("received bye on a failed logout");
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 11
0
            public async Task DeleteAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(DeleteAsync), pMC, pMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                var lItem = mMailboxCache.CheckHandle(pMailboxHandle);

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kDeleteCommandPart, lItem.MailboxNameCommandPart);

                    lBuilder.Add(new cDeleteCommandHook(lItem));

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("delete success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 12
0
            public async Task <char?> ListDelimiterAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ListDelimiterAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.enabled && _ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kListDelimiterCommandPart);

                    var lHook = new cListDelimiterCommandHook();
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("list delimiter success");
                        return(lHook.Delimiter);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 13
0
            public async Task CloseAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CloseAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // get exclusive access to the selected mailbox

                    mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, null);

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.Add(kCloseCommandPart);

                    var lHook = new cCloseCommandHook(mMailboxCache);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("close success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 14
0
            // NOTE that this needs extract info for the languages extension (translations of the responses)

            public async Task NamespaceAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(NamespaceAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.enabled && _ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                if (mNamespaceDataProcessor == null)
                {
                    mNamespaceDataProcessor = new cNamespaceDataProcessor(mSynchroniser, (EnabledExtensions & fEnableableExtensions.utf8) != 0);
                    mPipeline.Install(mNamespaceDataProcessor);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kNamespaceCommandPart);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("namespace success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, fCapabilities.namespaces, lContext);
                }
            }
Esempio n. 15
0
            public async Task CapabilityAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CapabilityAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notauthenticated && _ConnectionState != eConnectionState.authenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnecting);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this is only called during connect

                    lBuilder.Add(kCapabilityCommandPart);

                    var lCapabilities = mPipeline.Capabilities;

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType != eCommandResultType.ok)
                    {
                        throw new cProtocolErrorException(lResult, 0, lContext);
                    }

                    lContext.TraceInformation("capability success");

                    if (ReferenceEquals(lCapabilities, mPipeline.Capabilities))
                    {
                        throw new cUnexpectedServerActionException(0, "capability not received", lContext);
                    }

                    ZSetCapabilities(mPipeline.Capabilities, mPipeline.AuthenticationMechanisms, lContext);
                }
            }
Esempio n. 16
0
            private async Task <cCopyFeedback> ZUIDCopyAsync(cMethodControl pMC, iMailboxHandle pSourceMailboxHandle, uint pSourceUIDValidity, cUIntList pSourceUIDs, cMailboxCacheItem pDestinationItem, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZCopyAsync), pMC, pSourceMailboxHandle, pSourceUIDValidity, pSourceUIDs, pDestinationItem);

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pSourceMailboxHandle, pSourceUIDValidity);

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.AddUIDValidity(pSourceUIDValidity);                                            // the command is sensitive to UIDValidity changes

                    // build the command
                    lBuilder.Add(kUIDCopyCommandPart, new cTextCommandPart(cSequenceSet.FromUInts(pSourceUIDs)), cCommandPart.Space, pDestinationItem.MailboxNameCommandPart);

                    // add the hook
                    var lHook = new cCommandHookCopy(pSourceUIDValidity);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid copy success");
                        return(lHook.Feedback);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 17
0
            public async Task StartTLSAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(StartTLSAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notauthenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnauthenticated);
                }
                if (mPipeline.TLSInstalled)
                {
                    throw new InvalidOperationException();
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this is only called during connect

                    lBuilder.Add(kStartTLSCommandPart);

                    var lHook = new cStartTLSCommandHook(mPipeline);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceVerbose("starttls success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 18
0
            public async Task <List <iMailboxHandle> > ListExtendedAsync(cMethodControl pMC, eListExtendedSelect pSelect, bool pRemote, string pListMailbox, char?pDelimiter, cMailboxPathPattern pPattern, bool pStatus, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ListExtendedAsync), pMC, pSelect, pRemote, pListMailbox, pDelimiter, pPattern, pStatus);

                // caller needs to determine if list status is supported

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                if (pListMailbox == null)
                {
                    throw new ArgumentNullException(nameof(pListMailbox));
                }
                if (pPattern == null)
                {
                    throw new ArgumentNullException(nameof(pPattern));
                }

                if (!mCommandPartFactory.TryAsListMailbox(pListMailbox, pDelimiter, out var lListMailboxCommandPart))
                {
                    throw new ArgumentOutOfRangeException(nameof(pListMailbox));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.BeginList(eListBracketing.none);

                    lBuilder.Add(kListExtendedCommandPartList);

                    lBuilder.BeginList(eListBracketing.ifany);

                    if (pSelect == eListExtendedSelect.subscribed)
                    {
                        lBuilder.Add(kListExtendedCommandPartSubscribed);
                    }
                    else if (pSelect == eListExtendedSelect.subscribedrecursive)
                    {
                        lBuilder.Add(kListExtendedCommandPartSubscribed);
                        lBuilder.Add(kListExtendedCommandPartRecursiveMatch);
                    }

                    if (pRemote)
                    {
                        lBuilder.Add(kListExtendedCommandPartRemote);
                    }

                    lBuilder.EndList();

                    lBuilder.Add(kListExtendedCommandPartMailbox);
                    lBuilder.Add(lListMailboxCommandPart);

                    // return options

                    lBuilder.BeginList(eListBracketing.ifany, kListExtendedCommandPartReturnSpace);

                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.subscribed) != 0)
                    {
                        lBuilder.Add(kListExtendedCommandPartSubscribed);
                    }
                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.children) != 0)
                    {
                        lBuilder.Add(kListExtendedCommandPartChildren);
                    }
                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.specialuse) != 0 && _Capabilities.SpecialUse)
                    {
                        lBuilder.Add(kListExtendedCommandPartSpecialUse);
                    }

                    if (pStatus)
                    {
                        lBuilder.Add(kListExtendedCommandPartStatus);
                        lBuilder.AddStatusAttributes(mStatusAttributes);
                    }

                    lBuilder.EndList();
                    lBuilder.EndList();

                    var lHook = new cListExtendedCommandHook(mMailboxCache, pSelect, pPattern, pStatus);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("listextended success");
                        return(lHook.MailboxHandles);
                    }

                    fCapabilities lTryIgnoring = 0;

                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.specialuse) != 0 && _Capabilities.SpecialUse)
                    {
                        lTryIgnoring |= fCapabilities.specialuse;
                    }
                    if (pStatus)
                    {
                        lTryIgnoring |= fCapabilities.liststatus;
                    }
                    if (lTryIgnoring == 0)
                    {
                        lTryIgnoring |= fCapabilities.listextended;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Esempio n. 19
0
            private async Task ZStoreAsync(cMethodControl pMC, cStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZStoreAsync), pMC, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq);

                // no validation ... all the parameters have been validated already by the cSession by the time we get here

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pFeedback);
                    if (!lSelectedMailbox.SelectedForUpdate)
                    {
                        throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);
                    }

                    lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe)
                    lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false));    // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe

                    // uidvalidity must be captured before the handles are resolved
                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);

                    // collector
                    cStoreFeedbackCollector lFeedbackCollector = new cStoreFeedbackCollector();

                    // resolve the handles to MSNs
                    foreach (var lItem in pFeedback)
                    {
                        var lMSN = lSelectedMailbox.GetMSN(lItem.MessageHandle);
                        if (lMSN != 0)
                        {
                            lFeedbackCollector.Add(lMSN, lItem);
                        }
                    }

                    // if no handles were resolved, we are done
                    if (lFeedbackCollector.Count == 0)
                    {
                        return;
                    }

                    // build the command
                    lBuilder.Add(kStoreCommandPartStoreSpace, new cTextCommandPart(cSequenceSet.FromUInts(lFeedbackCollector.UInts)), cCommandPart.Space);
                    if (pIfUnchangedSinceModSeq != null)
                    {
                        lBuilder.Add(kStoreCommandPartLParenUnchangedSinceSpace, new cTextCommandPart(pIfUnchangedSinceModSeq.Value), kStoreCommandPartRParenSpace);
                    }
                    lBuilder.Add(pOperation, pFlags);

                    // add the hook
                    var lHook = new cCommandHookStore(lFeedbackCollector, null, lSelectedMailbox);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    // NOTE: updates may have been done on both OK and NO responses (see rfc 2180/ 7162) so we can't throw on a NO for this command ... NO indicates that some (or all) of the messages have pending deletes

                    // throw on a bad
                    if (lResult.ResultType == eCommandResultType.bad)
                    {
                        fCapabilities lTryIgnoring;
                        if (pIfUnchangedSinceModSeq == null)
                        {
                            lTryIgnoring = 0;
                        }
                        else
                        {
                            lTryIgnoring = fCapabilities.condstore;
                        }
                        throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                    }

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("store success");
                    }
                    else
                    {
                        lContext.TraceInformation("store possible partial success");
                    }
                }
            }
Esempio n. 20
0
            private async Task <cBody> ZUIDFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, bool pBinary, cSection pSection, uint pOrigin, uint pLength, cTrace.cContext pParentContext)
            {
                // the caller must have checked that the binary option is compatible with the section (e.g. if binary is true the section can't specify a textpart)
                //  the length must be greater than zero

                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZUIDFetchBodyAsync), pMC, pMailboxHandle, pUID, pBinary, pSection, pOrigin, pLength);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pUID == null)
                {
                    throw new ArgumentNullException(nameof(pUID));
                }
                if (pSection == null)
                {
                    throw new ArgumentNullException(nameof(pSection));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity);

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    // set uidvalidity
                    lBuilder.AddUIDValidity(pUID.UIDValidity);

                    // build command

                    lBuilder.Add(kFetchCommandPartUIDFetchSpace, new cTextCommandPart(pUID.UID));

                    if (pBinary)
                    {
                        lBuilder.Add(kFetchCommandPartSpaceBinaryPeekLBracket);
                    }
                    else
                    {
                        lBuilder.Add(kFetchCommandPartSpaceBodyPeekLBracket);
                    }

                    lBuilder.Add(pSection, pOrigin, pLength);

                    // hook
                    var lHook = new cCommandHookFetchBodyUID(pBinary, pSection, pOrigin, pUID.UID);
                    lBuilder.Add(lHook);

                    // go

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid fetch body success");
                        if (lHook.Body == null)
                        {
                            throw new cRequestedDataNotReturnedException(lContext);
                        }
                        return(lHook.Body);
                    }

                    if (lHook.Body != null)
                    {
                        lContext.TraceError("received body on a failed uid fetch body");
                    }

                    fCapabilities lTryIgnoring;
                    if (pBinary)
                    {
                        lTryIgnoring = fCapabilities.binary;
                    }
                    else
                    {
                        lTryIgnoring = 0;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Esempio n. 21
0
            private async Task ZFetchCacheItemsAsync(cMethodControl pMC, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchCacheItemsAsync), pMC, pMessageHandles, pItems);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }

                if (pMessageHandles == null)
                {
                    throw new ArgumentNullException(nameof(pMessageHandles));
                }
                if (pItems == null)
                {
                    throw new ArgumentNullException(nameof(pItems));
                }

                if (pMessageHandles.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pMessageHandles));
                }
                if (pItems.IsEmpty)
                {
                    throw new ArgumentOutOfRangeException(nameof(pItems));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pMessageHandles);

                    lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe)
                    lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false));    // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe

                    // uidvalidity must be captured before the handles are resolved
                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);

                    // resolve MSNs

                    cUIntList lMSNs = new cUIntList();

                    foreach (var lMessageHandle in pMessageHandles)
                    {
                        var lMSN = lSelectedMailbox.GetMSN(lMessageHandle);
                        if (lMSN != 0)
                        {
                            lMSNs.Add(lMSN);
                        }
                    }

                    if (lMSNs.Count == 0)
                    {
                        return;
                    }

                    // build command

                    lBuilder.Add(kFetchCommandPartFetchSpace, new cTextCommandPart(cSequenceSet.FromUInts(lMSNs)), cCommandPart.Space);
                    lBuilder.Add(pItems, lSelectedMailbox.MessageCache.NoModSeq);

                    // go

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("fetch success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 22
0
            public async Task <cMessageHandleList> SearchExtendedAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cFilter pFilter, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SearchExtendedAsync), pMC, pMailboxHandle, pFilter);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pFilter == null)
                {
                    throw new ArgumentNullException(nameof(pFilter));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    var lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pFilter.UIDValidity);

                    // special cases
                    if (ReferenceEquals(pFilter, cFilter.All))
                    {
                        return(new cMessageHandleList(lSelectedMailbox.MessageCache));
                    }
                    if (ReferenceEquals(pFilter, cFilter.None))
                    {
                        return(new cMessageHandleList());
                    }

                    if (pFilter.ContainsMessageHandles)
                    {
                        lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe
                    }
                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);                         // if a UIDValidity change happens while the command is running, disbelieve the results

                    lBuilder.Add(kSearchExtendedCommandPart);
                    lBuilder.Add(pFilter, lSelectedMailbox, false, mEncodingPartFactory);

                    var lHook = new cCommandHookSearchExtended(lBuilder.Tag, lSelectedMailbox, false);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("extended search success");
                        if (lHook.MessageHandles == null)
                        {
                            throw new cUnexpectedServerActionException(fCapabilities.esearch, "results not received on a successful extended search", lContext);
                        }
                        return(lHook.MessageHandles);
                    }

                    if (lHook.MessageHandles != null)
                    {
                        lContext.TraceError("results received on a failed extended search");
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, fCapabilities.esearch, lContext);
                    }
                    throw new cProtocolErrorException(lResult, fCapabilities.esearch, lContext);
                }
            }
Esempio n. 23
0
            public async Task SelectAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SelectAsync), pMC, pMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                var lItem = mMailboxCache.CheckHandle(pMailboxHandle);

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // get exclusive access to the selected mailbox
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));        // this command is msnunsafe

                    lBuilder.Add(kSelectCommandPart, lItem.MailboxNameCommandPart);
                    if (_Capabilities.CondStore)
                    {
                        lBuilder.Add(kSelectCommandPartCondStore);
                    }

                    var lHook = new cCommandHookSelect(mMailboxCache, _Capabilities, pMailboxHandle, true);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("select success");
                        return;
                    }

                    fCapabilities lTryIgnoring;
                    if (_Capabilities.CondStore)
                    {
                        lTryIgnoring = fCapabilities.condstore;
                    }
                    if (_Capabilities.QResync)
                    {
                        lTryIgnoring = fCapabilities.qresync;
                    }
                    else
                    {
                        lTryIgnoring = 0;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Esempio n. 24
0
            public async Task StatusAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(StatusAsync), pMC, pMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                var lItem = mMailboxCache.CheckHandle(pMailboxHandle);

                if (mStatusAttributes == 0)
                {
                    return;
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select: the status command is not supported on the selected mailbox

                    var lMailboxHandle = mMailboxCache.SelectedMailboxDetails?.MailboxHandle;
                    if (ReferenceEquals(pMailboxHandle, lMailboxHandle))
                    {
                        return;
                    }

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // status is msnunsafe

                    lBuilder.BeginList(eListBracketing.none);
                    lBuilder.Add(kStatusCommandPart);
                    lBuilder.Add(lItem.MailboxNameCommandPart);
                    lBuilder.AddStatusAttributes(mStatusAttributes);
                    lBuilder.EndList();

                    var lHook = new cStatusCommandHook(lItem);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("status success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        lContext.TraceInformation("status unsuccessful");
                        return;
                    }

                    fCapabilities lTryIgnoring;
                    if (_Capabilities.CondStore)
                    {
                        lTryIgnoring = fCapabilities.condstore;
                    }
                    else
                    {
                        lTryIgnoring = 0;
                    }

                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Esempio n. 25
0
            public async Task UIDFetchBinarySizeAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, string pPart, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchBinarySizeAsync), pMC, pMailboxHandle, pUID, pPart);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pUID == null)
                {
                    throw new ArgumentNullException(nameof(pUID));
                }
                if (pPart == null)
                {
                    throw new ArgumentNullException(nameof(pPart));
                }

                if (!cCommandPartFactory.TryAsAtom(pPart, out var lPart))
                {
                    throw new ArgumentOutOfRangeException(nameof(pPart));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity);

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    // set uidvalidity
                    lBuilder.AddUIDValidity(pUID.UIDValidity);

                    // build command
                    lBuilder.Add(kFetchCommandPartUIDFetchSpace, new cTextCommandPart(pUID.UID), kFetchCommandPartSpaceBinarySizeLBracket, lPart, cCommandPart.RBracket);

                    // go

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid fetch binary.size success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, fCapabilities.binary, lContext);
                    }
                    throw new cProtocolErrorException(lResult, fCapabilities.binary, lContext);
                }
            }
Esempio n. 26
0
            public async Task FetchBinarySizeAsync(cMethodControl pMC, iMessageHandle pMessageHandle, string pPart, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(FetchBinarySizeAsync), pMC, pMessageHandle, pPart);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMessageHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMessageHandle));
                }
                if (pPart == null)
                {
                    throw new ArgumentNullException(nameof(pPart));
                }

                if (!cCommandPartFactory.TryAsAtom(pPart, out var lPart))
                {
                    throw new ArgumentOutOfRangeException(nameof(pPart));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pMessageHandle);

                    lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe)
                    lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false));    // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe

                    // uidvalidity must be captured before the handles are resolved
                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);

                    // resolve the MSN
                    uint lMSN = lSelectedMailbox.GetMSN(pMessageHandle);

                    if (lMSN == 0)
                    {
                        if (pMessageHandle.Expunged)
                        {
                            throw new cMessageExpungedException(pMessageHandle);
                        }
                        else
                        {
                            throw new ArgumentOutOfRangeException(nameof(pMessageHandle));
                        }
                    }

                    // build command
                    lBuilder.Add(kFetchCommandPartFetchSpace, new cTextCommandPart(lMSN), kFetchCommandPartSpaceBinarySizeLBracket, lPart, cCommandPart.RBracket);

                    // go

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("fetch binary.size success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, fCapabilities.binary, lContext);
                    }
                    throw new cProtocolErrorException(lResult, fCapabilities.binary, lContext);
                }
            }
Esempio n. 27
0
            private async Task ZUIDFetchCacheItemsAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, uint pUIDValidity, cUIntList pUIDs, cMessageCacheItems pItems, cTrace.cContext pParentContext)
            {
                // note that this will fail if the UIDValidity has changed (this is different to the behaviour of standard fetch)
                // note that the caller should have checked that pAttributes contains some attributes to fetch

                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZUIDFetchCacheItemsAsync), pMC, pMailboxHandle, pUIDValidity, pUIDs, pItems);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }

                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pUIDs == null)
                {
                    throw new ArgumentNullException(nameof(pUIDs));
                }
                if (pItems == null)
                {
                    throw new ArgumentNullException(nameof(pItems));
                }

                if (pUIDs.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pUIDs));
                }
                if (pItems.IsEmpty)
                {
                    throw new ArgumentOutOfRangeException(nameof(pItems));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUIDValidity);

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.AddUIDValidity(pUIDValidity);                                                  // the command is sensitive to UIDValidity changes

                    lBuilder.Add(kFetchCommandPartUIDFetchSpace, new cTextCommandPart(cSequenceSet.FromUInts(pUIDs)), cCommandPart.Space);
                    lBuilder.Add(pItems, lSelectedMailbox.MessageCache.NoModSeq);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid fetch success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 28
0
            public async Task <Exception> AuthenticateAsync(cMethodControl pMC, cAccountId pAccountId, cSASL pSASL, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(AuthenticateAsync), pMC, pAccountId, pSASL.MechanismName);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notauthenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnauthenticated);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this is only called during connect

                    lBuilder.Add(kAuthenticateCommandPartAuthenticate);
                    lBuilder.Add(new cTextCommandPart(pSASL.MechanismName));

                    var lAuthentication = pSASL.GetAuthentication();
                    lBuilder.Add(lAuthentication);
                    pSASL.LastAuthentication = lAuthentication;

                    if (_Capabilities.SASL_IR)
                    {
                        IList <byte> lAuthenticationResponse;

                        try { lAuthenticationResponse = lAuthentication.GetResponse(null); }
                        catch (Exception e)
                        {
                            lContext.TraceException("SASL authentication object threw when getting initial response", e);
                            return(null);
                        }

                        if (lAuthenticationResponse != null)
                        {
                            lBuilder.Add(cCommandPart.Space);
                            if (lAuthenticationResponse.Count == 0)
                            {
                                lBuilder.Add(kAuthenticateCommandPartEqual);                                     // special case where the initial response is an empty string
                            }
                            else
                            {
                                lBuilder.Add(new cTextCommandPart(cBase64.Encode(lAuthenticationResponse), true));
                            }
                        }
                    }

                    var lHook = new cCommandHookAuthenticate(mPipeline, lAuthentication, _Capabilities.LoginReferrals);
                    lBuilder.Add(lHook);

                    var lCapabilities = mPipeline.Capabilities;

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("authenticate success");
                        ZAuthenticated(lCapabilities, lHook, lResult.ResponseText, pAccountId, lContext);
                        return(null);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        lContext.TraceInformation("authenticate failed: {0}", lResult.ResponseText);

                        if (ZSetHomeServerReferral(lResult.ResponseText, lContext))
                        {
                            return(new cHomeServerReferralException(lResult.ResponseText, lContext));
                        }

                        if (lResult.ResponseText.Code == eResponseTextCode.authenticationfailed || lResult.ResponseText.Code == eResponseTextCode.authorizationfailed || lResult.ResponseText.Code == eResponseTextCode.expired)
                        {
                            return(new cCredentialsException(lResult.ResponseText, lContext));
                        }

                        return(null);
                    }

                    lContext.TraceInformation("authenticate cancelled");

                    return(null);
                }
            }
Esempio n. 29
0
            private async Task <cCopyFeedback> ZCopyAsync(cMethodControl pMC, cMessageHandleList pSourceMessageHandles, cMailboxCacheItem pDestinationItem, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZCopyAsync), pMC, pSourceMessageHandles, pDestinationItem);

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pSourceMessageHandles);

                    lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe)
                    lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false));    // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe

                    // uidvalidity must be captured before the handles are resolved
                    var lUIDValidity = lSelectedMailbox.MessageCache.UIDValidity;
                    lBuilder.AddUIDValidity(lUIDValidity);

                    // resolve the handles to MSNs

                    cUIntList lMSNs = new cUIntList();

                    foreach (var lMessageHandle in pSourceMessageHandles)
                    {
                        var lMSN = lSelectedMailbox.GetMSN(lMessageHandle);

                        if (lMSN == 0)
                        {
                            if (lMessageHandle.Expunged)
                            {
                                throw new cMessageExpungedException(lMessageHandle);
                            }
                            else
                            {
                                throw new ArgumentOutOfRangeException(nameof(pSourceMessageHandles));
                            }
                        }

                        lMSNs.Add(lMSN);
                    }

                    // build the command
                    lBuilder.Add(kCopyCommandPart, new cTextCommandPart(cSequenceSet.FromUInts(lMSNs)), cCommandPart.Space, pDestinationItem.MailboxNameCommandPart);

                    // add the hook
                    var lHook = new cCommandHookCopy(lUIDValidity);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("copy success");
                        return(lHook.Feedback);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }