private static void LoadGameItems(Table table, CFStorage storage) { for (var i = 0; i < table.Data.NumGameItems; i++) { var itemName = $"GameItem{i}"; storage.TryGetStream(itemName, out var itemStream); if (itemStream == null) { Logger.Warn("Could not find stream {0}, skipping.", itemName); continue; } var itemData = itemStream.GetData(); if (itemData.Length < 4) { Logger.Warn("Skipping {itemName} because it has size of {itemDataLength}.", itemName, itemData.Length); continue; } var reader = new BinaryReader(new MemoryStream(itemData)); // parse to enum var iItemType = reader.ReadInt32(); if (!Enum.IsDefined(typeof(ItemType), iItemType)) { Logger.Info("Invalid item type " + iItemType); return; } var itemType = (ItemType)iItemType; switch (itemType) { case ItemType.Bumper: { var item = new VisualPinball.Engine.VPT.Bumper.Bumper(reader, itemName); table.Add(item); break; } case ItemType.Decal: { table.Add(new VisualPinball.Engine.VPT.Decal.Decal(reader, itemName)); break; } case ItemType.DispReel: { var item = new VisualPinball.Engine.VPT.DispReel.DispReel(reader, itemName); table.Add(item); break; } case ItemType.Flasher: { var item = new VisualPinball.Engine.VPT.Flasher.Flasher(reader, itemName); table.Add(item); break; } case ItemType.Flipper: { var item = new VisualPinball.Engine.VPT.Flipper.Flipper(reader, itemName); table.Add(item); break; } case ItemType.Gate: { var item = new VisualPinball.Engine.VPT.Gate.Gate(reader, itemName); table.Add(item); break; } case ItemType.HitTarget: { var item = new VisualPinball.Engine.VPT.HitTarget.HitTarget(reader, itemName); table.Add(item); break; } case ItemType.Kicker: { var item = new VisualPinball.Engine.VPT.Kicker.Kicker(reader, itemName); table.Add(item); break; } case ItemType.Light: { var item = new VisualPinball.Engine.VPT.Light.Light(reader, itemName); table.Add(item); break; } case ItemType.LightSeq: { var item = new VisualPinball.Engine.VPT.LightSeq.LightSeq(reader, itemName); table.Add(item); break; } case ItemType.Plunger: { var item = new VisualPinball.Engine.VPT.Plunger.Plunger(reader, itemName); table.Add(item); break; } case ItemType.Primitive: { var item = new Primitive.Primitive(reader, itemName); table.Add(item); break; } case ItemType.Ramp: { var item = new Ramp.Ramp(reader, itemName); table.Add(item); break; } case ItemType.Rubber: { var item = new Rubber.Rubber(reader, itemName); table.Add(item); break; } case ItemType.Spinner: { var item = new Spinner.Spinner(reader, itemName); table.Add(item); break; } case ItemType.Surface: { var item = new Surface.Surface(reader, itemName); table.Add(item); break; } case ItemType.TextBox: { var item = new TextBox.TextBox(reader, itemName); table.Add(item); break; } case ItemType.Timer: { var item = new Timer.Timer(reader, itemName); table.Add(item); break; } case ItemType.Trigger: { var item = new Trigger.Trigger(reader, itemName); table.Add(item); break; } } } }
/// <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> /// <param name="storage">The <see cref="CFStorage"/></param> /// <param name="binaryWriter">The <see cref="BinaryWriter" /></param> /// <param name="messageSize">Used to calculate the exact size of the <see cref="Message"/></param> /// <returns> /// Total size of the written <see cref="Properties"/> /// </returns> internal long WriteProperties(CFStorage storage, BinaryWriter binaryWriter, long?messageSize = null) { long size = 0; // The data inside the property stream (1) MUST be an array of 16-byte entries. The number of properties, // each represented by one entry, can be determined by first measuring the size of the property stream (1), // then subtracting the size of the header from it, and then dividing the result by the size of one entry. // The structure of each entry, representing one property, depends on whether the property is a fixed length // property or not. foreach (var property in this) { // property tag: A 32-bit value that contains a property type and a property ID. The low-order 16 bits // represent the property type. The high-order 16 bits represent the property ID. binaryWriter.Write(Convert.ToUInt16(property.Type)); // 2 bytes binaryWriter.Write(Convert.ToUInt16(property.Id)); // 2 bytes binaryWriter.Write(Convert.ToUInt32(property.Flags)); // 4 bytes switch (property.Type) { //case PropertyType.PT_ACTIONS: // break; case PropertyType.PT_APPTIME: case PropertyType.PT_SYSTIME: case PropertyType.PT_DOUBLE: case PropertyType.PT_I8: binaryWriter.Write(property.Data); break; case PropertyType.PT_ERROR: case PropertyType.PT_LONG: case PropertyType.PT_FLOAT: binaryWriter.Write(property.Data); binaryWriter.Write(new byte[4]); break; case PropertyType.PT_SHORT: binaryWriter.Write(property.Data); binaryWriter.Write(new byte[6]); break; case PropertyType.PT_BOOLEAN: binaryWriter.Write(property.Data); binaryWriter.Write(new byte[7]); break; //case PropertyType.PT_CURRENCY: // binaryWriter.Write(property.Data); // break; case PropertyType.PT_UNICODE: // Write the length of the property to the propertiesstream binaryWriter.Write(property.Data.Length + 2); binaryWriter.Write(new byte[4]); storage.AddStream(property.Name).SetData(property.Data); size += property.Data.LongLength; break; case PropertyType.PT_STRING8: // Write the length of the property to the propertiesstream binaryWriter.Write(property.Data.Length + 1); binaryWriter.Write(new byte[4]); storage.AddStream(property.Name).SetData(property.Data); size += property.Data.LongLength; break; case PropertyType.PT_CLSID: binaryWriter.Write(property.Data); break; //case PropertyType.PT_SVREID: // break; //case PropertyType.PT_SRESTRICT: // storage.AddStream(property.Name).SetData(property.Data); // break; case PropertyType.PT_BINARY: // Write the length of the property to the propertiesstream binaryWriter.Write(property.Data.Length); binaryWriter.Write(new byte[4]); storage.AddStream(property.Name).SetData(property.Data); size += property.Data.LongLength; break; case PropertyType.PT_MV_SHORT: break; case PropertyType.PT_MV_LONG: break; case PropertyType.PT_MV_FLOAT: break; case PropertyType.PT_MV_DOUBLE: break; case PropertyType.PT_MV_CURRENCY: break; case PropertyType.PT_MV_APPTIME: break; case PropertyType.PT_MV_LONGLONG: break; case PropertyType.PT_MV_UNICODE: // PropertyType.PT_MV_TSTRING break; case PropertyType.PT_MV_STRING8: break; case PropertyType.PT_MV_SYSTIME: break; //case PropertyType.PT_MV_CLSID: // break; case PropertyType.PT_MV_BINARY: break; case PropertyType.PT_UNSPECIFIED: break; case PropertyType.PT_NULL: break; case PropertyType.PT_OBJECT: // TODO: Adding new MSG file break; } } if (messageSize.HasValue) { binaryWriter.Write(Convert.ToUInt16(PropertyTags.PR_MESSAGE_SIZE.Type)); // 2 bytes binaryWriter.Write(Convert.ToUInt16(PropertyTags.PR_MESSAGE_SIZE.Id)); // 2 bytes binaryWriter.Write(Convert.ToUInt32(PropertyFlags.PROPATTR_READABLE | PropertyFlags.PROPATTR_WRITABLE)); // 4 bytes var totalSize = messageSize.Value + size + 8; var bytes = BitConverter.GetBytes(totalSize); binaryWriter.Write(bytes); binaryWriter.Write(new byte[4]); } // Make the properties stream binaryWriter.BaseStream.Position = 0; var propertiesStream = storage.TryGetStream(PropertyTags.PropertiesStreamName) ?? storage.AddStream(PropertyTags.PropertiesStreamName); propertiesStream.SetData(binaryWriter.BaseStream.ToByteArray()); return(size + binaryWriter.BaseStream.Length); }
void CMConvert(CompoundFile cf) { IList <IDirectoryEntry> entries = cf.GetDirectories(); // extract Circuit maker files and then try and rename directories // to match .pcbdoc entries string CurrentDir = ""; foreach (var entry in entries) { if (false && entry.Name == "Root Entry") { DirectoryInfo Info = Directory.CreateDirectory(entry.Name); if (!Info.Exists) { // for some reason the create directory failed so try again Info = Directory.CreateDirectory(entry.Name); } Thread.Sleep(500); // TODO this is a frig sort out ClearFolder(entry.Name); Directory.SetCurrentDirectory(entry.Name); CurrentDir = entry.Name; } else { if (entry.StgType == StgType.StgStorage) { CurrentDir = entry.Name; // Directory.CreateDirectory(entry.Name); CFStorage storage = cf.RootStorage.TryGetStorage(entry.Name); CFStream datastream = storage.GetStream("Data"); // get file contents and write to file byte[] data = datastream.GetData(); if (data.Length == 0) { OutputString($"Deleted '{CurrentDir}' no data"); // remove empty directory // Directory.Delete(CurrentDir); } else { // create the file // File.WriteAllBytes(CurrentDir + "\\" + "Data.dat", data); // now try and determine which file it is by examining the contents TextFile textfile = ByteArrayToStructure <TextFile>(data); TypeBinary typebinary = ByteArrayToStructure <TypeBinary>(data); TextFile2 textfile2 = ByteArrayToStructure <TextFile2>(data); if (IsPads(data)) { RenameDirectory(CurrentDir, "Pads6", data); } else if (IsVias(data)) { RenameDirectory(CurrentDir, "Vias6", data); } else if (IsTracks(data)) { RenameDirectory(CurrentDir, "Tracks6", data); } else if (IsComponentBodies(data)) { RenameDirectory(CurrentDir, "ComponentBodies6", data); } else if (IsBoard6(data)) { RenameDirectory(CurrentDir, "Board6", data); } else if (IsPolygons6(data)) { RenameDirectory(CurrentDir, "Polygons6", data); } else if (IsShapeBasedComponentBodies6(data)) { RenameDirectory(CurrentDir, "ShapeBasedComponentBodies6", data); } else if (IsArcs6(data)) { RenameDirectory(CurrentDir, "Arcs6", data); } else if (IsTexts6(data)) { RenameDirectory(CurrentDir, "Texts6", data); } else if (IsDimensions6(data)) { RenameDirectory(CurrentDir, "Dimensions6", data); } else if (IsRules6(data)) { RenameDirectory(CurrentDir, "Rules6", data); } else if (IsModels6(data)) { RenameDirectory(CurrentDir, "Models", data); // now need to get all of the model files CFStream models; byte[] modeldata; int i = 0; while ((models = storage.TryGetStream($"{i}")) != null) { OutputString($"Creating {i}.dat model file"); // get file contents and write to file modeldata = models.GetData(); // uncompress the x.dat file to a .step file // step file is renamed to it's actual name later in the process // string Inflated = ZlibCodecDecompress(modeldata); // File.WriteAllText($"Models\\{i}.step", Inflated); i++; } } else if ((textfile2.type == 0x0001 && textfile2.Length < data.Length) || textfile.Length < data.Length) { // could be text file string str = Encoding.Default.GetString(data); if (str.Contains("ORIGINX")) { RenameDirectory(CurrentDir, "Board6", data); } else if (str.Contains("AdvancedPlacerOptions")) { RenameDirectory(CurrentDir, "Advanced Placer Options6", data); } else if (str.Contains("SUPERCLASS")) { RenameDirectory(CurrentDir, "Classes6", data); } else if (str.Contains("SOURCEFOOTPRINTLIBRARY")) { RenameDirectory(CurrentDir, "Components6", data); } else if (str.Contains("DesignRuleCheckerOptions")) { RenameDirectory(CurrentDir, "Design Rule Checker Options6", data); } else if (str.Contains("POSITIVENETNAME")) { RenameDirectory(CurrentDir, "DifferentialPairs6", data); } else if (str.Contains("FWDMSG")) { RenameDirectory(CurrentDir, "FileVersionInfo", data); } else if (str.Contains("LOOPREMOVAL=")) { RenameDirectory(CurrentDir, "Nets6", data); } else if (str.Contains("PinSwapOptions")) { RenameDirectory(CurrentDir, "Pin Swap Option6", data); } else if (str.Contains("REMOVEDEAD")) { RenameDirectory(CurrentDir, "Polygons6", data); } else { OutputError($"Failed to convert possible text file '{CurrentDir}'"); } } else if (typebinary.Next < data.Length) { if (typebinary.Type == 0x03) { RenameDirectory(CurrentDir, "Vias6", data); } else if (typebinary.Type == 0x04) { RenameDirectory(CurrentDir, "Tracks6", data); } else if (typebinary.Type == 0x0B) { RenameDirectory(CurrentDir, "Regions6", data); } else if (typebinary.Type == 0x06) { RenameDirectory(CurrentDir, "Fills6", data); } else { OutputError($"Failed to convert possible binary file '{CurrentDir}'"); } } } } /* * else * if (entry.StgType == StgType.StgStream) * { * CFStream stream = cf.RootStorage.TryGetStream(CurrentDir + "\\" + entry.Name); * if (stream != null && stream.Size != 0) * { * var data = new byte[stream.Size]; * stream.Read(data, 0, data.Length); * File.WriteAllBytes(CurrentDir + "\\" + entry.Name, data); * } * } */ } // cf.RootStorage..DirEntry.EntryName. //OutputString($"{entry.ToString()}"); } Directory.SetCurrentDirectory(".."); }
/// <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 /// grbit 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> internal void SetWorkbookVisibility(CFStorage rootStorage) { if (!rootStorage.TryGetStream("WorkBook", out var stream)) { throw new OEFileIsCorrupt("Could not check workbook visibility because the WorkBook stream is not present"); } Logger.WriteToLog("Setting hidden Excel workbook to visible"); try { 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> /// This method will extract and save the data from the given <paramref name="storage"/> node to the <paramref name="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 the name of the created file that or null if there was nothing to export within the given <paramref name="storage"/> node.</returns> /// <exception cref="Exceptions.OEFileIsPasswordProtected">Raised when a WordDocument, WorkBook or PowerPoint Document stream is password protected</exception> public string SaveFromStorageNode(CFStorage storage, string outputFolder, string fileName) { Logger.WriteToLog($"Saving CFStorage to output folder '{outputFolder}' with file name {fileName}"); var contents = storage.TryGetStream("CONTENTS"); if (contents != null) { Logger.WriteToLog("CONTENTS stream found"); if (contents.Size <= 0) { Logger.WriteToLog("CONTENTS stream is empty"); return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } const string delimiter = "%DocumentOle:"; var documentOleFileName = GetDelimitedStringFromData(delimiter, contents.GetData()); if (documentOleFileName != null) { if (!documentOleFileName.Equals(string.Empty)) { fileName = Path.GetFileName(documentOleFileName); } contents.SetData(contents.GetData().Skip(delimiter.Length * 2 + documentOleFileName.Length).ToArray()); } return(SaveByteArrayToFile(contents.GetData(), FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } var package = storage.TryGetStream("Package"); if (package != null) { Logger.WriteToLog("Package stream found"); if (package.Size <= 0) { Logger.WriteToLog("Package stream is empty"); return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(package.GetData(), FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } var embeddedOdf = storage.TryGetStream("EmbeddedOdf"); if (embeddedOdf != null) { Logger.WriteToLog("EmbeddedOdf stream found"); // The embedded object is an Embedded ODF file if (embeddedOdf.Size <= 0) { Logger.WriteToLog("EmbeddedOdf stream is empty"); return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(embeddedOdf.GetData(), FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } if (storage.TryGetStream("\x0001Ole10Native") != null) { Logger.WriteToLog("Ole10Native stream found"); var ole10Native = new Ole10Native(storage); Logger.WriteToLog($"Ole10Native stream format is '{ole10Native.Format}'"); if (ole10Native.Format == OleFormat.File) { return(SaveByteArrayToFile(ole10Native.NativeData, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, ole10Native.FileName)))); } Logger.WriteToLog("Ole10Native is ignored"); return(null); } if (storage.TryGetStream("WordDocument") != null) { Logger.WriteToLog("WordDocument stream found"); // The embedded object is a Word file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded Word document.doc"; } return(SaveStorageTreeToCompoundFile(storage, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } if (storage.TryGetStream("Workbook") != null) { Logger.WriteToLog("Workbook stream found"); // The embedded object is an Excel file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded Excel document.xls"; } Excel.SetWorkbookVisibility(storage); return(SaveStorageTreeToCompoundFile(storage, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } if (storage.TryGetStream("PowerPoint Document") != null) { Logger.WriteToLog("PowerPoint Document stream found"); // The embedded object is a PowerPoint file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded PowerPoint document.ppt"; } return(SaveStorageTreeToCompoundFile(storage, FileManager.FileExistsMakeNew(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="Exceptions.OEFileIsPasswordProtected">Raised when a WordDocument, WorkBook or PowerPoint Document stream is password protected</exception> public static string SaveFromStorageNode(CFStorage storage, string outputFolder, string fileName) { var contents = storage.TryGetStream("CONTENTS"); if (contents != null) { if (contents.Size <= 0) { return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(contents.GetData(), FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } var package = storage.TryGetStream("Package"); if (package != null) { if (package.Size <= 0) { return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(package.GetData(), FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } var embeddedOdf = storage.TryGetStream("EmbeddedOdf"); if (embeddedOdf != null) { // The embedded object is an Embedded ODF file if (embeddedOdf.Size <= 0) { return(null); } if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultEmbeddedObjectName; } return(SaveByteArrayToFile(embeddedOdf.GetData(), FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } if (storage.TryGetStream("\x0001Ole10Native") != null) { var ole10Native = new Ole10Native(storage); return(ole10Native.Format == OleFormat.File ? SaveByteArrayToFile(ole10Native.NativeData, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, ole10Native.FileName))) : null); } if (storage.TryGetStream("WordDocument") != null) { // The embedded object is a Word file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded Word document.doc"; } return(SaveStorageTreeToCompoundFile(storage, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } if (storage.TryGetStream("Workbook") != null) { // The embedded object is an Excel file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded Excel document.xls"; } Excel.SetWorkbookVisibility(storage); return(SaveStorageTreeToCompoundFile(storage, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } if (storage.TryGetStream("PowerPoint Document") != null) { // The embedded object is a PowerPoint file if (string.IsNullOrWhiteSpace(fileName)) { fileName = "Embedded PowerPoint document.ppt"; } return(SaveStorageTreeToCompoundFile(storage, FileManager.FileExistsMakeNew(Path.Combine(outputFolder, fileName)))); } return(null); }