Пример #1
0
                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)));
                        }
                    }
                }
Пример #2
0
 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);
 }
Пример #3
0
        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);
            }
        }
Пример #4
0
            public void SetFetchBodyReadConfiguration(cBatchSizerConfiguration pConfiguration, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SetFetchBodyReadConfiguration), pConfiguration);

                if (pConfiguration == null)
                {
                    throw new ArgumentNullException(nameof(pConfiguration));
                }
                mFetchBodyReadSizer = new cBatchSizer(pConfiguration);
            }
Пример #5
0
                protected async Task YFlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext)
                {
                    if (mCount == 0)
                    {
                        return;
                    }

                    pContext.TraceVerbose("writing {0} bytes to stream", mCount);

                    mStopwatch.Restart();
                    await mStream.WriteAsync(mBuffer, 0, mCount, pMC.CancellationToken).ConfigureAwait(false);

                    mStopwatch.Stop();

                    // store the time taken so the next write is a better size
                    pWriteSizer.AddSample(mCount, mStopwatch.ElapsedMilliseconds);

                    mCount = 0;
                }
Пример #6
0
            // (note for when adding more: they need to be disposed)

            public cSession(cCallbackSynchroniser pSynchroniser, fCapabilities pIgnoreCapabilities, fMailboxCacheDataItems pMailboxCacheDataItems, cBatchSizerConfiguration pNetworkWriteConfiguration, cIdleConfiguration pIdleConfiguration, cBatchSizerConfiguration pFetchCacheItemsConfiguration, cBatchSizerConfiguration pFetchBodyReadConfiguration, Encoding pEncoding, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewObject(nameof(cSession), pIgnoreCapabilities, pMailboxCacheDataItems, pNetworkWriteConfiguration, pIdleConfiguration, pFetchCacheItemsConfiguration, pFetchBodyReadConfiguration);

                mSynchroniser          = pSynchroniser ?? throw new ArgumentNullException(nameof(pSynchroniser));
                mIgnoreCapabilities    = pIgnoreCapabilities;
                mMailboxCacheDataItems = pMailboxCacheDataItems;

                mPipeline = new cCommandPipeline(pSynchroniser, ZDisconnected, pNetworkWriteConfiguration, pIdleConfiguration, lContext);

                mFetchCacheItemsSizer = new cBatchSizer(pFetchCacheItemsConfiguration);
                mFetchBodyReadSizer   = new cBatchSizer(pFetchBodyReadConfiguration);

                mCommandPartFactory = new cCommandPartFactory(false, null);

                if (pEncoding == null)
                {
                    mEncodingPartFactory = mCommandPartFactory;
                }
                else
                {
                    mEncodingPartFactory = new cCommandPartFactory(false, pEncoding);
                }
            }
Пример #7
0
 public override Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext) => YWriteAsync(pMC, pBytes, pOffset, pWriteSizer, pContext);
Пример #8
0
                private async Task ZBackgroundSendAppendDataAndMoveNextAsync(cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(ZBackgroundSendAppendDataAndMoveNextAsync));

                    switch (mCurrentCommand.CurrentPart())
                    {
                    case cTextCommandPart lText:

                        await ZBackgroundSendAppendDataAsync(lText.Secret, lText.Bytes, lText.Bytes.Count, lContext).ConfigureAwait(false);

                        break;

                    case cLiteralCommandPart lLiteral:

                        await ZBackgroundSendAppendDataAsync(lLiteral.Secret, lLiteral.Bytes, lLiteral.Bytes.Count, lContext).ConfigureAwait(false);

                        break;

                    case cStreamCommandPart lStream:

                        int lBytesRemaining = lStream.Length;

                        if (lBytesRemaining > 0)
                        {
                            Stopwatch   lStopwatch = new Stopwatch();
                            cBatchSizer lReadSizer = new cBatchSizer(lStream.ReadConfiguration);
                            byte[]      lBuffer    = new byte[lReadSizer.Current];

                            while (lBytesRemaining > 0)
                            {
                                int lReadSize = Math.Min(lReadSizer.Current, lBytesRemaining);

                                if (lReadSize > lBuffer.Length)
                                {
                                    lBuffer = new byte[lReadSize];
                                }

                                if (!lStream.Secret)
                                {
                                    lContext.TraceVerbose("reading {0} bytes from stream", lReadSize);
                                }

                                lStopwatch.Restart();
                                int lCount = await lStream.Stream.ReadAsync(lBuffer, 0, lReadSize, mBackgroundCancellationTokenSource.Token).ConfigureAwait(false);

                                lStopwatch.Stop();

                                // store the time taken so the next read is a better size
                                lReadSizer.AddSample(lCount, lStopwatch.ElapsedMilliseconds);

                                await ZBackgroundSendAppendDataAsync(lStream.Secret, lBuffer, lCount, lContext).ConfigureAwait(false);

                                lBytesRemaining -= lCount;
                            }
                        }

                        break;

                    default:

                        throw new cInternalErrorException();
                    }

                    if (mCurrentCommand.MoveNext())
                    {
                        return;
                    }

                    ZBackgroundSendTerminateCommand(lContext);
                }
Пример #9
0
 public cConnection(cBatchSizerConfiguration pWriteConfiguration)
 {
     mWriteSizer = new cBatchSizer(pWriteConfiguration);
 }
