/// <summary> /// Remove filter from specified memorystream. /// </summary> /// <param name="m"></param> /// <remarks>Filter data must not be more than 2GB (Signed integer max)</remarks> /// <returns></returns> public static Object RemoveFilter(FilteredData filteredData) { BinaryFormatter formatter = new BinaryFormatter(); MemoryStream[] bodyStream = new MemoryStream[2] { new MemoryStream(), new MemoryStream() }; Object returnVal = null; // Parse filter data int i = 0; for (string filterName = Utility.GetStringByZeroTarminatedChar(filteredData.Filter); filterName != typeof(BaseFilter).ToString() && i < LocalConfig.MaxFilterCount; i++, filterName = Utility.GetStringByZeroTarminatedChar(filteredData.Filter)) { if (!IOFilterFactory.Instance.ContainsIOFilter(filterName)) { bodyStream[0].Close(); bodyStream[1].Close(); throw new NoCorrespondingFilterFoundException(filterName); } // Get filter instance IOFilterBase filter = IOFilterFactory.Instance.GetIOFilter(filterName); // Setup MemoryStream bodyStream[i % 2] = new MemoryStream(filteredData.data); // Remove filter here filter.InputFilter(ref bodyStream[i % 2], ref bodyStream[(i + 1) % 2]); // Get filter object bodyStream[(i + 1) % 2].Position = 0; BinaryReader reader = new BinaryReader(bodyStream[(i + 1) % 2]); filteredData.Filter = reader.ReadChars(LocalConfig.FilterNameFixedLength); if (bodyStream[(i + 1) % 2].Length > Int32.MaxValue) throw new OverflowException(); // When byte length is larger than intergar max value, throw exception. filteredData.data = reader.ReadBytes((int)bodyStream[(i + 1) % 2].Length); // The line below is not nice but in .NET Framework 3.5, when BinaryReader is Closed(), its BaseStream will be also Closed() so the line below is given in order to preserve original base stream content. bodyStream[(i + 1) % 2] = new MemoryStream(bodyStream[(i + 1) % 2].ToArray()); reader.Close(); // Reset MemoryStream bodyStream[i % 2].Close(); bodyStream[i % 2] = new MemoryStream(); } try { bodyStream[(i + 1) % 2] = new MemoryStream(filteredData.data); returnVal = formatter.Deserialize(bodyStream[(i + 1) % 2]); } catch (Exception e) { throw e; } finally { bodyStream[0].Close(); bodyStream[1].Close(); } return returnVal; }
/// <summary> /// Apply filter to specified object. /// </summary> /// <param name="obj">Data to be filtered</param> /// <param name="filterOrder">Order to apply filter. filterOrder[0] is applied at first and filterOrder[lastindex] is applied at last.</param> /// <returns></returns> public static FilteredData ApplyFilter(Object obj, List<string> filterOrder) { MemoryStream[] bodyStream = new MemoryStream[] { new MemoryStream(), new MemoryStream() }; BinaryFormatter formatter = new BinaryFormatter(); // Convert password data object to binary data stream formatter.Serialize(bodyStream[0], obj); bodyStream[0].Position = 0; List<string> order = new List<string>(); order.Add(typeof(BaseFilter).ToString()); order.AddRange(filterOrder); // Apply data filters // NoFilter must come first for filtering. This is why do-while statement is using instead of while or for statement int i = 0; FilteredData filteredData = new FilteredData(); do { // Get filter name registered string filterName = order[i]; // Throw exception if associated filter instance does not exist if (!IOFilterFactory.Instance.ContainsIOFilter(filterName)) { bodyStream[0].Close(); bodyStream[1].Close(); throw new InvalidOperationException(); } // Get target filter instance IOFilterBase filter = IOFilterFactory.Instance.GetIOFilter(filterName); // Write filter name information Utility.GetCharTerminatedByZero(filterName, ref filteredData.Filter); // Do apply filter filter.OutputFilter(ref bodyStream[i % 2], ref bodyStream[(i + 1) % 2]); // Convert input as a filter does and write it to output stream bodyStream[(i + 1) % 2].Position = 0; // Set filtered data filteredData.data = bodyStream[(i + 1) % 2].ToArray(); // Set filter object into MemoryStream bodyStream[(i + 1) % 2].Close(); bodyStream[(i + 1) % 2] = new MemoryStream(); BinaryWriter writer = new BinaryWriter(bodyStream[(i + 1) % 2]); writer.Write(filteredData.Filter, 0, filteredData.Filter.Length); writer.Write(filteredData.data, 0, filteredData.data.Length); // The line below is not nice but in .NET Framework 3.5, when BinaryWriter is Closed(), its BaseStream will be also Closed() so the line below is given in order to preserve original base stream content. bodyStream[(i + 1) % 2] = new MemoryStream(bodyStream[(i + 1) % 2].ToArray()); writer.Close(); // Reset MemoryStream bodyStream[i % 2].Close(); // Release input stream resources bodyStream[i % 2] = new MemoryStream(); } while (++i < order.Count); // Convert FilteredData object into MemoryStream return filteredData; }