/// <summary> /// Creates this object and sets all its properties /// </summary> /// <param name="storage">The OLE version 2.0 object as a <see cref="CFStorage" /></param> internal Ole10Native(CFStorage storage) { if (storage == null) throw new ArgumentNullException("storage"); var ole10Native = storage.GetStream("\x0001Ole10Native"); var compObj = storage.GetStream("\x0001CompObj"); var compObjStream = new CompObjStream(compObj); AnsiUserType = compObjStream.AnsiUserType; StringFormat = compObjStream.StringFormat; ClipboardFormat = compObjStream.ClipboardFormat; switch (compObjStream.AnsiUserType) { case "OLE Package": var ole10NativeSize = (int) ole10Native.Size - 4; var data = ole10Native.GetData(4, ref ole10NativeSize); var package = new Package(data); Format = package.Format; FileName = Path.GetFileName(package.FileName); FilePath = package.FilePath; NativeData = package.Data; break; case "PBrush": case "Pakket": // Ignore break; default: throw new OEObjectTypeNotSupported("Unsupported OleNative AnsiUserType '" + compObjStream.AnsiUserType + "' found"); } }
//[TestMethod] //public void Test_INCREMENTAL_TRANSACTED_CHANGE_CFS() //{ // Random r = new Random(); // for (int i = r.Next(1, 100); i < 1024 * 1024 * 70; i = i << 1) // { // SingleTransactedChange(i + r.Next(0, 3)); // } //} private void SingleTransactedChange(int size) { String filename = "INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS.cfs"; if (File.Exists(filename)) { File.Delete(filename); } CompoundFile cf = new CompoundFile(); CFStorage st = cf.RootStorage.AddStorage("MyStorage"); CFStream sm = st.AddStream("MyStream"); byte[] b = Helpers.GetBuffer(size); sm.SetData(b); cf.Save(filename); cf.Close(); CompoundFile cf2 = new CompoundFile(filename); CFStorage st2 = cf2.RootStorage.GetStorage("MyStorage"); CFStream sm2 = st2.GetStream("MyStream"); Assert.IsNotNull(sm2); Assert.IsTrue(sm2.Size == size); Assert.IsTrue(Helpers.CompareBuffer(sm2.GetData(), b)); cf2.Close(); }
public void Test_WRITE_AND_READ_CFS() { String filename = "WRITE_AND_READ_CFS.cfs"; CompoundFile cf = new CompoundFile(); CFStorage st = cf.RootStorage.AddStorage("MyStorage"); CFStream sm = st.AddStream("MyStream"); byte[] b = Helpers.GetBuffer(220, 0x0A); sm.SetData(b); cf.Save(filename); cf.Close(); CompoundFile cf2 = new CompoundFile(filename); CFStorage st2 = cf2.RootStorage.GetStorage("MyStorage"); CFStream sm2 = st2.GetStream("MyStream"); cf2.Close(); Assert.IsNotNull(sm2); Assert.IsTrue(sm2.Size == 220); if (File.Exists(filename)) { File.Delete(filename); } }
/// <summary> /// Reads the header record containing the size of the data. /// </summary> /// <param name="storage"> /// Storage key where to look for the Header stream. /// </param> /// <returns>Size of the Data section.</returns> internal static uint ReadHeader(CFStorage storage) { using (var header = storage.GetStream("Header").GetBinaryReader()) { return(header.ReadUInt32()); } }
public static string GetIQPDetailFromStream(CFStorage storage, string streamName) { CFStream IQPDetailStream = storage.GetStream(streamName); int IQPDetailSize = (int)IQPDetailStream.Size; byte[] IQPDetailBytes = IQPDetailStream.GetData(3, ref IQPDetailSize); return(Encoding.UTF8.GetString(IQPDetailBytes)); }
/// <summary> /// Creates this object and sets all its properties /// </summary> /// <param name="storage">The OLE version 2.0 object as a <see cref="CFStorage" /></param> internal Ole10Native(CFStorage storage) { if (storage == null) { throw new ArgumentNullException("storage"); } var ole10Native = storage.GetStream("\x0001Ole10Native"); var compObj = storage.GetStream("\x0001CompObj"); var compObjStream = new CompObjStream(compObj); AnsiUserType = compObjStream.AnsiUserType; StringFormat = compObjStream.StringFormat; ClipboardFormat = compObjStream.ClipboardFormat; switch (compObjStream.AnsiUserType) { case "OLE Package": var olePackageSize = (int)ole10Native.Size - 4; var olePackageData = new byte[olePackageSize]; ole10Native.Read(olePackageData, 4, olePackageSize); var package = new Package(olePackageData); Format = package.Format; FileName = Path.GetFileName(package.FileName); FilePath = package.FilePath; NativeData = package.Data; break; case "PBrush": var pbBrushSize = (int)ole10Native.Size - 4; var pbBrushData = new byte[pbBrushSize]; ole10Native.Read(pbBrushData, 4, pbBrushSize); FileName = "Embedded PBrush image.bmp"; Format = OleFormat.File; NativeData = pbBrushData; break; case "Pakket": // Ignore break; default: throw new OEObjectTypeNotSupported("Unsupported OleNative AnsiUserType '" + compObjStream.AnsiUserType + "' found"); } }
private _VBA_PROJECTStream ReadVbaProjectStream(CFStorage VBAStorage) { CFStream stream = VBAStorage.GetStream("_VBA_PROJECT"); Byte[] uncompressedData = stream.GetData(); var dataReader = new XlBinaryReader(ref uncompressedData); var result = new _VBA_PROJECTStream(dataReader); return(result); }
/// <summary> /// Получить ссылку на поток из файла MCDF по его пути /// </summary> /// <param name="file">Файл - хранилище</param> /// <param name="streamPath">Путь к потоку в файле</param> /// <returns></returns> public static CFStream GetFileStream(CompoundFile file, string streamPath) { string[] path = streamPath.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); CFStorage curDir = file.RootStorage; for (int i = 0; i < path.Length - 1; i++) { curDir = curDir.GetStorage(path[i]); } return(curDir.GetStream(path[path.Length - 1])); }
/// <summary> /// Creates this object and reads all the <see cref="StringStreamItem" /> objects /// from the given <paramref name="storage"/> /// </summary> /// <param name="storage">The <see cref="CFStorage"/> that contains the <see cref="PropertyTags.EntryStream"/></param> internal StringStream(CFStorage storage) { var stream = storage.GetStream(PropertyTags.StringStream); using (var memoryStream = new MemoryStream(stream.GetData())) using (var binaryReader = new BinaryReader(memoryStream)) while (!binaryReader.Eos()) { var stringStreamItem = new StringStreamItem(binaryReader); Add(stringStreamItem); } }
/// <summary> /// Creates this object and reads all the <see cref="Guid" /> objects from /// the given <paramref name="storage"/> /// </summary> /// <param name="storage">The <see cref="CFStorage"/> that containts the <see cref="PropertyTags.GuidStream"/></param> internal GuidStream(CFStorage storage) { var stream = storage.GetStream(PropertyTags.GuidStream); using (var memoryStream = new MemoryStream(stream.GetData())) using (var binaryReader = new BinaryReader(memoryStream)) while (!binaryReader.Eos()) { var guid = new Guid(binaryReader.ReadBytes(16)); Add(guid); } }
private CFStream GetStream(CFStorage cfstorage, string streamname) { CFStream stream = null; try { stream = cfstorage.GetStream(streamname); } catch (Exception) { } return(stream); }
/// <summary> /// Writes all the <see cref="Guid"/>'s as a <see cref="CFStream" /> to the /// given <paramref name="storage" /> /// </summary> /// <param name="storage">The <see cref="CFStorage" /></param> internal void Write(CFStorage storage) { var stream = storage.GetStream(PropertyTags.GuidStream); using (var memoryStream = new MemoryStream()) using (var binaryWriter = new BinaryWriter(memoryStream)) { foreach (var guid in this) { binaryWriter.Write(guid.ToByteArray()); } stream.SetData(memoryStream.ToArray()); } }
/// <summary> /// Writes all the <see cref="EntryStreamItem"/>'s as a <see cref="CFStream" /> to the /// given <paramref name="storage" /> /// </summary> /// <param name="storage">The <see cref="CFStorage" /></param> internal void Write(CFStorage storage) { var stream = storage.GetStream(PropertyTags.EntryStream); using (var memoryStream = new MemoryStream()) using (var binaryWriter = new BinaryWriter(memoryStream)) { foreach (var entryStreamItem in this) { entryStreamItem.Write(binaryWriter); } stream.SetData(memoryStream.ToArray()); } }
/// <summary> /// Adds a complete stream to the hash data. /// </summary> /// <param name="hashBuf">Current data to hash</param> /// <param name="streamName">Stream to hash</param> /// <param name="stg">Storage of the stream</param> private void AddStream(ICollection <byte[]> hashBuf, string streamName, CFStorage stg) { try { var stream = stg.GetStream(streamName); if (stream != null) { var data = stream.GetData(); hashBuf.Add(data); } } catch (CFItemNotFound) { _logger.Warn("Skipping non-existent Stream {0}.", streamName); } catch (Exception e) { _logger.Error(e, "Error reading data!"); _crashManager.Report(e, "vpt"); } }
/// <summary> /// Reads the component parameter information. /// </summary> /// <param name="componentStorage">Component footprint storage key.</param> /// <param name="component">Component instance where the parameters will be imported into.</param> private void ReadFootprintParameters(CFStorage componentStorage, PcbComponent component) { BeginContext("Parameters"); try { using (var reader = componentStorage.GetStream("Parameters").GetBinaryReader()) { var parameters = ReadBlock(reader, size => ReadParameters(reader, size)); component.ImportFromParameters(parameters); } } finally { EndContext(); } }
/// <summary> /// Reads the library data from the current file which contains the PCB library /// header information parameters and also a list of the existing components. /// </summary> /// <param name="library"></param> private void ReadLibraryData(CFStorage library) { using (var reader = library.GetStream("Data").GetBinaryReader()) { var parameters = ReadBlock(reader, size => ReadParameters(reader, size)); Data.Header.ImportFromParameters(parameters); var footprintCount = reader.ReadUInt32(); for (var i = 0; i < footprintCount; ++i) { var refName = ReadStringBlock(reader); var sectionKey = GetSectionKeyFromRefName(refName); Data.Items.Add(ReadFootprint(sectionKey)); } } }
public VPXFile(string filename) { _cf = new CompoundFile(filename, CFSUpdateMode.ReadOnly, CFSConfiguration.Default); CFStorage gameStg = _cf.RootStorage.GetStorage("GameStg"); UInt32 version = new VPXReader(gameStg.GetStream("Version")).ReadUInt32(); void visitor(CFItem item) { if (item.Name.StartsWith("Image") && item is CFStream stream) { ReadImage(stream, true); } } gameStg.VisitEntries(visitor, true); }
private bool ContainsPattern(CFStorage storage, string fileName) { var stream = storage.GetStream(fileName); var data = stream.GetData(); if (data.Length == 0) { Logger.Debug($"Ignoring \"{fileName}\", len: 0"); return(false); } foreach (var pattern in _masks) { try { var target = GetLnkTarget(data); if (target.ToLowerInvariant().StartsWith(pattern.ToLowerInvariant())) { Logger.Debug($"Target \"{target}\" matches pattern \"{pattern}\""); return(true); } else if (string.Empty.Equals(target)) { Logger.Debug($"Target \"{target}\" ignored, not a lnk file"); } } catch (System.Runtime.InteropServices.COMException ex) { if (LinkUtil.IsMissingDriveException(ex)) { Logger.Debug($"Target drive does not exist, marking for deletion"); return(true); } else { Logger.Debug($"Target ignored, not a lnk file"); } } /*if (ContainsSubstring(data, pattern)) { * return true; * }*/ } return(false); }
static void CopyCfStreamsExcept(CFStorage src, CFStorage dest, string excludeName) { src.VisitEntries(i => { if (i.Name?.Equals(excludeName, StringComparison.InvariantCultureIgnoreCase) ?? false) { return; } if (i.IsStorage) { dest.AddStorage(i.Name); CopyCfStreamsExcept((CFStorage)i, dest.GetStorage(i.Name), null); } else { dest.AddStream(i.Name); dest.GetStream(i.Name).SetData(((CFStream)i).GetData()); } }, false); }
public void Test_CHECK_DISPOSED_() { const String FILENAME = "MultipleStorage.cfs"; CompoundFile cf = new CompoundFile(FILENAME); CFStorage st = cf.RootStorage.GetStorage("MyStorage"); cf.Close(); try { byte[] temp = st.GetStream("MyStream").GetData(); Assert.Fail("Stream without media"); } catch (Exception ex) { Assert.IsTrue(ex is CFDisposedException); } }
public void Test_WRITE_AND_READ_CFS_VERSION_4() { String filename = "WRITE_AND_READ_CFS_V4.cfs"; CompoundFile cf = new CompoundFile(CFSVersion.Ver_4, CFSConfiguration.EraseFreeSectors | CFSConfiguration.SectorRecycle); CFStorage st = cf.RootStorage.AddStorage("MyStorage"); CFStream sm = st.AddStream("MyStream"); byte[] b = new byte[220]; sm.SetData(b); cf.Save(filename); cf.Close(); CompoundFile cf2 = new CompoundFile(filename); CFStorage st2 = cf2.RootStorage.GetStorage("MyStorage"); CFStream sm2 = st2.GetStream("MyStream"); Assert.IsNotNull(sm2); Assert.IsTrue(sm2.Size == 220); cf2.Close(); }
public void Test_WRITE_READ_CFS_VERSION_4_STREAM() { String filename = "WRITE_COMMIT_READ_CFS_V4.cfs"; CompoundFile cf = new CompoundFile(CFSVersion.Ver_4, CFSConfiguration.SectorRecycle | CFSConfiguration.EraseFreeSectors); CFStorage st = cf.RootStorage.AddStorage("MyStorage"); CFStream sm = st.AddStream("MyStream"); byte[] b = Helpers.GetBuffer(227); sm.SetData(b); cf.Save(filename); cf.Close(); CompoundFile cf2 = new CompoundFile(filename); CFStorage st2 = cf2.RootStorage.GetStorage("MyStorage"); CFStream sm2 = st2.GetStream("MyStream"); Assert.IsNotNull(sm2); Assert.IsTrue(sm2.Size == b.Length); cf2.Close(); }
private void SingleWriteReadMatchingSTREAMED(int size) { MemoryStream ms = new MemoryStream(size); CompoundFile cf = new CompoundFile(); CFStorage st = cf.RootStorage.AddStorage("MyStorage"); CFStream sm = st.AddStream("MyStream"); byte[] b = Helpers.GetBuffer(size); sm.SetData(b); cf.Save(ms); cf.Close(); CompoundFile cf2 = new CompoundFile(ms); CFStorage st2 = cf2.RootStorage.GetStorage("MyStorage"); CFStream sm2 = st2.GetStream("MyStream"); Assert.IsNotNull(sm2); Assert.IsTrue(sm2.Size == size); Assert.IsTrue(Helpers.CompareBuffer(sm2.GetData(), b)); cf2.Close(); }
/// <summary> /// When a Excel document is embedded in for example a Word document the Workbook /// is set to hidden. Don't know why Microsoft does this but they do. To solve this /// problem we seek the WINDOW1 record in the BOF record of the stream. In there a /// gbit structure is located. The first bit in this structure controls the visibility /// of the workbook, so we check if this bit is set to 1 (hidden) and if so set it to 0. /// Normally a Workbook stream only contains one WINDOW record but when it is embedded /// it will contain 2 or more records. /// </summary> /// <param name="rootStorage">The <see cref="CFStorage">Root storage</see> of a <see cref="CompoundFile"/></param> /// <exception cref="OEFileIsCorrupt">Raised when the <paramref name="rootStorage"/> does not have a Workbook stream</exception> public static void SetWorkbookVisibility(CFStorage rootStorage) { if (!rootStorage.ExistsStream("WorkBook")) { throw new OEFileIsCorrupt("Could not check workbook visibility because the WorkBook stream is not present"); } try { var stream = rootStorage.GetStream("WorkBook") as CFStream; if (stream == null) { return; } var bytes = stream.GetData(); using (var memoryStream = new MemoryStream(bytes)) using (var binaryReader = new BinaryReader(memoryStream)) { // Get the record type, at the beginning of the stream this should always be the BOF var recordType = binaryReader.ReadUInt16(); var recordLength = binaryReader.ReadUInt16(); // Something seems to be wrong, we would expect a BOF but for some reason it isn't if (recordType != 0x809) { throw new OEFileIsCorrupt("The file is corrupt"); } binaryReader.BaseStream.Position += recordLength; while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length) { recordType = binaryReader.ReadUInt16(); recordLength = binaryReader.ReadUInt16(); // Window1 record (0x3D) if (recordType == 0x3D) { // ReSharper disable UnusedVariable var xWn = binaryReader.ReadUInt16(); var yWn = binaryReader.ReadUInt16(); var dxWn = binaryReader.ReadUInt16(); var dyWn = binaryReader.ReadUInt16(); // ReSharper restore UnusedVariable // The grbit contains the bit that hides the sheet var grbit = binaryReader.ReadBytes(2); var bitArray = new BitArray(grbit); // When the bit is set then unset it (bitArray.Get(0) == true) if (bitArray.Get(0)) { bitArray.Set(0, false); // Copy the byte back into the stream, 2 positions back so that we overwrite the old bytes bitArray.CopyTo(bytes, (int)binaryReader.BaseStream.Position - 2); } break; } binaryReader.BaseStream.Position += recordLength; } } stream.SetData(bytes); } catch (Exception exception) { throw new OEFileIsCorrupt( "Could not check workbook visibility because the file seems to be corrupt", exception); } }
/// <summary> /// When a Excel document is embedded in for example a Word document the Workbook /// is set to hidden. Don't know why Microsoft does this but they do. To solve this /// problem we seek the WINDOW1 record in the BOF record of the stream. In there a /// gbit structure is located. The first bit in this structure controls the visibility /// of the workbook, so we check if this bit is set to 1 (hidden) en is so set it to 0. /// Normally a Workbook stream only contains one WINDOW record but when it is embedded /// it will contain 2 or more records. /// </summary> /// <param name="rootStorage">The <see cref="CFStorage">Root storage</see> of a <see cref="CompoundFile"/></param> /// <exception cref="OEFileIsCorrupt">Raised when the <paramref name="rootStorage"/> does not have a Workbook stream</exception> public static void SetWorkbookVisibility(CFStorage rootStorage) { if (!rootStorage.ExistsStream("WorkBook")) throw new OEFileIsCorrupt("Could not check workbook visibility because the WorkBook stream is not present"); try { var stream = rootStorage.GetStream("WorkBook") as CFStream; if (stream == null) return; var bytes = stream.GetData(); using (var memoryStream = new MemoryStream(bytes)) using (var binaryReader = new BinaryReader(memoryStream)) { // Get the record type, at the beginning of the stream this should always be the BOF var recordType = binaryReader.ReadUInt16(); var recordLength = binaryReader.ReadUInt16(); // Something seems to be wrong, we would expect a BOF but for some reason it isn't if (recordType != 0x809) throw new OEFileIsCorrupt("The file is corrupt"); binaryReader.BaseStream.Position += recordLength; while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length) { recordType = binaryReader.ReadUInt16(); recordLength = binaryReader.ReadUInt16(); // Window1 record (0x3D) if (recordType == 0x3D) { // ReSharper disable UnusedVariable var xWn = binaryReader.ReadUInt16(); var yWn = binaryReader.ReadUInt16(); var dxWn = binaryReader.ReadUInt16(); var dyWn = binaryReader.ReadUInt16(); // ReSharper restore UnusedVariable // The grbit contains the bit that hides the sheet var grbit = binaryReader.ReadBytes(2); var bitArray = new BitArray(grbit); // When the bit is set then unset it (bitArray.Get(0) == true) if (bitArray.Get(0)) { bitArray.Set(0, false); // Copy the byte back into the stream, 2 positions back so that we overwrite the old bytes bitArray.CopyTo(bytes, (int)binaryReader.BaseStream.Position - 2); } break; } binaryReader.BaseStream.Position += recordLength; } } stream.SetData(bytes); } catch (Exception exception) { throw new OEFileIsCorrupt( "Could not check workbook visibility because the file seems to be corrupt", exception); } }
static bool CfStoragesAreDifferent(CFStorage s1, CFStorage s2, out string explain) { var s1Names = new List <Tuple <string, bool> >(); var s2Names = new List <Tuple <string, bool> >(); s1.VisitEntries(i => s1Names.Add(Tuple.Create(i.Name, i.IsStorage)), false); s2.VisitEntries(i => s2Names.Add(Tuple.Create(i.Name, i.IsStorage)), false); s1Names.Sort(); s2Names.Sort(); if (!s1Names.SequenceEqual(s2Names)) { explain = $"Different file lists in storage '{s1.Name}'.\r\nFile 1: {{'{string.Join("', '", s1Names)}'}}\r\nFile 2: {{'{string.Join("'', '", s2Names)}'}}."; return(true); } FormControl fc1 = null; foreach (var t in s1Names) { if (t.Item2) { if (CfStoragesAreDifferent(s1.GetStorage(t.Item1), s2.GetStorage(t.Item1), out explain)) { return(true); } } else if (t.Item1 == "f") { fc1 = new FormControl(s1.GetStream("f").GetData()); var fc2 = new FormControl(s2.GetStream("f").GetData()); if (!fc1.Equals(fc2)) { explain = $"Different contents of stream 'f' in storage '{s1.Name}'."; return(true); } } else if (t.Item1 == "o" && fc1 != null) { var o1 = s1.GetStream("o").GetData(); var o2 = s2.GetStream("o").GetData(); uint idx = 0; foreach (var site in fc1.Sites) { explain = $"Different contents of stream 'o', site '{site.Name}' in storage '{s1.Name}'."; var o1Range = o1.Range(idx, site.ObjectStreamSize); var o2Range = o2.Range(idx, site.ObjectStreamSize); switch (site.ClsidCacheIndex) { case 15: // MorphData case 26: // CheckBox case 25: // ComboBox case 24: // ListBox case 27: // OptionButton case 23: // TextBox case 28: // ToggleButton if (!new MorphDataControl(o1Range).Equals(new MorphDataControl(o2Range))) { return(true); } break; case 17: // CommandButton if (!new CommandButtonControl(o1Range).Equals(new CommandButtonControl(o2Range))) { return(true); } break; case 21: // Label if (!new LabelControl(o1Range).Equals(new LabelControl(o2Range))) { return(true); } break; default: if (!o1Range.SequenceEqual(o2Range)) { return(true); } break; } idx += site.ObjectStreamSize; } } else if (!s1.GetStream(t.Item1).GetData().SequenceEqual(s2.GetStream(t.Item1).GetData())) { explain = $"Different contents of stream '{t.Item1}' in storage '{s1.Name}'."; return(true); } } explain = "No differences found."; return(false); }
static public void Main(string[] args) { // List of target VBA modules to stomp, if empty => all modules will be stomped List <string> targetModules = new List <string>(); // Filename that contains the VBA code used for substitution string VBASourceFileName = ""; // Target MS Office version for pcode string targetOfficeVersion = ""; // Option to hide modules from VBA editor GUI bool optionHideInGUI = false; // Option to start web server to serve malicious template int optionWebserverPort = 0; // Option to display help bool optionShowHelp = false; // File format is OpenXML (docm or xlsm) bool is_OpenXML = false; // Option to delete metadata from file bool optionDeleteMetadata = false; // Option to set random module names in dir stream bool optionSetRandomNames = false; // Temp path to unzip OpenXML files to String unzipTempPath = ""; // Start parsing command line arguments var p = new OptionSet() { { "n|name=", "The target module name to stomp.\n" + "This argument can be repeated.", v => targetModules.Add(v) }, { "s|sourcefile=", "File containing substitution VBA code (fake code).", v => VBASourceFileName = v }, { "g|guihide", "Hide code from VBA editor GUI.", v => optionHideInGUI = v != null }, { "t|targetversion=", "Target MS Office version the pcode will run on.", v => targetOfficeVersion = v }, { "w|webserver=", "Start web server on specified port to serve malicious template.", (int v) => optionWebserverPort = v }, { "d|delmetadata", "Remove metadata stream (may include your name etc.).", v => optionDeleteMetadata = v != null }, { "r|randomnames", "Set random module names, confuses some analyst tools.", v => optionSetRandomNames = v != null }, { "v", "Increase debug message verbosity.", v => { if (v != null) { ++verbosity; } } }, { "h|help", "Show this message and exit.", v => optionShowHelp = v != null }, }; List <string> extra; try { extra = p.Parse(args); } catch (OptionException e) { Console.WriteLine(e.Message); Console.WriteLine("Try '--help' for more information."); return; } if (extra.Count > 0) { filename = string.Join(" ", extra.ToArray()); } else { optionShowHelp = true; } if (optionShowHelp) { ShowHelp(p); return; } // End parsing command line arguments // OLE Filename (make a copy so we don't overwrite the original) string outFilename = getOutFilename(filename); string oleFilename = outFilename; // Attempt to unzip as docm or xlsm OpenXML format try { unzipTempPath = CreateUniqueTempDirectory(); ZipFile.ExtractToDirectory(filename, unzipTempPath); if (File.Exists(Path.Combine(unzipTempPath, "word", "vbaProject.bin"))) { oleFilename = Path.Combine(unzipTempPath, "word", "vbaProject.bin"); } else if (File.Exists(Path.Combine(unzipTempPath, "xl", "vbaProject.bin"))) { oleFilename = Path.Combine(unzipTempPath, "xl", "vbaProject.bin"); } is_OpenXML = true; } catch (Exception) { // Not OpenXML format, Maybe 97-2003 format, Make a copy if (File.Exists(outFilename)) { File.Delete(outFilename); } File.Copy(filename, outFilename); } // Open OLE compound file for editing try { cf = new CompoundFile(oleFilename, CFSUpdateMode.Update, 0); } catch (Exception e) { Console.WriteLine("ERROR: Could not open file " + filename); Console.WriteLine("Please make sure this file exists and is .docm or .xlsm file or a .doc in the Office 97-2003 format."); Console.WriteLine(); Console.WriteLine(e.Message); return; } // Read relevant streams CFStorage commonStorage = cf.RootStorage; // docm or xlsm if (cf.RootStorage.TryGetStorage("Macros") != null) { commonStorage = cf.RootStorage.GetStorage("Macros"); // .doc } if (cf.RootStorage.TryGetStorage("_VBA_PROJECT_CUR") != null) { commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR"); // xls } vbaProjectStream = commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").GetData(); projectStream = commonStorage.GetStream("project").GetData(); dirStream = Decompress(commonStorage.GetStorage("VBA").GetStream("dir").GetData()); // Read project stream as string string projectStreamString = System.Text.Encoding.UTF8.GetString(projectStream); // Find all VBA modules in current file List <ModuleInformation> vbaModules = ParseModulesFromDirStream(dirStream); // Write streams to debug log (if verbosity enabled) DebugLog("Hex dump of original _VBA_PROJECT stream:\n" + Utils.HexDump(vbaProjectStream)); DebugLog("Hex dump of original dir stream:\n" + Utils.HexDump(dirStream)); DebugLog("Hex dump of original project stream:\n" + Utils.HexDump(projectStream)); // Replace Office version in _VBA_PROJECT stream if (targetOfficeVersion != "") { ReplaceOfficeVersionInVBAProject(vbaProjectStream, targetOfficeVersion); commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").SetData(vbaProjectStream); } // Hide modules from GUI if (optionHideInGUI) { foreach (var vbaModule in vbaModules) { if ((vbaModule.moduleName != "ThisDocument") && (vbaModule.moduleName != "ThisWorkbook")) { Console.WriteLine("Hiding module: " + vbaModule.moduleName); projectStreamString = projectStreamString.Replace("Module=" + vbaModule.moduleName, ""); } } // Write changes to project stream commonStorage.GetStream("project").SetData(Encoding.UTF8.GetBytes(projectStreamString)); } // Stomp VBA modules if (VBASourceFileName != "") { byte[] streamBytes; foreach (var vbaModule in vbaModules) { DebugLog("VBA module name: " + vbaModule.moduleName + "\nOffset for code: " + vbaModule.textOffset); // If this module is a target module, or if no targets are specified, then stomp if (targetModules.Contains(vbaModule.moduleName) || !targetModules.Any()) { Console.WriteLine("Now stomping VBA code in module: " + vbaModule.moduleName); streamBytes = commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).GetData(); DebugLog("Existing VBA source:\n" + GetVBATextFromModuleStream(streamBytes, vbaModule.textOffset)); // Get new VBA source code from specified text file. If not specified, VBA code is removed completely. string newVBACode = ""; if (VBASourceFileName != "") { try { newVBACode = System.IO.File.ReadAllText(VBASourceFileName); } catch (Exception e) { Console.WriteLine("ERROR: Could not open VBA source file " + VBASourceFileName); Console.WriteLine("Please make sure this file exists and contains ASCII only characters."); Console.WriteLine(); Console.WriteLine(e.Message); return; } } DebugLog("Replacing with VBA code:\n" + newVBACode); streamBytes = ReplaceVBATextInModuleStream(streamBytes, vbaModule.textOffset, newVBACode); DebugLog("Hex dump of VBA module stream " + vbaModule.moduleName + ":\n" + Utils.HexDump(streamBytes)); commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).SetData(streamBytes); } } } // Set random ASCII names for VBA modules in dir stream if (optionSetRandomNames) { Console.WriteLine("Setting random ASCII names for VBA modules in dir stream (while leaving unicode names intact)."); // Recompress and write to dir stream commonStorage.GetStorage("VBA").GetStream("dir").SetData(Compress(SetRandomNamesInDirStream(dirStream))); } // Delete metadata from document if (optionDeleteMetadata) { try { cf.RootStorage.Delete("\u0005SummaryInformation"); } catch (Exception e) { Console.WriteLine("ERROR: metadata stream does not exist (option ignored)"); DebugLog(e.Message); } } // Commit changes and close file cf.Commit(); cf.Close(); // Purge unused space in file CompoundFile.ShrinkCompoundFile(oleFilename); // Zip the file back up as a docm or xlsm if (is_OpenXML) { if (File.Exists(outFilename)) { File.Delete(outFilename); } ZipFile.CreateFromDirectory(unzipTempPath, outFilename); // Delete Temporary Files Directory.Delete(unzipTempPath, true); } // Start web server, if option is specified if (optionWebserverPort != 0) { try { WebServer ws = new WebServer(SendFile, "http://*:" + optionWebserverPort.ToString() + "/"); ws.Run(); Console.WriteLine("Webserver starting on port " + optionWebserverPort.ToString() + ". Press a key to quit."); Console.ReadKey(); ws.Stop(); Console.WriteLine("Webserver closed. Goodbye!"); } catch (Exception e) { Console.WriteLine("ERROR: could not start webserver on specified port"); DebugLog(e.Message); } } }
private static bool CfStoragesAreDifferent(CFStorage s1, CFStorage s2, out string explain) { var s1Names = new List <Tuple <string, bool> >(); var s2Names = new List <Tuple <string, bool> >(); s1.VisitEntries(i => s1Names.Add(Tuple.Create(i.Name, i.IsStorage)), false); s2.VisitEntries(i => s2Names.Add(Tuple.Create(i.Name, i.IsStorage)), false); s1Names.Sort(); s2Names.Sort(); if (!s1Names.SequenceEqual(s2Names)) { explain = string.Format(VBASyncResources.ExplainFrxDifferentFileLists, s1.Name, string.Join("', '", s1Names.Select(t => t.Item1)), string.Join("', '", s2Names.Select(t => t.Item1))); return(true); } FormControl fc1 = null; foreach (var t in s1Names) { if (t.Item2) { if (CfStoragesAreDifferent(s1.GetStorage(t.Item1), s2.GetStorage(t.Item1), out explain)) { return(true); } } else if (t.Item1 == "f") { fc1 = new FormControl(s1.GetStream("f").GetData()); var fc2 = new FormControl(s2.GetStream("f").GetData()); if (!fc1.Equals(fc2)) { explain = string.Format(VBASyncResources.ExplainFrxGeneralStreamDifference, "f", s1.Name); return(true); } } else if (t.Item1 == "o" && fc1 != null) { var o1 = s1.GetStream("o").GetData(); var o2 = s2.GetStream("o").GetData(); uint idx = 0; foreach (var site in fc1.Sites) { explain = string.Format(VBASyncResources.ExplainFrxOStreamDifference, site.Name, s1.Name); var o1Range = o1.Range(idx, site.ObjectStreamSize); var o2Range = o2.Range(idx, site.ObjectStreamSize); switch (site.ClsidCacheIndex) { case 15: // MorphData case 26: // CheckBox case 25: // ComboBox case 24: // ListBox case 27: // OptionButton case 23: // TextBox case 28: // ToggleButton if (!new MorphDataControl(o1Range).Equals(new MorphDataControl(o2Range))) { return(true); } break; case 17: // CommandButton if (!new CommandButtonControl(o1Range).Equals(new CommandButtonControl(o2Range))) { return(true); } break; case 18: // TabStrip if (!new TabStripControl(o1Range).Equals(new TabStripControl(o2Range))) { return(true); } break; case 21: // Label if (!new LabelControl(o1Range).Equals(new LabelControl(o2Range))) { return(true); } break; default: if (!o1Range.SequenceEqual(o2Range)) { return(true); } break; } idx += site.ObjectStreamSize; } } else if (!s1.GetStream(t.Item1).GetData().SequenceEqual(s2.GetStream(t.Item1).GetData())) { explain = string.Format(VBASyncResources.ExplainFrxGeneralStreamDifference, t.Item1, s1.Name); return(true); } } explain = "No differences found."; return(false); }
/// <summary> /// Creates this object and sets all its properties /// </summary> /// <param name="storage">The OLE version 2.0 object as a <see cref="CFStorage" /></param> internal Ole10Native(CFStorage storage) { if (storage == null) { throw new ArgumentNullException(nameof(storage)); } var ole10Native = storage.GetStream("\x0001Ole10Native"); var compObj = storage.GetStream("\x0001CompObj"); var compObjStream = new CompObjStream(compObj); AnsiUserType = compObjStream.AnsiUserType; StringFormat = compObjStream.StringFormat; ClipboardFormat = compObjStream.ClipboardFormat; switch (compObjStream.AnsiUserType) { case "OLE Package": var olePackageSize = (int)ole10Native.Size - 4; if (olePackageSize <= 0) { break; } var olePackageData = new byte[olePackageSize]; ole10Native.Read(olePackageData, 4, olePackageSize); var package = new Package(olePackageData); Format = package.Format; FileName = Path.GetFileName(package.FileName); FilePath = package.FilePath; NativeData = package.Data; break; case "PBrush": case "Paintbrush-afbeelding": var pbBrushSize = (int)ole10Native.Size - 4; if (pbBrushSize <= 0) { break; } var pbBrushData = new byte[pbBrushSize]; ole10Native.Read(pbBrushData, 4, pbBrushSize); FileName = "Embedded PBrush image.bmp"; Format = OleFormat.File; NativeData = pbBrushData; break; case "Pakket": // Ignore break; // MathType (http://docs.wiris.com/en/mathtype/start) is a equations editor // The data is stored in the MTEF format within image file formats (PICT, WMF, EPS, GIF) or Office documents // as kind of pickaback data. (http://docs.wiris.com/en/mathtype/mathtype_desktop/mathtype-sdk/mtefstorage). // Within Office, a placeholder image shows the created equation. // Because MathType does not support storing equations in a separate MTEF file, a export of the data is not // directly possible and would require a conversion into the mentioned file formats. // Due that facts, it make no sense try to export the data. case "MathType 5.0 Equation": break; // Used by the depreciated Microsoft Office ClipArt Gallery // supposedly to store some metadata case "MS_ClipArt_Gallery": case "Microsoft ClipArt Gallery": break; default: throw new OEObjectTypeNotSupported("Unsupported OleNative AnsiUserType '" + compObjStream.AnsiUserType + "' found"); } }
/// <summary> /// This method will extract and save the data from the given <see cref="storage"/> node to the <see cref="outputFolder"/> /// </summary> /// <param name="storage">The <see cref="CFStorage"/> node</param> /// <param name="outputFolder">The outputFolder</param> /// <param name="fileName">The fileName to use, null when the fileName is unknown</param> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when a WordDocument, WorkBook or PowerPoint Document stream is password protected</exception> public static string SaveFromStorageNode(CFStorage storage, string outputFolder, string fileName) { if (storage.ExistsStream("CONTENTS")) { var contents = storage.GetStream("CONTENTS"); if (contents.Size <= 0) return null; if (string.IsNullOrWhiteSpace(fileName)) fileName = DefaultEmbeddedObjectName; return SaveByteArrayToFile(contents.GetData(), Path.Combine(outputFolder, fileName)); } if (storage.ExistsStream("Package")) { var package = storage.GetStream("Package"); if (package.Size <= 0) return null; if (string.IsNullOrWhiteSpace(fileName)) fileName = DefaultEmbeddedObjectName; return SaveByteArrayToFile(package.GetData(), Path.Combine(outputFolder, fileName)); } if (storage.ExistsStream("EmbeddedOdf")) { // The embedded object is an Embedded ODF file var package = storage.GetStream("EmbeddedOdf"); if (package.Size <= 0) return null; if (string.IsNullOrWhiteSpace(fileName)) fileName = DefaultEmbeddedObjectName; return SaveByteArrayToFile(package.GetData(), Path.Combine(outputFolder, fileName)); } if (storage.ExistsStream("\x0001Ole10Native")) { var ole10Native = new Ole10Native(storage); return ole10Native.Format == OleFormat.File ? SaveByteArrayToFile(ole10Native.NativeData, Path.Combine(outputFolder, ole10Native.FileName)) : null; } if (storage.ExistsStream("WordDocument")) { // The embedded object is a Word file if (string.IsNullOrWhiteSpace(fileName)) fileName = "Embedded Word document.doc"; return SaveStorageTreeToCompoundFile(storage, Path.Combine(outputFolder, fileName)); } if (storage.ExistsStream("Workbook")) { // The embedded object is an Excel file if (string.IsNullOrWhiteSpace(fileName)) fileName = "Embedded Excel document.xls"; Excel.SetWorkbookVisibility(storage); return SaveStorageTreeToCompoundFile(storage, Path.Combine(outputFolder, fileName)); } if (storage.ExistsStream("PowerPoint Document")) { // The embedded object is a PowerPoint file if (string.IsNullOrWhiteSpace(fileName)) fileName = "Embedded PowerPoint document.ppt"; return SaveStorageTreeToCompoundFile(storage, Path.Combine(outputFolder, fileName)); } return null; }
/// <summary> /// This method will extract and save the data from the given <see cref="storage"/> node to the <see cref="outputFolder"/> /// </summary> /// <param name="storage">The <see cref="CFStorage"/> node</param> /// <param name="outputFolder">The outputFolder</param> /// <param name="fileName">The fileName to use, null when the fileName is unknown</param> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when a WordDocument, WorkBook or PowerPoint Document stream is password protected</exception> public static string SaveFromStorageNode(CFStorage storage, string outputFolder, string fileName) { if (storage.ExistsStream("CONTENTS")) { var contents = storage.GetStream("CONTENTS"); if (contents.Size <= 0) { return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(contents.GetData(), Path.Combine(outputFolder, fileName))); } if (storage.ExistsStream("Package")) { var package = storage.GetStream("Package"); if (package.Size <= 0) { return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(package.GetData(), Path.Combine(outputFolder, fileName))); } if (storage.ExistsStream("EmbeddedOdf")) { // The embedded object is an Embedded ODF file var package = storage.GetStream("EmbeddedOdf"); if (package.Size <= 0) { return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(package.GetData(), Path.Combine(outputFolder, fileName))); } if (storage.ExistsStream("\x0001Ole10Native")) { var ole10Native = new Ole10Native(storage); return(ole10Native.Format == OleFormat.File ? SaveByteArrayToFile(ole10Native.NativeData, Path.Combine(outputFolder, ole10Native.FileName)) : null); } if (storage.ExistsStream("WordDocument")) { // The embedded object is a Word file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded Word document.doc"; } return(SaveStorageTreeToCompoundFile(storage, Path.Combine(outputFolder, fileName))); } if (storage.ExistsStream("Workbook")) { // The embedded object is an Excel file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded Excel document.xls"; } Excel.SetWorkbookVisibility(storage); return(SaveStorageTreeToCompoundFile(storage, Path.Combine(outputFolder, fileName))); } if (storage.ExistsStream("PowerPoint Document")) { // The embedded object is a PowerPoint file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded PowerPoint document.ppt"; } return(SaveStorageTreeToCompoundFile(storage, Path.Combine(outputFolder, fileName))); } return(null); }
/// <summary> /// Gets the MAPI property value from a stream or storage in this storage. /// </summary> /// <param name="propIdentifier">The 4 char hexadecimal prop identifier.</param> /// <returns>The value of the MAPI property or null if not found.</returns> private object GetMapiPropertyFromStreamOrStorage(string propIdentifier) { //determine if the property identifier is in a stream or sub storage string propTag = null; var propType = PropertyType.PT_UNSPECIFIED; foreach (string propKey in _keys) { if (propKey.StartsWith(MapiTags.SubStgVersion1 + propIdentifier)) { propTag = propKey.Substring(12, 8); propType = (PropertyType)ushort.Parse(propKey.Substring(16, 4), System.Globalization.NumberStyles.HexNumber); break; } } //depending on prop type use method to get property value string containerName = MapiTags.SubStgVersion1 + propTag; switch (propType) { case PropertyType.PT_UNSPECIFIED: return(null); case PropertyType.PT_STRING8: return(this.GetStreamAsString(containerName, Encoding.Default)); case PropertyType.PT_UNICODE: return(this.GetStreamAsString(containerName, Encoding.Unicode)); case PropertyType.PT_BINARY: return(_storage.GetStream(containerName).GetData()); case PropertyType.PT_OBJECT: return(_storage.GetStorage(containerName)); case PropertyType.PT_MV_STRING8: case PropertyType.PT_MV_UNICODE: // If the property is a unicode multiview item we need to read all the properties // again and filter out all the multivalue names, they end with -00000000, -00000001, etc.. var multiValueContainerNames = _keys.Where(propKey => propKey.StartsWith(containerName + "-")).ToList(); var values = new List <string>(); foreach (var multiValueContainerName in multiValueContainerNames) { var value = GetStreamAsString(multiValueContainerName, propType == PropertyType.PT_MV_STRING8 ? Encoding.Default : Encoding.Unicode); // Multi values always end with a null char so we need to strip that one off if (value.EndsWith("/0")) { value = value.Substring(0, value.Length - 1); } values.Add(value); } return(values); default: throw new ApplicationException("MAPI property has an unsupported type and can not be retrieved."); } }
public void LoadAttachmentProps(CFStorage attachmentStorage) { byte[] descBytes; try { descBytes = attachmentStorage.GetStream("AttachDesc").GetData(); } catch (CFItemNotFound ex) { throw new NotSupportedException("Attachment description stream not found", ex); } if (descBytes.Length == 0) { throw new ArgumentException("no description bytes to read"); } int nextIndex = 2; //first two bytes are the version StringUtils.ReadStringA(descBytes, ref nextIndex); StringUtils.ReadStringA(descBytes, ref nextIndex); string displayName = StringUtils.ReadStringA(descBytes, ref nextIndex); StringUtils.ReadStringA(descBytes, ref nextIndex); StringUtils.ReadStringA(descBytes, ref nextIndex); string extension = StringUtils.ReadStringA(descBytes, ref nextIndex); nextIndex += 16; AttachmentMethod = (AttachType)BitConverter.ToUInt32(descBytes, nextIndex); nextIndex += 4; ContentID = StringUtils.ReadStringW(descBytes, ref nextIndex); StringUtils.ReadStringW(descBytes, ref nextIndex); StringUtils.ReadStringW(descBytes, ref nextIndex); StringUtils.ReadStringW(descBytes, ref nextIndex); string displayNameW = StringUtils.ReadStringW(descBytes, ref nextIndex); StringUtils.ReadStringW(descBytes, ref nextIndex); StringUtils.ReadStringW(descBytes, ref nextIndex); string extensionW = StringUtils.ReadStringW(descBytes, ref nextIndex); //there's other stuff here, but I'm not going to read it Name = displayName ?? displayNameW; Extension = extension ?? extensionW; #if __ANDROID__ MimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(Extension == null ? null : Extension.Trim('.')); #endif switch (AttachmentMethod) { case AttachType.afByBalue: Content = attachmentStorage.GetStream("AttachContents").GetData(); return; case AttachType.afEmbeddedMessage: LoadRpmsgDataFromEmbeddedAttachment(attachmentStorage.GetStorage("MAPIMessage")); return; default: LogUtils.Error("unsupported attachment method: " + AttachmentMethod); Content = new byte[0]; return; } }