/// <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"); } }
public void Test_DELETE_STREAM_2() { String filename = "MultipleStorage.cfs"; CompoundFile cf = new CompoundFile(filename); CFStorage cfs = cf.RootStorage.GetStorage("MyStorage").GetStorage("AnotherStorage"); cfs.Delete("AnotherStream"); cf.Save(TestContext + "MultipleStorage_REMOVED_STREAM_2.cfs"); cf.Close(); }
/// <summary> /// Writes the <see cref="Attachment" /> objects to the given <paramref name="rootStorage" /> /// and it will set all the needed properties /// </summary> /// <param name="rootStorage">The root <see cref="CFStorage" /></param> /// <returns> /// Total size of the written <see cref="Attachment"/> objects and it's <see cref="Properties"/> /// </returns> internal long WriteToStorage(CFStorage rootStorage) { long size = 0; for (var index = 0; index < Count; index++) { var attachment = this[index]; var storage = rootStorage.AddStorage(PropertyTags.AttachmentStoragePrefix + index.ToString("X8").ToUpper()); size += attachment.WriteProperties(storage, index); } return(size); }
public void Test_ENTRY_NAME_LENGTH() { //Thanks to Mark Bosold for bug fix and unit CompoundFile cf = new CompoundFile(); // Cannot be equal. string maxCharactersStreamName = "1234567890123456789A12345678901"; // 31 chars string maxCharactersStorageName = "1234567890123456789012345678901"; // 31 chars // Try Storage entry name with max characters. Assert.IsNotNull(cf.RootStorage.AddStorage(maxCharactersStorageName)); CFStorage strg = cf.RootStorage.GetStorage(maxCharactersStorageName); Assert.IsNotNull(strg); Assert.IsTrue(strg.Name == maxCharactersStorageName); // Try Stream entry name with max characters. Assert.IsNotNull(cf.RootStorage.AddStream(maxCharactersStreamName)); CFStream strm = cf.RootStorage.GetStream(maxCharactersStreamName); Assert.IsNotNull(strm); Assert.IsTrue(strm.Name == maxCharactersStreamName); string tooManyCharactersEntryName = "12345678901234567890123456789012"; // 32 chars try { // Try Storage entry name with too many characters. cf.RootStorage.AddStorage(tooManyCharactersEntryName); Assert.Fail(); } catch (Exception ex) { Assert.IsTrue(ex is CFException); } try { // Try Stream entry name with too many characters. cf.RootStorage.AddStream(tooManyCharactersEntryName); Assert.Fail(); } catch (Exception ex) { Assert.IsTrue(ex is CFException); } cf.Save("EntryNameLength"); cf.Close(); }
private CFStorage GetStorage(CFStorage cfstorage, string storagename) { CFStorage storage = null; try { storage = cfstorage.GetStorage(storagename); } catch (Exception) { } return(storage); }
private CFStream GetStream(CFStorage cfstorage, string streamname) { CFStream stream = null; try { stream = cfstorage.GetStream(streamname); } catch (Exception) { } return(stream); }
/// <summary> /// This will save the complete tree from the given <paramref name="storage"/> to a new <see cref="CompoundFile"/> /// </summary> /// <param name="storage"></param> /// <param name="fileName">The filename with path for the new compound file</param> internal static string SaveStorageTreeToCompoundFile(CFStorage storage, string fileName) { Logger.WriteToLog($"Saving storage tree to compound file '{fileName}'"); fileName = FileManager.FileExistsMakeNew(fileName); using (var compoundFile = new CompoundFile()) { GetStorageChain(compoundFile.RootStorage, storage); compoundFile.Save(fileName); } return(fileName); }
private static void LoadMappings(Table table, CFStorage gameStorage) { var name = "Mappings0"; gameStorage.TryGetStream(name, out var citStream); if (citStream != null) { using (var stream = new MemoryStream(citStream.GetData())) using (var reader = new BinaryReader(stream)) { table.Mappings = new Mappings.Mappings(reader, name); } } }
public static CFStream GetStream(ref CompoundFile cf, string path, string name) { List <string> pathList = null; if (path != "%Root_Entry%") { pathList = path.Split(new char[] { '/' }).ToList <string>(); } CFStorage rootStorage = cf.RootStorage; return(CFUtil.GetStorage(pathList, ref rootStorage).GetStream(name)); }
/// <summary> /// Creates this object and reads all the <see cref="EntryStreamItem" /> objects from /// the given <paramref name="storage"/> /// </summary> /// <param name="storage">The <see cref="CFStorage"/> that containts the <see cref="PropertyTags.EntryStream"/></param> internal EntryStream(CFStorage storage) { if (!storage.TryGetStream(PropertyTags.EntryStream, out var stream)) { stream = storage.AddStream(PropertyTags.EntryStream); } using (var memoryStream = new MemoryStream(stream.GetData())) using (var binaryReader = new BinaryReader(memoryStream)) while (!binaryReader.Eos()) { var entryStreamItem = new EntryStreamItem(binaryReader); Add(entryStreamItem); } }
public static CFStorage GetStorage(List <string> pathList, ref CFStorage storage) { if (pathList == null || pathList[0] == "") { return(storage); } if (pathList.Count <string>() > 1) { int index = pathList.Count <string>() - 1; string storageName = pathList[index]; pathList.RemoveAt(index); return(CFUtil.GetStorage(pathList, ref storage).GetStorage(storageName)); } return(storage.GetStorage(pathList[0])); }
public void Test_CREATE_STORAGE_WITH_CREATION_DATE() { const String STORAGE_NAME = "NewStorage1"; CompoundFile cf = new CompoundFile(); CFStorage st = cf.RootStorage.AddStorage(STORAGE_NAME); st.CreationDate = DateTime.Now; Assert.IsNotNull(st); Assert.AreEqual(STORAGE_NAME, st.Name, false); cf.Save("ProvaData.cfs"); cf.Close(); }
internal void Write(CFStorage storage, string streamName) { var stream = storage.TryGetStream(streamName) ?? storage.AddStream(streamName); using (var memoryStream = new MemoryStream()) using (var binaryWriter = new BinaryWriter(memoryStream)) { foreach (var entryStreamItem in this) { entryStreamItem.Write(binaryWriter); } stream.SetData(memoryStream.ToArray()); } }
public void Test_DELETE_DIRECTORY() { String FILENAME = "MultipleStorage2.cfs"; CompoundFile cf = new CompoundFile(FILENAME, CFSUpdateMode.ReadOnly, CFSConfiguration.Default); CFStorage st = cf.RootStorage.GetStorage("MyStorage"); Assert.IsNotNull(st); st.Delete("AnotherStorage"); cf.Save("MultipleStorage_Delete.cfs"); cf.Close(); }
/// <summary> /// Writes 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 WriteLibraryData(CFStorage library) { library.GetOrAddStream("Data").Write(writer => { var parameters = Data.Header.ExportToParameters(); WriteBlock(writer, w => WriteParameters(w, parameters)); writer.Write(Data.Items.Count); foreach (var component in Data.Items) { WriteStringBlock(writer, component.Pattern); WriteFootprint(component); } }); }
/// <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> /// 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()); } }
public void Test_FIX_BUG_GH_14() { String filename = "MyFile.dat"; String storageName = "MyStorage"; String streamName = "MyStream"; int BUFFER_SIZE = 800 * Mb; int iterationCount = 3; int streamCount = 3; CompoundFile compoundFileInit = new CompoundFile(CFSVersion.Ver_4, CFSConfiguration.Default); compoundFileInit.Save(filename); compoundFileInit.Close(); CompoundFile compoundFile = new CompoundFile(filename, CFSUpdateMode.Update, CFSConfiguration.Default); CFStorage st = compoundFile.RootStorage.AddStorage(storageName); byte b = 0X0A; for (int streamId = 0; streamId < streamCount; ++streamId) { CFStream sm = st.AddStream(streamName + streamId); for (int iteration = 0; iteration < iterationCount; ++iteration) { sm.Append(Helpers.GetBuffer(BUFFER_SIZE, b)); compoundFile.Commit(); } b++; } compoundFile.Close(); compoundFile = new CompoundFile(filename, CFSUpdateMode.ReadOnly, CFSConfiguration.Default); byte[] testBuffer = new byte[100]; byte t = 0x0A; for (int streamId = 0; streamId < streamCount; ++streamId) { compoundFile.RootStorage.GetStorage(storageName).GetStream(streamName + streamId).Read(testBuffer, BUFFER_SIZE / 2, 100); Assert.IsTrue(testBuffer.All(g => g == t)); compoundFile.RootStorage.GetStorage(storageName).GetStream(streamName + streamId).Read(testBuffer, BUFFER_SIZE - 101, 100); Assert.IsTrue(testBuffer.All(g => g == t)); compoundFile.RootStorage.GetStorage(storageName).GetStream(streamName + streamId).Read(testBuffer, 0, 100); Assert.IsTrue(testBuffer.All(g => g == t)); t++; } compoundFile.Close(); }
public void Test_VISIT_STORAGE() { String FILENAME = "testVisiting.xls"; // Remove... if (File.Exists(FILENAME)) { File.Delete(FILENAME); } //Create... CompoundFile ncf = new CompoundFile(); CFStorage l1 = ncf.RootStorage.AddStorage("Storage Level 1"); l1.AddStream("l1ns1"); l1.AddStream("l1ns2"); l1.AddStream("l1ns3"); CFStorage l2 = l1.AddStorage("Storage Level 2"); l2.AddStream("l2ns1"); l2.AddStream("l2ns2"); ncf.Save(FILENAME); ncf.Close(); // Read... CompoundFile cf = new CompoundFile(FILENAME); FileStream output = new FileStream("reportVisit.txt", FileMode.Create); TextWriter sw = new StreamWriter(output); Console.SetOut(sw); Action <CFItem> va = delegate(CFItem target) { sw.WriteLine(target.Name); }; cf.RootStorage.VisitEntries(va, true); cf.Close(); sw.Close(); }
private void CopyStorage(CFStorage source, CFStorage dest) { source.VisitEntries(i => { if (i.IsStorage) { CopyStorage((CFStorage)i, dest.AddStorage(i.Name)); } else if (i.IsStream) { var newStream = dest.AddStream(i.Name); var currStream = (CFStream)i; newStream.SetData(currStream.GetData()); } }, false); }
/// <summary> /// Writes all <see cref="Property">properties</see> either as a <see cref="CFStream"/> or as a collection in /// a <see cref="PropertyTags.PropertiesStreamName"/> stream to the given <paramref name="storage"/>, this depends /// on the <see cref="PropertyType"/> /// </summary> /// <remarks> /// See the <see cref="Properties"/> class it's <see cref="Properties.WriteProperties"/> method for the logic /// that is used to determine this /// </remarks> /// <param name="storage">The <see cref="CFStorage"/></param> /// <returns> /// Total size of the written <see cref="Recipient"/> object and it's <see cref="Properties"/> /// </returns> internal long WriteProperties(CFStorage storage) { var propertiesStream = new RecipientProperties(); propertiesStream.AddProperty(PropertyTags.PR_ROWID, RowId); propertiesStream.AddProperty(PropertyTags.PR_ENTRYID, Mapi.GenerateEntryId()); propertiesStream.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey()); propertiesStream.AddProperty(PropertyTags.PR_RECIPIENT_TYPE, RecipientType); propertiesStream.AddProperty(PropertyTags.PR_ADDRTYPE_W, AddressTypeString); propertiesStream.AddProperty(PropertyTags.PR_EMAIL_ADDRESS_W, Email); propertiesStream.AddProperty(PropertyTags.PR_OBJECT_TYPE, ObjectType); propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_TYPE, DisplayType); propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_NAME_W, DisplayName); propertiesStream.AddProperty(PropertyTags.PR_SEARCH_KEY, Mapi.GenerateSearchKey(AddressTypeString, Email)); return(propertiesStream.WriteProperties(storage)); }
/// <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); }
/// <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> /// 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"); } }
public void AddToCompoundFile(CompoundFile cf) { CFStorage projectStorage = cf.RootStorage.AddStorage("_VBA_PROJECT_CUR"); CFStorage vbaStorage = projectStorage.AddStorage("VBA"); AddStreamToStorage(projectStorage, this.ProjectWmStream); AddStreamToStorage(projectStorage, this.ProjectStream); AddStreamToStorage(vbaStorage, this.ThisWorkbookStream); AddStreamToStorage(vbaStorage, this.VbaProjectStream); AddStreamToStorage(vbaStorage, this.dirStream); foreach (var modStream in ModuleStreams) { AddStreamToStorage(vbaStorage, modStream); } }
private static void LoadCollections(FileTableContainer tableContainer, CFStorage storage) { for (var i = 0; i < tableContainer.NumCollections; i++) { var collectionName = $"Collection{i}"; storage.TryGetStream(collectionName, out var collectionStream); if (collectionStream == null) { Logger.Warn("Could not find stream {0}, skipping.", collectionName); continue; } using (var stream = new MemoryStream(collectionStream.GetData())) using (var reader = new BinaryReader(stream)) { tableContainer.Collections.Add(new CollectionData(reader, collectionName)); } } }
private void ReadUniqueIdPrimitiveInformation(CFStorage componentStorage, PcbComponent component) { if (!componentStorage.TryGetStorage("UniqueIdPrimitiveInformation", out var uniqueIdPrimitiveInformation)) { return; } BeginContext("UniqueIdPrimitiveInformation"); try { var recordCount = ReadHeader(uniqueIdPrimitiveInformation); using (var reader = uniqueIdPrimitiveInformation.GetStream("Data").GetBinaryReader()) { uint actualRecordCount = 0; while (reader.BaseStream.Position < reader.BaseStream.Length) { var parameters = ReadBlock(reader, size => ReadParameters(reader, size)); var primitiveIndex = parameters["PRIMITIVEINDEX"].AsIntOrDefault(); var primitiveObjectId = parameters["PRIMITIVEOBJECTID"].AsStringOrDefault(); var uniqueId = parameters["UNIQUEID"].AsStringOrDefault(); if (!CheckValue("PRIMITIVEINDEX < Primitives.Count", primitiveIndex < component.Primitives.Count, true)) { return; } var primitive = component.Primitives[primitiveIndex]; if (!CheckValue(nameof(primitiveObjectId), primitiveObjectId, primitive.ObjectId.ToString())) { return; } primitive.UniqueId = uniqueId; actualRecordCount++; } AssertValue(nameof(actualRecordCount), actualRecordCount, recordCount); } } finally { EndContext(); } }
/// <summary> /// Creates this object and sets all it's properties /// </summary> internal Message() { CompoundFile = new CompoundFile(); // In the preceding figure, the "__nameid_version1.0" named property mapping storage contains the // three streams used to provide a mapping from property ID to property name // ("__substg1.0_00020102", "__substg1.0_00030102", and "__substg1.0_00040102") and various other // streams that provide a mapping from property names to property IDs. _nameIdStorage = CompoundFile.RootStorage.TryGetStorage(PropertyTags.NameIdStorage) ?? CompoundFile.RootStorage.AddStorage(PropertyTags.NameIdStorage); var entryStream = _nameIdStorage.AddStream(PropertyTags.EntryStream); entryStream.SetData(new byte[0]); var stringStream = _nameIdStorage.AddStream(PropertyTags.StringStream); stringStream.SetData(new byte[0]); var guidStream = _nameIdStorage.AddStream(PropertyTags.GuidStream); guidStream.SetData(new byte[0]); }
private static void LoadCollections(Table table, CFStorage storage) { for (var i = 0; i < table.Data.NumCollections; i++) { var collectionName = $"Collection{i}"; storage.TryGetStream(collectionName, out var collectionStream); if (collectionStream == null) { Logger.Warn("Could not find stream {0}, skipping.", collectionName); continue; } using (var stream = new MemoryStream(collectionStream.GetData())) using (var reader = new BinaryReader(stream)) { var collection = new Collection.Collection(reader, collectionName); table.Collections[collection.Name.ToLower()] = collection; } } }
/// <summary> /// Load compound file from an existing stream. /// </summary> /// <param name="stream">Stream to load compound file from</param> private void Load(Stream stream) { try { _header = new Header(); _directoryEntries = new List<IDirectoryEntry>(); SourceStream = stream; _header.Read(stream); var numberOfSectors = Ceiling(((stream.Length - GetSectorSize())/(double) GetSectorSize())); if (stream.Length > 0x7FFFFF0) TransactionLockAllocated = true; _sectors = new SectorCollection(); for (var i = 0; i < numberOfSectors; i++) _sectors.Add(null); LoadDirectories(); RootStorage = new CFStorage(this, _directoryEntries[0]); } catch (Exception) { if (stream != null) stream.Close(); throw; } }
/// <summary> /// Create a blank, version 3 compound file. /// Sector recycle is turned off to achieve the best reading/writing /// performance in most common scenarios. /// </summary> /// <example> /// <code> /// /// byte[] b = new byte[10000]; /// for (int i = 0; i < 10000; i++) /// { /// b[i % 120] = (byte)i; /// } /// /// CompoundFile cf = new CompoundFile(); /// CFStream myStream = cf.RootStorage.AddStream("MyStream"); /// /// Assert.IsNotNull(myStream); /// myStream.SetData(b); /// cf.Save("MyCompoundFile.cfs"); /// cf.Close(); /// /// </code> /// </example> public CompoundFile() { _header = new Header(); _sectorRecycle = false; _difatSectorFATEntriesCount = (GetSectorSize()/4) - 1; _fatSectorEntriesCount = (GetSectorSize()/4); //Root -- RootStorage = new CFStorage(this); RootStorage.DirEntry.SetEntryName("Root Entry"); RootStorage.DirEntry.StgType = StgType.StgRoot; }
/// <summary> /// Create a new, blank, compound file. /// </summary> /// <param name="cfsVersion">Use a specific Compound File Version to set 512 or 4096 bytes sectors</param> /// <param name="sectorRecycle">If true, recycle unused sectors</param> /// <example> /// <code> /// /// byte[] b = new byte[10000]; /// for (int i = 0; i < 10000; i++) /// { /// b[i % 120] = (byte)i; /// } /// /// CompoundFile cf = new CompoundFile(CFSVersion.Ver_4, true, true); /// CFStream myStream = cf.RootStorage.AddStream("MyStream"); /// /// Assert.IsNotNull(myStream); /// myStream.SetData(b); /// cf.Save("MyCompoundFile.cfs"); /// cf.Close(); /// /// </code> /// </example> /// <remarks> /// Sector recycling reduces data writing performances but avoids space wasting in scenarios with frequently /// data manipulation of the same streams. The new compound file is open in Update mode. /// </remarks> public CompoundFile(CFSVersion cfsVersion, bool sectorRecycle) { _header = new Header((ushort) cfsVersion); _sectorRecycle = sectorRecycle; _difatSectorFATEntriesCount = (GetSectorSize()/4) - 1; _fatSectorEntriesCount = (GetSectorSize()/4); //Root -- RootStorage = new CFStorage(this); RootStorage.DirEntry.SetEntryName("Root Entry"); RootStorage.DirEntry.StgType = StgType.StgRoot; }
/// <summary> /// Returns the complete tree with all the <see cref="CFStorage"/> and <see cref="CFStream"/> children /// </summary> /// <param name="rootStorage"></param> /// <param name="storage"></param> private static void GetStorageChain(CFStorage rootStorage, CFStorage storage) { foreach (var child in storage.Children) { if (child.IsStorage) { var newRootStorage = rootStorage.AddStorage(child.Name); GetStorageChain(newRootStorage, child as CFStorage); } else if (child.IsStream) { var childStream = child as CFStream; if (childStream == null) continue; var stream = rootStorage.AddStream(child.Name); var bytes = childStream.GetData(); stream.SetData(bytes); } } }
/// <summary> /// This will save the complete tree from the given <paramref name="storage"/> to a new <see cref="CompoundFile"/> /// </summary> /// <param name="storage"></param> /// <param name="fileName">The filename with path for the new compound file</param> internal static string SaveStorageTreeToCompoundFile(CFStorage storage, string fileName) { fileName = FileManager.FileExistsMakeNew(fileName); using (var compoundFile = new CompoundFile()) { GetStorageChain(compoundFile.RootStorage, storage); compoundFile.Save(fileName); } return fileName; }
/// <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> /// <returns></returns> /// <exception cref="OEFileIsPasswordProtected">Raised when a WordDocument, WorkBook or PowerPoint Document stream is password protected</exception> internal static string SaveFromStorageNode(CFStorage storage, string outputFolder) { return SaveFromStorageNode(storage, outputFolder, null); }
/// <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); } }