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 ZMessagesFetchAsync(cMethodControl pMC, cSession pSession, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMessagesFetchAsync), pMC, pMessageHandles, pItems); if (pMessageHandles.Count == 0) { return; } if (pItems.IsEmpty) { return; } if (pMessageHandles.TrueForAll(h => h.Contains(pItems))) { return; } cProgress lProgress; if (pConfiguration == null) { lProgress = new cProgress(); } else { mSynchroniser.InvokeActionInt(pConfiguration.SetCount, pMessageHandles.Count, lContext); lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); } await pSession.FetchCacheItemsAsync(pMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); }
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 <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); } }
private async Task ZSelectAsync(iMailboxHandle pMailboxHandle, bool pForUpdate, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZSelectAsync), pMailboxHandle, pForUpdate); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || !lSession.IsConnected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected); } if (pMailboxHandle == null) { throw new ArgumentNullException(nameof(pMailboxHandle)); } using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); if (pForUpdate) { await lSession.SelectAsync(lMC, pMailboxHandle, lContext).ConfigureAwait(false); } else { await lSession.ExamineAsync(lMC, pMailboxHandle, lContext).ConfigureAwait(false); } } }
public async Task FetchCacheItemsAsync(cMethodControl pMC, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cProgress pProgress, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(FetchCacheItemsAsync), 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 (pProgress == null) { throw new ArgumentNullException(nameof(pProgress)); } mMailboxCache.CheckInSelectedMailbox(pMessageHandles); // to be repeated inside the select lock // split the handles into groups based on what attributes need to be retrieved, for each group do the retrieval foreach (var lGroup in ZFetchCacheItemsGroups(pMessageHandles, pItems)) { await ZFetchCacheItemsAsync(pMC, lGroup, pProgress, lContext).ConfigureAwait(false); } }
private async Task <cMailbox> ZCreateAsync(cMailboxName pMailboxName, bool pAsFutureParent, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZCreateAsync), pMailboxName, pAsFutureParent); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || !lSession.IsConnected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected); } if (pMailboxName == null) { throw new ArgumentNullException(nameof(pMailboxName)); } using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); var lMailboxHandle = await lSession.CreateAsync(lMC, pMailboxName, pAsFutureParent, lContext).ConfigureAwait(false); return(new cMailbox(this, lMailboxHandle)); } }
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); } }
private async Task ZDisconnectAsync(cTrace.cContext pParentContext) { var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(ZDisconnectAsync)); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || !lSession.IsConnected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected); } using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); try { await lSession.LogoutAsync(lMC, lContext).ConfigureAwait(false); } catch when(lSession.ConnectionState != eConnectionState.disconnected) { lSession.Disconnect(lContext); throw; } } }
public async sealed override Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext) { while (pOffset < pBytes.Count) { byte lByte = pBytes[pOffset++]; if (mBufferedCR) { mBufferedCR = false; if (lByte == cASCII.LF) { await YWriteLineAsync(pMC, mLine, pWriteSizer, pContext).ConfigureAwait(false); mLine.Clear(); continue; } mLine.Add(cASCII.CR); } if (lByte == cASCII.CR) { mBufferedCR = true; } else { mLine.Add(lByte); } } }
public static void _Tests(cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cQuotedPrintableDecoder), nameof(_Tests)); if (LTest("testNow's the time = \r\n", "for all folk to come=\t \t \r\n", " to the aid of their country. \t\r\n") != "Now's the time for all folk to come to the aid of their country.\r\n") { throw new cTestsException($"{nameof(cQuotedPrintableDecoder)}.1"); } string LTest(params string[] pLines) { var lMC = new cMethodControl(-1, System.Threading.CancellationToken.None); var lWriteSizer = new cBatchSizer(new cBatchSizerConfiguration(1, 10, 1000, 1)); using (var lStream = new MemoryStream()) { cDecoder lDecoder = new cQuotedPrintableDecoder(lStream); int lOffset = 4; foreach (var lLine in pLines) { lDecoder.WriteAsync(lMC, new cBytes(lLine), lOffset, lWriteSizer, lContext).Wait(); lOffset = 0; } lDecoder.FlushAsync(lMC, lWriteSizer, lContext).Wait(); return(new string(System.Text.Encoding.UTF8.GetChars(lStream.GetBuffer(), 0, (int)lStream.Length))); } } }
protected async Task YWriteAsync(cMethodControl pMC, IList <byte> pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext) { if (mStream.CanTimeout) { mStream.WriteTimeout = pMC.Timeout; } while (pOffset < pBytes.Count) { if (mCount == 0) { mBuffer = new byte[pWriteSizer.Current]; } while (mCount < mBuffer.Length && pOffset < pBytes.Count) { mBuffer[mCount++] = pBytes[pOffset++]; } if (mCount < mBuffer.Length) { return; } await YFlushAsync(pMC, pWriteSizer, pContext).ConfigureAwait(false); } }
protected async override Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext) { // build the buffer to decode mBytes.Clear(); foreach (var lByte in pLine) { if (cBase64.IsInAlphabet(lByte)) { mBytes.Add(lByte); } } // special case if (mBytes.Count == 0) { return; } // decode if (!cBase64.TryDecode(mBytes, out var lBytes, out var lError)) { throw new cContentTransferDecodingException(lError, pContext); } await YWriteAsync(pMC, lBytes, 0, pWriteSizer, pContext).ConfigureAwait(false); }
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 sealed override Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext) { if (mBufferedCR) { mLine.Add(cASCII.CR); } await YWriteLineAsync(pMC, mLine, pWriteSizer, pContext).ConfigureAwait(false); await YFlushAsync(pMC, pWriteSizer, pContext).ConfigureAwait(false); }
private async Task ZUIDFetchBodyAsync(iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cBodyFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDFetchBodyAsync), pMailboxHandle, pUID, pSection, pDecoding); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.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)); } if (pStream == null) { throw new ArgumentNullException(nameof(pStream)); } if (!pStream.CanWrite) { throw new ArgumentOutOfRangeException(nameof(pStream)); } if (pConfiguration == null) { using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); var lProgress = new cProgress(); var lWriteSizer = new cBatchSizer(mFetchBodyWriteConfiguration); await lSession.UIDFetchBodyAsync(lMC, pMailboxHandle, pUID, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false); } } else { var lMC = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken); var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); var lWriteSizer = new cBatchSizer(pConfiguration.Write ?? mFetchBodyWriteConfiguration); await lSession.UIDFetchBodyAsync(lMC, pMailboxHandle, pUID, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false); } }
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 UIDStoreAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUIDStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDStoreAsync), pMC, pMailboxHandle, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq); 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 (pFeedback == null) { throw new ArgumentNullException(nameof(pFeedback)); } if (pFlags == null) { throw new ArgumentNullException(nameof(pFlags)); } if (pFeedback.Count == 0) { throw new ArgumentOutOfRangeException(nameof(pFeedback)); } if (pIfUnchangedSinceModSeq == 0) { throw new ArgumentOutOfRangeException(nameof(pIfUnchangedSinceModSeq)); } if (pIfUnchangedSinceModSeq != null && !_Capabilities.CondStore) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.CondStoreNotInUse); } uint lUIDValidity = pFeedback[0].UID.UIDValidity; cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity); // to be repeated inside the select lock if (!lSelectedMailbox.SelectedForUpdate) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate); // to be repeated inside the select lock } cStoreFeedbackCollector lFeedbackCollector = new cStoreFeedbackCollector(pFeedback); await ZUIDStoreAsync(pMC, pMailboxHandle, lUIDValidity, lFeedbackCollector, pOperation, pFlags, pIfUnchangedSinceModSeq, pFeedback, lContext).ConfigureAwait(false); }
public async Task <cExclusiveAccess.cToken> GetIdleBlockTokenAsync(cMethodControl pMC, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(GetIdleBlockTokenAsync)); if (mDisposed) { throw new ObjectDisposedException(nameof(cCommandPipeline)); } var lTask = mIdleBlock.GetTokenAsync(pMC, lContext); mBackgroundReleaser.Release(lContext); return(await lTask.ConfigureAwait(false)); }
private Task ZRequestStatus(cMethodControl pMC, cSession pSession, List <iMailboxHandle> pMailboxHandles, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZRequestStatus), pMC); List <Task> lTasks = new List <Task>(); foreach (var lMailboxHandle in pMailboxHandles) { if (lMailboxHandle.ListFlags?.CanSelect == true) { lTasks.Add(pSession.StatusAsync(pMC, lMailboxHandle, lContext)); } } return(Task.WhenAll(lTasks)); }
public async Task ConnectAsync(cMethodControl pMC, cServer pServer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ConnectAsync), pMC, pServer); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.notconnected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnconnected); } ZSetState(eConnectionState.connecting, lContext); sGreeting lGreeting; try { lGreeting = await mPipeline.ConnectAsync(pMC, pServer, lContext).ConfigureAwait(false); } catch (Exception) { ZSetState(eConnectionState.disconnected, lContext); throw; } if (lGreeting.Type == eGreetingType.bye) { ZSetState(eConnectionState.disconnected, lContext); if (ZSetHomeServerReferral(lGreeting.ResponseText, lContext)) { throw new cHomeServerReferralException(lGreeting.ResponseText, lContext); } throw new cConnectByeException(lGreeting.ResponseText, lContext); } if (mPipeline.Capabilities != null) { ZSetCapabilities(mPipeline.Capabilities, mPipeline.AuthenticationMechanisms, lContext); } if (lGreeting.Type == eGreetingType.ok) { ZSetState(eConnectionState.notauthenticated, lContext); return; } // preauth ZSetHomeServerReferral(lGreeting.ResponseText, lContext); ZSetConnectedAccountId(new cAccountId(pServer.Host, eAccountType.unknown), lContext); }
private async Task ZUIDStoreAsync(iMailboxHandle pMailboxHandle, cUIDStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDStoreAsync), pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.SelectedMailboxDetails?.SelectedForUpdate != true) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate); } if (pMailboxHandle == null) { throw new ArgumentNullException(nameof(pMailboxHandle)); } if (pFeedback == null) { throw new ArgumentNullException(nameof(pFeedback)); } if (pFlags == null) { throw new ArgumentNullException(nameof(pFlags)); } if (pIfUnchangedSinceModSeq == 0) { throw new ArgumentOutOfRangeException(nameof(pIfUnchangedSinceModSeq)); } if (pIfUnchangedSinceModSeq != null && !lSession.Capabilities.CondStore) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.CondStoreNotInUse); } if (pFeedback.Count == 0) { return; } // it is valid to add or remove zero flags according to the ABNF (!) using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); await lSession.UIDStoreAsync(lMC, pMailboxHandle, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext).ConfigureAwait(false); } }
private async Task ZFetchCacheItemsAsync(cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZFetchCacheItemsAsync), pMessageHandles, pItems); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.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) { return; } if (pItems.IsEmpty) { return; } if (pConfiguration == null) { using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); var lProgress = new cProgress(); await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); } } else { var lMC = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken); var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); } }
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 Task UIDFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchBodyAsync), pMC, pMailboxHandle, pUID, pSection, pDecoding); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity); // to be repeated inside the select lock return(ZFetchBodyAsync(pMC, pMailboxHandle, pUID, null, pSection, pDecoding, pStream, pProgress, pWriteSizer, lContext)); }
public Task <cCopyFeedback> CopyAsync(cMethodControl pMC, cMessageHandleList pSourceMessageHandles, iMailboxHandle pDestinationMailboxHandle, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CopyAsync), pMC, pSourceMessageHandles, pDestinationMailboxHandle); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pSourceMessageHandles == null) { throw new ArgumentNullException(nameof(pSourceMessageHandles)); } if (pDestinationMailboxHandle == null) { throw new ArgumentNullException(nameof(pDestinationMailboxHandle)); } if (pSourceMessageHandles.Count == 0) { throw new ArgumentOutOfRangeException(nameof(pSourceMessageHandles)); } cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pSourceMessageHandles); // to be repeated inside the select lock var lDestinationItem = mMailboxCache.CheckHandle(pDestinationMailboxHandle); if (pSourceMessageHandles.TrueForAll(h => h.UID != null)) { var lMessageHandle = pSourceMessageHandles.Find(h => h.Expunged); if (lMessageHandle != null) { throw new cMessageExpungedException(lMessageHandle); } return(ZUIDCopyAsync(pMC, lSelectedMailbox.MailboxHandle, pSourceMessageHandles[0].UID.UIDValidity, new cUIntList(from h in pSourceMessageHandles select h.UID.UID), lDestinationItem, lContext)); } else { return(ZCopyAsync(pMC, pSourceMessageHandles, lDestinationItem, lContext)); } }