private void BufferData(byte[] data, int offset, int size, bool needToCopyData)
        {
            int n;

            // try last buffer
            if (_lastBuffer != null)
            {
                n       = _lastBuffer.Append(data, offset, size);
                size   -= n;
                offset += n;
            }
            else if (!needToCopyData && offset == 0 && !_responseBufferingOn)
            {
                // when not buffering, there is no need for big buffer accumulating multiple writes
                // the byte[] data can be sent as is

                _buffers.Add(new HttpResponseBufferElement(data, size));
                return;
            }

            // do other buffers if needed
            while (size > 0)
            {
                _lastBuffer = new HttpResponseBufferElement();
                _buffers.Add(_lastBuffer);
                n       = _lastBuffer.Append(data, offset, size);
                offset += n;
                size   -= n;
            }
        }
        //
        // Buffer management
        //

        internal void ClearBuffers()
        {
            ClearCharBuffer();

            _buffers    = new ArrayList();
            _lastBuffer = null;
        }
        private void BufferResource(IntPtr data, int offset, int size)
        {
            if (size > BufferingParams.MAX_RESOURCE_BYTES_TO_COPY || !_responseBufferingOn)
            {
                // for long response strings create its own buffer element to avoid copy cost
                // also, when not buffering, no need for an extra copy (nothing will get accumulated anyway)
                _lastBuffer = null;
                _buffers.Add(new HttpResourceResponseElement(data, offset, size));
                return;
            }

            int n;

            // try last buffer
            if (_lastBuffer != null)
            {
                n       = _lastBuffer.Append(data, offset, size);
                size   -= n;
                offset += n;
            }

            // do other buffers if needed
            while (size > 0)
            {
                _lastBuffer = new HttpResponseBufferElement();
                _buffers.Add(_lastBuffer);
                n       = _lastBuffer.Append(data, offset, size);
                offset += n;
                size   -= n;
            }
        }
        internal void Filter(bool finalFiltering)
        {
            // no filter?
            if (_installedFilter == null)
            {
                return;
            }

            // flush char buffer and remember old buffers
            if (_charBufferLength != _charBufferFree)
            {
                FlushCharBuffer(true);
            }

            _lastBuffer = null;

            // no content to filter
            if (_buffers.Count == 0)
            {
                return;
            }

            // remember old buffers
            ArrayList oldBuffers = _buffers;

            _buffers = new ArrayList();

            // push old buffer list through the filter

            Debug.Assert(_filterSink != null);

            _filterSink.Filtering = true;

            try {
                int n = oldBuffers.Count;
                for (int i = 0; i < n; i++)
                {
                    IHttpResponseElement buf = (IHttpResponseElement)oldBuffers[i];

                    int len = buf.GetSize();

                    if (len > 0)
                    {
                        _installedFilter.Write(buf.GetBytes(), 0, len);
                    }
                }

                _installedFilter.Flush();

                if (finalFiltering)
                {
                    _installedFilter.Close();
                }
            }
            finally {
                _filterSink.Filtering = false;
            }
        }
 private static CachedRawResponse Convert(OutputCacheEntry oce)
 {
     ArrayList headers = null;
     if ((oce.HeaderElements != null) && (oce.HeaderElements.Count > 0))
     {
         headers = new ArrayList(oce.HeaderElements.Count);
         for (int i = 0; i < oce.HeaderElements.Count; i++)
         {
             HttpResponseHeader header = new HttpResponseHeader(oce.HeaderElements[i].Name, oce.HeaderElements[i].Value);
             headers.Add(header);
         }
     }
     ArrayList buffers = null;
     if ((oce.ResponseElements != null) && (oce.ResponseElements.Count > 0))
     {
         buffers = new ArrayList(oce.ResponseElements.Count);
         for (int j = 0; j < oce.ResponseElements.Count; j++)
         {
             ResponseElement element = oce.ResponseElements[j];
             IHttpResponseElement element2 = null;
             if (element is FileResponseElement)
             {
                 HttpContext current = HttpContext.Current;
                 HttpWorkerRequest request = (current != null) ? current.WorkerRequest : null;
                 bool supportsLongTransmitFile = (request != null) && request.SupportsLongTransmitFile;
                 bool isImpersonating = ((current != null) && current.IsClientImpersonationConfigured) || HttpRuntime.IsOnUNCShareInternal;
                 FileResponseElement element3 = (FileResponseElement) element;
                 element2 = new HttpFileResponseElement(element3.Path, element3.Offset, element3.Length, isImpersonating, supportsLongTransmitFile);
             }
             else if (element is MemoryResponseElement)
             {
                 MemoryResponseElement element4 = (MemoryResponseElement) element;
                 int size = System.Convert.ToInt32(element4.Length);
                 element2 = new HttpResponseBufferElement(element4.Buffer, size);
             }
             else
             {
                 if (!(element is SubstitutionResponseElement))
                 {
                     throw new NotSupportedException();
                 }
                 SubstitutionResponseElement element5 = (SubstitutionResponseElement) element;
                 element2 = new HttpSubstBlockResponseElement(element5.Callback);
             }
             buffers.Add(element2);
         }
     }
     else
     {
         buffers = new ArrayList();
     }
     return new CachedRawResponse(new HttpRawResponse(oce.StatusCode, oce.StatusDescription, headers, buffers, false), oce.Settings, oce.KernelCacheUrl, oce.CachedVaryId);
 }
        internal void WriteFile(IntPtr fileHandle, long offset, long size)
        {
            if (_charBufferLength != _charBufferFree)
            {
                FlushCharBuffer(true);
            }

            _lastBuffer = null;
            _buffers.Add(new HttpFileResponseElement(fileHandle, offset, size));

            if (!_responseBufferingOn)
            {
                _response.Flush();
            }
        }
        internal HttpWriter(HttpResponse response)
        {
            _response = response;
            _stream   = new HttpResponseStream(this);

            _buffers    = new ArrayList();
            _lastBuffer = null;

            _charBuffer       = (char[])s_Allocator.GetBuffer();
            _charBufferLength = _charBuffer.Length;
            _charBufferFree   = _charBufferLength;

            UpdateResponseBuffering();
            UpdateResponseEncoding();
        }
        private void FlushCharBuffer(bool flushEncoder)
        {
            int numChars = _charBufferLength - _charBufferFree;

            Debug.Assert(numChars > 0);

            // remember that response required encoding (to indicate the charset= is needed)
            _responseEncodingUsed = true;

            // estimate conversion size
            int estByteSize = _responseEncoding.GetMaxByteCount(numChars);
            int realByteSize;

            if (estByteSize <= BufferingParams.MAX_BYTES_TO_COPY || !_responseBufferingOn)
            {
                // small size -- allocate intermediate buffer and copy into the output buffer
                byte[] byteBuffer = new byte[estByteSize];
                realByteSize = _responseEncoder.GetBytes(_charBuffer, 0, numChars,
                                                         byteBuffer, 0, flushEncoder);
                BufferData(byteBuffer, 0, realByteSize, false);
            }
            else
            {
                // convert right into the output buffer

                int free = (_lastBuffer != null) ? _lastBuffer.FreeBytes : 0;

                if (free < estByteSize)
                {
                    // need new buffer -- last one doesn't have enough space
                    _lastBuffer = new HttpResponseBufferElement();
                    _buffers.Add(_lastBuffer);
                    free = _lastBuffer.FreeBytes;
                }

                // byte buffers must be long enough to keep everything in char buffer
                Debug.Assert(free >= estByteSize);

                realByteSize = _responseEncoder.GetBytes(_charBuffer, 0, numChars,
                                                         _lastBuffer.ByteBuffer, _lastBuffer.ByteOffset, flushEncoder);
                _lastBuffer.FreeBytes = free - realByteSize;
            }

            _charBufferFree = _charBufferLength;
        }
        //
        //  Snapshot for caching
        //

        internal ArrayList GetSnapshot(out bool hasSubstBlocks)
        {
            if (_charBufferLength != _charBufferFree)
            {
                FlushCharBuffer(true);
            }

            _lastBuffer = null; // to make sure nothing gets appended after

            hasSubstBlocks = false;

            ArrayList buffers = new ArrayList();

            // copy buffer references to the returned list, make non-recyclable
            int n = _buffers.Count;

            for (int i = 0; i < n; i++)
            {
                Object responseElement = _buffers[i];

                HttpResponseBufferElement buffer = responseElement as HttpResponseBufferElement;

                if (buffer != null)
                {
                    if (buffer.FreeBytes > BufferingParams.MAX_FREE_BYTES_TO_CACHE)
                    {
                        // copy data if too much is free
                        responseElement = buffer.Clone();
                    }
                    else
                    {
                        // cache the buffer as is with free bytes
                        buffer.DisableRecycling();
                    }
                }
                else if (responseElement is HttpSubstBlockResponseElement)
                {
                    hasSubstBlocks = true;
                }

                buffers.Add(responseElement);
            }
            return(buffers);
        }
        //
        // Support for substitution blocks
        //

        internal void WriteSubstBlock(String name, String defaultValue)
        {
            if (_charBufferLength != _charBufferFree)
            {
                FlushCharBuffer(true);
            }

            _lastBuffer = null;

            // convert filler to byte array bytes
            int numChars    = defaultValue.Length;
            int maxNumBytes = _responseEncoding.GetMaxByteCount(numChars);

            byte[] fillerBytes = new byte[maxNumBytes];
            int    numBytes    = _responseEncoder.GetBytes(defaultValue.ToCharArray(), 0, numChars, fillerBytes, 0, true);

            // add new substitution block to the buffer list
            _buffers.Add(new HttpSubstBlockResponseElement(name, fillerBytes, numBytes));
        }
        internal void MakeSubstitution(String name, String value, bool canChangeSize)
        {
            // find the block by name
            int i = FindSubstitutionBlock(name);

            if (i < 0)
            {
                return;
            }
            HttpSubstBlockResponseElement block = (HttpSubstBlockResponseElement)_buffers[i];

            // allocate byte array
            int size     = block.GetSize();
            int maxBytes = _responseEncoding.GetMaxByteCount(value.Length);

            if (maxBytes < size)
            {
                maxBytes = size;
            }
            byte[] bytes = new byte[maxBytes];

            // prefill with filler
            System.Array.Copy(block.Data, bytes, size);

            // convert string
            int newSize = _responseEncoder.GetBytes(value.ToCharArray(), 0, value.Length, bytes, 0, true);

            // adjust size if allowed
            if (canChangeSize)
            {
                size = newSize;
            }

            // replace substitution block with memory block
            _buffers[i] = new HttpResponseBufferElement(bytes, size);
        }
        private static CachedRawResponse Convert(OutputCacheEntry oce) {            
            ArrayList headers = null;
            if (oce.HeaderElements != null && oce.HeaderElements.Count > 0) {
                headers = new ArrayList(oce.HeaderElements.Count);
                for (int i = 0; i < oce.HeaderElements.Count; i++) {
                    HttpResponseHeader h = new HttpResponseHeader(oce.HeaderElements[i].Name, oce.HeaderElements[i].Value);
                    headers.Add(h);
                }                
            }

            ArrayList buffers = null;
            if (oce.ResponseElements != null && oce.ResponseElements.Count > 0) {
                buffers = new ArrayList(oce.ResponseElements.Count);
                for (int i = 0; i < oce.ResponseElements.Count; i++) {
                    ResponseElement re = oce.ResponseElements[i];
                    IHttpResponseElement elem = null;
                    if (re is FileResponseElement) {
                        HttpContext context = HttpContext.Current;
                        HttpWorkerRequest wr = (context != null) ? context.WorkerRequest : null;
                        bool supportsLongTransmitFile = (wr != null && wr.SupportsLongTransmitFile);
                        bool isImpersonating = ((context != null && context.IsClientImpersonationConfigured) || HttpRuntime.IsOnUNCShareInternal);
                        FileResponseElement fre = (FileResponseElement)re;

                        // DevDiv #21203: Need to verify permission to access the requested file since handled by native code.
                        HttpRuntime.CheckFilePermission(fre.Path);

                        elem = new HttpFileResponseElement(fre.Path, fre.Offset, fre.Length, isImpersonating, supportsLongTransmitFile);
                    }
                    else if (re is MemoryResponseElement) {
                        MemoryResponseElement mre = (MemoryResponseElement)re;
                        int size = System.Convert.ToInt32(mre.Length);
                        elem = new HttpResponseBufferElement(mre.Buffer, size);
                    }
                    else if (re is SubstitutionResponseElement) {
                        SubstitutionResponseElement sre = (SubstitutionResponseElement)re;
                        elem = new HttpSubstBlockResponseElement(sre.Callback);                        
                    }
                    else {
                        throw new NotSupportedException();
                    }
                    buffers.Add(elem);
                }
            }
            else {
                buffers = new ArrayList();
            }
            
            HttpRawResponse rawResponse = new HttpRawResponse(oce.StatusCode, oce.StatusDescription, headers, buffers, false /*hasSubstBlocks*/);
            CachedRawResponse cachedRawResponse = new CachedRawResponse(rawResponse, oce.Settings, oce.KernelCacheUrl, oce.CachedVaryId);

            return cachedRawResponse;
        }