public static void Write(ProductHints productHints, string filePath) { string xmlString = ToString(productHints); if (xmlString != null) { // write to file var xmlBytes = Encoding.UTF8.GetBytes(xmlString); BinaryFile.ByteArrayToFile(filePath, xmlBytes); } }
public static ProductHints ReadFromString(string objectData) { ProductHints productHints = null; // read xml into model var serializer = new XmlSerializer(typeof(ProductHints)); using (TextReader reader = new StringReader(objectData)) { productHints = (ProductHints)serializer.Deserialize(reader); } return(productHints); }
public static ProductHints Read(string filePath) { ProductHints productHints = null; // read xml into model var serializer = new XmlSerializer(typeof(ProductHints)); using (var reader = XmlReader.Create(filePath)) { productHints = (ProductHints)serializer.Deserialize(reader); } return(productHints); }
public static string ToString(ProductHints productHints) { if (productHints == null) { return(null); } // write to xml file var serializer = new XmlSerializer(productHints.GetType()); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); // don't add xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" StringBuilder sb = new StringBuilder(); StringWriterWithEncoding stringWriter = new StringWriterWithEncoding(sb, Encoding.UTF8); XmlWriterSettings settings = new XmlWriterSettings { OmitXmlDeclaration = true, // when using false, the xml declaration and encoding is added (<?xml version="1.0" encoding="utf-8"?>) Indent = true, IndentChars = " ", NewLineChars = "\n", NewLineHandling = NewLineHandling.Replace }; using (XmlWriter writer = XmlWriter.Create(stringWriter, settings)) { // writer.WriteStartDocument(false); // when using OmitXmlDeclaration = false, add the standalone="no" property to the xml declaration // write custom xml declaration to duplicate the original xml format writer.WriteRaw("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n"); serializer.Serialize(writer, productHints, ns); } // add an extra \n at the end (0A) sb.Append("\n"); // ugly way to remove whitespace in self closing tags when writing xml document sb.Replace(" />", "/>"); string xmlString = sb.ToString(); // ugly way to add an extra newline after <ProductHints spec="1.0.16"> and before </ProductHints> xmlString = Regex.Replace(xmlString, @"(\<ProductHints.*?\>\n)", "$1\n", RegexOptions.IgnoreCase); xmlString = Regex.Replace(xmlString, @"(\n\</ProductHints\>)", "\n$1", RegexOptions.IgnoreCase); return(xmlString); }
/// <summary> /// Update the ImageBytes byte array in the ProductHints object using the stored Image and Imageformat /// </summary> /// <param name="productHints">product hints object</param> public static void UpdateImageBytesFromImage(ProductHints productHints) { if (productHints != null) { var image = productHints.Product.Icon.Image; var imageFormat = productHints.Product.Icon.ImageFormat; if (image != null && imageFormat != null) { using (var ms = new MemoryStream()) { image.Save(ms, imageFormat); // store image bytes productHints.Product.Icon.ImageBytes = ms.ToArray(); } } } }
/// <summary> /// Update the Image and Imageformat in the ProductHints object using the stored ImageBytes /// </summary> /// <param name="productHints">product hints object</param> public static void UpdateImageFromImageBytes(ProductHints productHints) { if (productHints != null) { var imageBytes = productHints.Product.Icon.ImageBytes; if (imageBytes != null) { using (var ms = new MemoryStream(imageBytes)) { IImageFormat imageFormat = null; var image = Image.Load(ms, out imageFormat); // store format productHints.Product.Icon.ImageFormat = imageFormat; // store image productHints.Product.Icon.Image = image; } } } }
public static void Pack(string inputDirectoryPath, string outputDirectoryPath, bool doList, bool doVerbose) { Log.Information("Packing directory {0} ...", inputDirectoryPath); string libraryName = Path.GetFileNameWithoutExtension(inputDirectoryPath); string outputFileName = libraryName + ".nicnt"; string outputFilePath = Path.Combine(outputDirectoryPath, outputFileName); Log.Information("Packing into file {0} ...", outputFilePath); // read the ContentVersion.txt file string contentVersionPath = Path.Combine(inputDirectoryPath, "ContentVersion.txt"); string version = "1.0"; if (File.Exists(contentVersionPath)) { version = IOUtils.ReadTextFromFile(contentVersionPath); if (doVerbose) { Log.Debug("Read version: '" + version + "' from ContentVersion.txt"); } } else { Log.Information("No ContentVersion.txt file found - using default version: '" + version + "'"); } // read the [LibraryName].xml file (should have the same name as the input directory) string productHintsXmlFileName = libraryName + ".xml"; string productHintsXmlFilePath = Path.Combine(inputDirectoryPath, productHintsXmlFileName); string productHintsXml = ""; ProductHints productHints = null; if (File.Exists(productHintsXmlFilePath)) { productHintsXml = IOUtils.ReadTextFromFile(productHintsXmlFilePath); Log.Information(string.Format("Found ProductHints Xml with length {0} characters.", productHintsXml.Length)); if (doVerbose) { Log.Debug("ProductHints Xml:\n" + productHintsXml); } // get the product hints as an object productHints = ProductHintsFactory.ReadFromString(productHintsXml); // get the productHints as string productHintsXml = ProductHintsFactory.ToString(productHints); // test output // var xmlBytesTest = Encoding.UTF8.GetBytes(productHintsXml); // BinaryFile.ByteArrayToFile(Path.Combine(inputDirectoryPath, libraryName + "-test.xml"), xmlBytesTest); // check that the directory name is the same as the Name and RegKey in the xml file if (productHints.Product.Name != productHints.Product.RegKey || libraryName != productHints.Product.Name) { Log.Error(string.Format("Fixing '{0}' due to incorrect values! (Library-Name: '{1}', Xml-Name: '{2}', Xml-RegKey: '{3}')", productHintsXmlFileName, libraryName, productHints.Product.Name, productHints.Product.RegKey)); // change into the library name productHints.Product.Name = libraryName; productHints.Product.RegKey = libraryName; // update the productHints as string productHintsXml = ProductHintsFactory.ToString(productHints); // and overwrite var xmlBytes = Encoding.UTF8.GetBytes(productHintsXml); BinaryFile.ByteArrayToFile(productHintsXmlFilePath, xmlBytes); } } else { Log.Error("Mandatory ProductHints XML file not found at: " + productHintsXmlFilePath); return; } // read the files in the resources directory var resourceList = new List <NICNTResource>(); string resourcesDirectoryPath = Path.Combine(inputDirectoryPath, "Resources"); if (Directory.Exists(resourcesDirectoryPath)) { var resourcesFilePaths = Directory.GetFiles(resourcesDirectoryPath, "*.*", SearchOption.AllDirectories); int counter = 1; foreach (var filePath in resourcesFilePaths) { var res = new NICNTResource(); string name = Path.GetFileName(filePath); // remove the counter in front string escapedFileNameWithNumber = Regex.Replace(name, @"^\d{3}(.*?)$", "$1", RegexOptions.IgnoreCase); // convert the windows supported unix filename to the original unix filename string unescapedFileName = ToUnixFileName(escapedFileNameWithNumber); res.Name = unescapedFileName; var bytes = File.ReadAllBytes(filePath); res.Data = bytes; res.Length = bytes.Length; res.Count = counter; resourceList.Add(res); counter++; } if (resourceList.Count > 0) { if (doVerbose) { Log.Debug("Added " + resourceList.Count + " files found in the Resources directory."); } } else { if (doVerbose) { Log.Information("No files in the Resource directory found!"); } } } else { if (doVerbose) { Log.Information("No Resources directory found!"); } } // check for mandatory .db.cache if (!resourceList.Any(m => m.Name.ToLower() == ".db.cache")) { XmlDocument xml = new XmlDocument(); // Adding the XmlDeclaration (version encoding and standalone) is not necessary as it is added using the XmlWriterSettings // XmlNode docNode = xml.CreateXmlDeclaration("1.0", "UTF-8", "no"); // xml.AppendChild(docNode); XmlElement root = xml.CreateElement("soundinfos"); root.SetAttribute("version", "110"); xml.AppendChild(root); XmlElement all = xml.CreateElement("all"); root.AppendChild(all); // format the xml string string xmlString = BeautifyXml(xml); var res = new NICNTResource(); res.Name = ".db.cache"; var bytes = Encoding.UTF8.GetBytes(xmlString); res.Data = bytes; res.Length = bytes.Length; // res.EndIndex is calculated during the write resource operation later res.Count = resourceList.Count + 1; resourceList.Add(res); if (doVerbose) { Log.Information("No .db.cache found - using default .db.cache:\n" + xml.OuterXml); } } using (BinaryFile bf = new BinaryFile(outputFilePath, BinaryFile.ByteOrder.LittleEndian, true)) { bf.Write(NKS_NICNT_MTD); // 2F 5C 20 4E 49 20 46 43 20 4D 54 44 20 20 2F 5C /\ NI FC MTD /\ bf.Write(new byte[50]); // 50 zero bytes bf.WriteStringPadded(version, 66, Encoding.Unicode); // zero padded string Int32 unknown1 = 1; bf.Write(unknown1); bf.Write(new byte[8]); // 8 zero bytes Int32 startOffset = 512000; bf.Write(startOffset); Int32 unknown3 = startOffset; bf.Write(unknown3); bf.Write(new byte[104]); // 104 zero bytes bf.Write(productHintsXml); bf.Write(new byte[startOffset + 256 - bf.Position]); // 512000 + 256 zero bytes - current pos bf.Write(NKS_NICNT_MTD); // 2F 5C 20 4E 49 20 46 43 20 4D 54 44 20 20 2F 5C /\ NI FC MTD /\ bf.Write(new byte[116]); // 116 zero bytes Int64 unknown4 = 2; bf.Write(unknown4); bf.Write(new byte[4]); // 4 zero bytes Int64 unknown5 = 1; bf.Write(unknown5); bf.Write(new byte[104]); // 104 zero bytes Int64 unknown6 = 1; bf.Write(unknown6); // write delimiter bf.Write(StringUtils.HexStringToByteArray("F0F0F0F0F0F0F0F0")); Int64 totalResourceCount = resourceList.Count; bf.Write(totalResourceCount); Int64 totalResourceLength = resourceList.Sum(item => item.Length); // sum of bytes in the resourceList bf.Write(totalResourceLength); bf.Write(NKS_NICNT_TOC); // 2F 5C 20 4E 49 20 46 43 20 54 4F 43 20 20 2F 5C /\ NI FC TOC /\ bf.Write(new byte[600]); // 600 zero bytes Int64 resCounter = 1; Int64 lastEndIndex = 0; foreach (var res in resourceList) { bf.Write(resCounter); bf.Write(new byte[16]); // 16 zero bytes bf.WriteStringPadded(res.Name, 600, Encoding.Unicode); // zero padded string Int64 resUnknown = 0; bf.Write(resUnknown); Int64 resEndIndex = lastEndIndex + res.Length; // aggregated end index bf.Write(resEndIndex); lastEndIndex = resEndIndex; resCounter++; } // write delimiter bf.Write(StringUtils.HexStringToByteArray("F1F1F1F1F1F1F1F1")); Int64 unknown13 = 0; bf.Write(unknown13); Int64 unknown14 = 0; bf.Write(unknown14); bf.Write(NKS_NICNT_TOC); // 2F 5C 20 4E 49 20 46 43 20 54 4F 43 20 20 2F 5C /\ NI FC TOC /\ bf.Write(new byte[592]); // 592 zero bytes foreach (var res in resourceList) { Log.Information(String.Format("Resource '{0}' @ position {1} [{2} bytes]", res.Name, bf.Position, res.Length)); bf.Write(res.Data); } } }