Пример #10
0
            private async Task ZFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, iMessageHandle pMessageHandle, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchBodyAsync), pMC, pMailboxHandle, pUID, pMessageHandle, pSection, pDecoding);

                if (pSection == null)
                {
                    throw new ArgumentNullException(nameof(pSection));
                }
                if (pStream == null)
                {
                    throw new ArgumentNullException(nameof(pStream));
                }
                if (pProgress == null)
                {
                    throw new ArgumentNullException(nameof(pProgress));
                }
                if (pWriteSizer == null)
                {
                    throw new ArgumentNullException(nameof(pWriteSizer));
                }

                if (!pStream.CanWrite)
                {
                    throw new ArgumentOutOfRangeException(nameof(pStream));
                }

                // work out if binary can/should be used or not
                bool lBinary = _Capabilities.Binary && pSection.TextPart == eSectionTextPart.all && pDecoding != eDecodingRequired.none;

                cDecoder lDecoder;

                if (lBinary || pDecoding == eDecodingRequired.none)
                {
                    lDecoder = new cIdentityDecoder(pStream);
                }
                else if (pDecoding == eDecodingRequired.base64)
                {
                    lDecoder = new cBase64Decoder(pStream);
                }
                else if (pDecoding == eDecodingRequired.quotedprintable)
                {
                    lDecoder = new cQuotedPrintableDecoder(pStream);
                }
                else
                {
                    throw new cContentTransferDecodingException("required decoding not supported", lContext);
                }

                uint lOrigin = 0;

                Stopwatch lStopwatch = new Stopwatch();

                while (true)
                {
                    int lLength = mFetchBodyReadSizer.Current;

                    lStopwatch.Restart();

                    cBody lBody;
                    if (pUID == null)
                    {
                        lBody = await ZFetchBodyAsync(pMC, pMessageHandle, lBinary, pSection, lOrigin, (uint)lLength, lContext).ConfigureAwait(false);
                    }
                    else
                    {
                        lBody = await ZUIDFetchBodyAsync(pMC, pMailboxHandle, pUID, lBinary, pSection, lOrigin, (uint)lLength, lContext).ConfigureAwait(false);
                    }

                    lStopwatch.Stop();

                    // store the time taken so the next fetch is a better size
                    mFetchBodyReadSizer.AddSample(lBody.Bytes.Count, lStopwatch.ElapsedMilliseconds);

                    uint lBodyOrigin = lBody.Origin ?? 0;

                    // the body that we get may start before the place that we asked for
                    int lOffset = (int)(lOrigin - lBodyOrigin);

                    // write the bytes
                    await lDecoder.WriteAsync(pMC, lBody.Bytes, lOffset, pWriteSizer, lContext).ConfigureAwait(false);

                    // update progress
                    pProgress.Increment(lBody.Bytes.Count - lOffset, lContext);

                    // if the body we got was the whole body, we are done
                    if (lBody.Origin == null)
                    {
                        break;
                    }

                    // if we got less bytes than asked for then we will assume that we are at the end
                    if (lBody.Bytes.Count - lOffset < lLength)
                    {
                        break;
                    }

                    // set the start point for the next fetch
                    lOrigin = lBodyOrigin + (uint)lBody.Bytes.Count;
                }

                await lDecoder.FlushAsync(pMC, pWriteSizer, lContext).ConfigureAwait(false);
            }
Пример #11
0
            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));
            }
Пример #12
0
                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);
                        }
                    }
                }
Пример #13
0
 public override Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext) => YFlushAsync(pMC, pWriteSizer, pContext);
Пример #14
0
 protected abstract Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext);
Пример #15
0
 public abstract Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext);
Пример #16
0
 public abstract Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext);
Пример #17
0
                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);
                }
Пример #18
0
                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);
                    }
                }
Пример #19
0
                protected async override Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext)
                {
                    byte lByte;

                    // special case
                    if (pLine.Count == 0)
                    {
                        return;
                    }

                    // strip trailing space

                    int lEOL = pLine.Count;

                    while (true)
                    {
                        lByte = pLine[lEOL - 1];
                        if (lByte != cASCII.SPACE && lByte != cASCII.TAB)
                        {
                            break;
                        }
                        if (--lEOL == 0)
                        {
                            return;
                        }
                    }

                    // strip trailing =

                    bool lSoftLineBreak;

                    if (pLine[lEOL - 1] == cASCII.EQUALS)
                    {
                        if (--lEOL == 0)
                        {
                            return;
                        }
                        lSoftLineBreak = true;
                    }
                    else
                    {
                        lSoftLineBreak = false;
                    }

                    // decode

                    mBytes.Clear();

                    int lInputByte = 0;

                    while (lInputByte < lEOL)
                    {
                        lByte = pLine[lInputByte++];

                        if (lByte == cASCII.EQUALS)
                        {
                            if (lInputByte + 2 <= lEOL && ZGetHexEncodedNibble(pLine, lInputByte, out int lMSN) && ZGetHexEncodedNibble(pLine, lInputByte + 1, out int lLSN))
                            {
                                lInputByte = lInputByte + 2;
                                lByte      = (byte)(lMSN << 4 | lLSN);
                            }
                        }

                        mBytes.Add(lByte);
                    }

                    if (!lSoftLineBreak)
                    {
                        mBytes.Add(cASCII.CR);
                        mBytes.Add(cASCII.LF);
                    }

                    await YWriteAsync(pMC, mBytes, 0, pWriteSizer, pContext).ConfigureAwait(false);
                }