// Copyright © 2017 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace CefSharp.Example.Filters
{
///
/// Experimental filter that buffers all the data before any sort of processing
/// This has not been production tested, no performance analysis has been done.
/// The idea here being that we can buffer all the data, then perform some sort of
/// post processing (replacing/adding/removing text).
///
public class ExperimentalStreamResponseFilter : IResponseFilter
{
private List dataOutBuffer = new List();
bool IResponseFilter.InitFilter()
{
return true;
}
FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
{
if (dataIn == null)
{
dataInRead = 0;
dataOutWritten = 0;
var maxWrite = Math.Min(dataOutBuffer.Count, dataOut.Length);
//Write the maximum portion that fits in dataOut.
if (maxWrite > 0)
{
dataOut.Write(dataOutBuffer.ToArray(), 0, (int)maxWrite);
dataOutWritten += maxWrite;
}
//If dataOutBuffer is bigger than dataOut then we'll write the
// data on the second pass
if (maxWrite < dataOutBuffer.Count)
{
// Need to write more bytes than will fit in the output buffer.
// Remove the bytes that were written already
dataOutBuffer.RemoveRange(0, (int)(maxWrite - 1));
return FilterStatus.NeedMoreData;
}
//All data was written, so we clear the buffer and return FilterStatus.Done
dataOutBuffer.Clear();
return FilterStatus.Done;
}
//We're going to read all of dataIn
dataInRead = dataIn.Length;
var dataInBuffer = new byte[(int)dataIn.Length];
dataIn.Read(dataInBuffer, 0, dataInBuffer.Length);
//Add all the bytes to the dataOutBuffer
dataOutBuffer.AddRange(dataInBuffer);
dataOutWritten = 0;
//The assumption here is dataIn is smaller than dataOut then this will be the last of the
//data to read and we can start processing, this is not a production tested assumption
if (dataIn.Length < dataOut.Length)
{
var bytes = ReplaceTextInBufferedData(dataOutBuffer.ToArray());
//Clear the buffer and add the processed data, it's possible
//that with our processing the data has become to large to fit in dataOut
//So we'll have to write the data in multiple passes in that case
dataOutBuffer.Clear();
dataOutBuffer.AddRange(bytes);
var maxWrite = Math.Min(dataOutBuffer.Count, dataOut.Length);
//Write the maximum portion that fits in dataOut.
if (maxWrite > 0)
{
dataOut.Write(dataOutBuffer.ToArray(), 0, (int)maxWrite);
dataOutWritten += maxWrite;
}
//If dataOutBuffer is bigger than dataOut then we'll write the
// data on the second pass
if (maxWrite < dataOutBuffer.Count)
{
// Need to write more bytes than will fit in the output buffer.
// Remove the bytes that were written already
dataOutBuffer.RemoveRange(0, (int)(maxWrite - 1));
return FilterStatus.NeedMoreData;
}
//All data was written, so we clear the buffer and return FilterStatus.Done
dataOutBuffer.Clear();
return FilterStatus.Done;
}
else
{
//We haven't got all of our dataIn yet, so we keep buffering so that when it's finished
//we can process the buffer, replace some words etc and then write it all out.
return FilterStatus.NeedMoreData;
}
}
void IDisposable.Dispose()
{
}
///
/// If your copy and pasting this example, then this is the part your most likely to change
/// (unless your fixing a bug)
///
/// buffered data
/// post processed data, text added/replaced/etc
private byte[] ReplaceTextInBufferedData(byte[] bytes)
{
//NOTE: This is a quick and dirty example of manipulating the data as a string
//By all means contribute a better working example, this is good enough for my demo purpose at this point in time.
var dataString = Encoding.UTF8.GetString(bytes);
dataString = dataString.Replace("CefSharp", "CEF#");
return Encoding.UTF8.GetBytes(dataString);
}
}
}