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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
// 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); } }
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); } }
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); } }
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); } }
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); } }
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"); } } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }