public static int Main(string[] args) { #if DEBUG // set args here for debugging args = new[] { "--build", @"..\..\..\SamplePlugin\", "../../../SamplePlugin/bin/Debug/", "-c=test.xml" }; #endif var selectedCommand = new Command(); string input = null; string output = null; string config = null; bool verbose = false; var options = new OptionSet() { { "b|build", "create plgx file", v => { if (v != null) { selectedCommand |= Command.Build; } } }, { "l|list", "list contents of plgx file", v => { if (v != null) { selectedCommand |= Command.List; } } }, { "e|extract", "extract file(s) from plgx", v => { if (v != null) { selectedCommand |= Command.Extract; } } }, { "p|package", "package plgx for distribution", v => { if (v != null) { selectedCommand |= Command.Package; } } }, { "h|help|?", "show usage", v => { if (v != null) { selectedCommand |= Command.Help; } } }, { "i|in|input=", "input file or directory", v => { input = v; } }, { "o|out|output=", "output file or directory", v => { output = v; } }, { "c|conf|config|configuration=", "configuration file", v => { config = v; } }, { "v|verbose", "configuration file", v => { verbose = v != null; } } }; try { var extras = options.Parse(args); if (input == null && extras.Count >= 1) { input = extras [0]; extras.RemoveAt(0); } if (output == null && extras.Count >= 1) { output = extras [0]; extras.RemoveAt(0); } if (config == null && extras.Count >= 1) { config = extras [0]; extras.RemoveAt(0); } input = GetFullPath(input); output = GetFullPath(output); config = GetFullPath(config); if (verbose) { Console.WriteLine("input: " + input); Console.WriteLine("output: " + output); Console.WriteLine("config: " + config); Console.WriteLine("extras: " + string.Join(", ", extras)); Console.WriteLine(); } } catch (Exception ex) { Console.WriteLine(ex.Message); selectedCommand = Command.Help; } if (selectedCommand == Command.Help || // build requires source dir (selectedCommand == Command.Build && (input == null || output == null)) || // build requires source dir (selectedCommand == Command.List && input == null) || // selected commands are mutually exclusive Math.Log((double)selectedCommand, 2) % 1 != 0) { Console.WriteLine(GetUsage()); return(1); } switch (selectedCommand) { #region Build Command case Command.Build: try { // populate common information for all plgx var plgx = new PlgxInfo(); plgx.Version = PlgxInfo.PlgxVersion1; plgx.FileUuid = new PwUuid(true); plgx.CreationTime = TimeUtil.SerializeUtc(DateTime.Now); var assm = Assembly.GetAssembly(typeof(Program)).GetName(); plgx.GeneratorName = assm.Name; plgx.GeneratorVersion = StrUtil.ParseVersion(assm.Version.ToString()); // read the optional config file to get the rest of the plgx header // information if (config != null) { var configDoc = new XmlDocument(); configDoc.Load(config); // mono xbuild adds namespaces for some reason, so we have to // strip them or else the serializer fails configDoc = XmlNamespaceStripper.StripNamespace(configDoc); var serializer = new XmlSerializer(typeof(PlgxConfiguration)); if (verbose) { #if DEBUG var writer = new XmlTextWriter(Console.OpenStandardOutput(), Encoding.UTF8); writer.Formatting = Formatting.Indented; configDoc.Save(writer); Console.WriteLine(); #endif serializer.UnknownAttribute += (sender, e) => Console.WriteLine("Unknown attribute: {0} at {1}:{2}", e.Attr.Name, e.LineNumber, e.LinePosition); serializer.UnknownElement += (sender, e) => Console.WriteLine("Unknown element: {0} at {1}:{2}", e.Element.Name, e.LineNumber, e.LinePosition); serializer.UnknownNode += (sender, e) => Console.WriteLine("Unknown node: {0} at {1}:{2}", e.Name, e.LineNumber, e.LinePosition); serializer.UnreferencedObject += (sender, e) => Console.WriteLine("Unreferenced object: {0}", e.UnreferencedId); } configDoc.Save(config); var plgxConfig = serializer.Deserialize(File.OpenRead(config)) as PlgxConfiguration; if (plgxConfig.Prerequisites != null) { if (!string.IsNullOrWhiteSpace(plgxConfig.Prerequisites.KeePassVersion)) { plgx.PrereqKP = StrUtil.ParseVersion(plgxConfig.Prerequisites.KeePassVersion); } if (!string.IsNullOrWhiteSpace(plgxConfig.Prerequisites.DotNetVersion)) { plgx.PrereqNet = StrUtil.ParseVersion(plgxConfig.Prerequisites.DotNetVersion); } if (plgxConfig.Prerequisites.OSSpecified) { plgx.PrereqOS = plgxConfig.Prerequisites.OS.GetValue(); } if (plgxConfig.Prerequisites.PointerSizeSpecified) { plgx.PrereqPtr = uint.Parse(plgxConfig.Prerequisites.PointerSize.GetValue()); } } if (plgxConfig.BuildCommands != null) { if (!string.IsNullOrWhiteSpace(plgxConfig.BuildCommands.PreBuild)) { plgx.BuildPre = plgxConfig.BuildCommands.PreBuild; } if (!string.IsNullOrWhiteSpace(plgxConfig.BuildCommands.PostBuild)) { plgx.BuildPost = plgxConfig.BuildCommands.PostBuild; } } } // read the .csproj file to find which files we need to include in // the plgx var projectFiles = Directory.GetFiles(input, "*.csproj"); if (projectFiles.Length != 1) { Console.WriteLine("Source directory must contain one and only on .csproj file"); return(1); } var project = new XmlDocument(); project.Load(projectFiles [0]); var assemblyNames = project.GetElementsByTagName("AssemblyName"); foreach (XmlNode assemblyName in assemblyNames) { plgx.BaseFileName = assemblyName.InnerText; } // include any files from <PlgxExtras> elements var plgxExtras = project.GetElementsByTagName("PlgxExtras"); foreach (XmlNode extra in plgxExtras) { foreach (XmlNode child in extra.ChildNodes) { if (child.LocalName == "Item") { var source = child.Attributes ["Source"]; var destination = child.Attributes ["Destination"]; if (source != null && !string.IsNullOrWhiteSpace(source.Value) && destination != null && !string.IsNullOrWhiteSpace(destination.Value)) { var sourcePath = UrlUtil.ConvertSeparators(source.Value); sourcePath = Path.Combine(input, sourcePath); sourcePath = Path.GetFullPath(sourcePath); plgx.AddFileFromDisk(sourcePath, destination.Value); } } } } // include all of the project files unless specifically excluded var itemGroups = project.GetElementsByTagName("ItemGroup"); foreach (XmlNode itemGroup in itemGroups) { // make copy of nodes except comments so that we can delete them inside of the for // loop if we need to var children = itemGroup.ChildNodes.Cast <XmlNode>().Where(child => child.NodeType != XmlNodeType.Comment).ToList(); foreach (XmlNode child in children) { if (child.LocalName == "Reference") { foreach (XmlNode childMetadata in child.ChildNodes) { var assemblyPath = Path.GetFullPath( Path.Combine(input, UrlUtil.ConvertSeparators(childMetadata.InnerText))); if (childMetadata.Name == "HintPath" && (child.Attributes ["Include"] == null || (!child.Attributes ["Include"].Value.StartsWith("KeePass,") && !child.Attributes ["Include"].Value.StartsWith("KeePass.exe")))) { if (!assemblyPath.StartsWith(input)) { // TODO - do we really want a fixed folder name here? childMetadata.InnerText = @"References\" + Path.GetFileName(assemblyPath); } plgx.AddFileFromDisk(assemblyPath, childMetadata.InnerText); } } continue; } // technically, the Include attribute is a semicolon separated // list and can include wildcards, but KeePass is only looking // for single files here, so we should not have to take this // into account var includeFile = child.Attributes ["Include"]; if (includeFile != null && !string.IsNullOrWhiteSpace(includeFile.Value)) { // skip "Include" files that are marked for exclusion from // the .plgx var exclude = false; foreach (XmlNode grandchild in child.ChildNodes) { if (grandchild.LocalName == "ExcludeFromPlgx") { exclude = true; break; } } if (exclude) { continue; } // copy all project items that have an Include attribute var includeFilePath = Path.GetFullPath( Path.Combine(input, UrlUtil.ConvertSeparators(includeFile.Value))); // <ProjectReference> elements get deleted. // If the <ProjectReference> element has <PlgxReference> child // elements, new <Reference> elements will be created using the // data from the <PlgxReference> element if (child.LocalName == "ProjectReference") { foreach (XmlNode projectItem in child.ChildNodes) { if (projectItem.LocalName == "PlgxReference") { var source = Path.GetFullPath(Path.Combine(input, UrlUtil.ConvertSeparators(projectItem.InnerText))); var destination = @"Reference\" + Path.GetFileName(source); var projectReference = project.CreateElement("Reference", child.NamespaceURI); projectReference.SetAttribute("Include", Path.GetFileName(destination)); var hintPath = project.CreateElement("HintPath", child.NamespaceURI); hintPath.InnerText = destination; projectReference.AppendChild(hintPath); child.ParentNode.AppendChild(projectReference); plgx.AddFileFromDisk(source, destination); } } child.ParentNode.RemoveChild(child); continue; } plgx.AddFileFromDisk(includeFilePath, includeFile.Value); } } } // write the in-memory project xml document (.csproj) to the plgx // instead of the file on disk since we may have changed it using (var stream = new MemoryStream()) { var writer = new XmlTextWriter(stream, Encoding.UTF8); writer.Formatting = Formatting.Indented; project.Save(writer); plgx.Files.Add(Path.GetFileName(projectFiles [0]), stream.ToArray()); #if DEBUG if (verbose) { Console.WriteLine(Encoding.UTF8.GetString( plgx.Files[Path.GetFileName(projectFiles[0])])); Console.WriteLine(); } #endif } if (verbose) { Console.WriteLine(plgx.ToString(true)); } plgx.WriteFile(output); } catch (Exception ex) { Console.WriteLine(ex.Message); return(1); } break; #endregion #region Extract Command case Command.Extract: Console.WriteLine("Not implemented."); return(1); #endregion #region List Command case Command.List: try { var plgx = PlgxInfo.ReadFile(File.OpenRead(input)); Console.WriteLine(plgx.ToString(true)); } catch (Exception ex) { Console.WriteLine(ex.Message); return(1); } break; #endregion #region Package Command case Command.Package: Console.WriteLine("Not implemented."); return(1); #endregion } return(0); }
/// <summary> /// Reads contents of plgx as PlgxInfo object. /// </summary> /// <returns>PlgxInfo object containing information from the plgx.</returns> /// <param name="stream">Stream containing plgx contents.</param> public static PlgxInfo ReadFile(Stream stream) { var reader = new BinaryReader (stream); var plgx = new PlgxInfo (); var signature1 = reader.ReadUInt32(); var signature2 = reader.ReadUInt32(); plgx.Version = reader.ReadUInt32(); if ((signature1 != PlgxSignature1) || (signature2 != PlgxSignature2)) throw new PlgxException ("Invalid signature at start of file"); if((plgx.Version & PlgxVersionMask) > (PlgxVersion1 & PlgxVersionMask)) throw new PlgxException(KLRes.FileVersionUnsupported); bool? content = null; while(true) { var pair = ReadObject(reader); if(pair.Key == PlgxEOF) break; else if(pair.Key == PlgxFileUuid) plgx.FileUuid = new PwUuid(pair.Value); else if(pair.Key == PlgxBaseFileName) plgx.BaseFileName = StrUtil.Utf8.GetString(pair.Value); else if(pair.Key == PlgxCreationTime) plgx.CreationTime = StrUtil.Utf8.GetString(pair.Value); else if(pair.Key == PlgxGeneratorName) plgx.GeneratorName = StrUtil.Utf8.GetString(pair.Value); else if(pair.Key == PlgxGeneratorVersion) plgx.GeneratorVersion = MemUtil.BytesToUInt64(pair.Value); else if(pair.Key == PlgxPrereqKP) plgx.PrereqKP = MemUtil.BytesToUInt64(pair.Value); else if(pair.Key == PlgxPrereqNet) plgx.PrereqNet = MemUtil.BytesToUInt64(pair.Value); else if(pair.Key == PlgxPrereqOS) plgx.PrereqOS = StrUtil.Utf8.GetString(pair.Value); else if(pair.Key == PlgxPrereqPtr) plgx.PrereqPtr = MemUtil.BytesToUInt32(pair.Value); else if(pair.Key == PlgxBuildPre) plgx.BuildPre = StrUtil.Utf8.GetString(pair.Value); else if(pair.Key == PlgxBuildPost) plgx.BuildPost = StrUtil.Utf8.GetString(pair.Value); else if(pair.Key == PlgxBeginContent) { if(content.HasValue) throw new PlgxException(KLRes.FileCorrupted); content = true; } else if(pair.Key == PlgxFile) { if(!content.HasValue || !content.Value) throw new PlgxException(KLRes.FileCorrupted); var file = ExtractFile(pair.Value); if (file != null) { plgx.Files.Add(file.Value); } } else if(pair.Key == PlgxEndContent) { if(!content.HasValue || !content.Value) throw new PlgxException(KLRes.FileCorrupted); content = false; } else { // TODO - do we want to list extra data? } } return plgx; }
public static int Main(string[] args) { #if DEBUG // set args here for debugging args = new[] { "--build", @"..\..\..\SamplePlugin\", "../../../SamplePlugin/bin/Debug/", "-c=test.xml" }; #endif var selectedCommand = new Command (); string input = null; string output = null; string config = null; bool verbose = false; var options = new OptionSet () { { "b|build", "create plgx file", v => { if (v != null) selectedCommand |= Command.Build; } }, { "l|list", "list contents of plgx file", v => { if (v != null) selectedCommand |= Command.List; } }, { "e|extract", "extract file(s) from plgx", v => { if (v != null) selectedCommand |= Command.Extract; } }, { "p|package", "package plgx for distribution", v => { if (v != null) selectedCommand |= Command.Package; } }, { "h|help|?", "show usage", v => { if (v != null) selectedCommand |= Command.Help; } }, { "i|in|input=", "input file or directory", v => { input = v; } }, { "o|out|output=", "output file or directory", v => { output = v; } }, { "c|conf|config|configuration=", "configuration file", v => { config = v; } }, { "v|verbose", "configuration file", v => { verbose = v != null; } } }; try { var extras = options.Parse (args); if (input == null && extras.Count >= 1) { input = extras [0]; extras.RemoveAt (0); } if (output == null && extras.Count >= 1) { output = extras [0]; extras.RemoveAt (0); } if (config == null && extras.Count >= 1) { config = extras [0]; extras.RemoveAt (0); } input = GetFullPath(input); output = GetFullPath(output); config = GetFullPath(config); if (verbose) { Console.WriteLine ("input: " + input); Console.WriteLine ("output: " + output); Console.WriteLine ("config: " + config); Console.WriteLine ("extras: " + string.Join (", ", extras)); Console.WriteLine (); } } catch (Exception ex) { Console.WriteLine (ex.Message); selectedCommand = Command.Help; } if (selectedCommand == Command.Help || // build requires source dir (selectedCommand == Command.Build && (input == null || output == null)) || // build requires source dir (selectedCommand == Command.List && input == null) || // selected commands are mutually exclusive Math.Log ((double)selectedCommand, 2) % 1 != 0) { Console.WriteLine (GetUsage ()); return 1; } switch (selectedCommand) { #region Build Command case Command.Build: try { // populate common information for all plgx var plgx = new PlgxInfo (); plgx.Version = PlgxInfo.PlgxVersion1; plgx.FileUuid = new PwUuid (true); plgx.CreationTime = TimeUtil.SerializeUtc (DateTime.Now); var assm = Assembly.GetAssembly (typeof(Program)).GetName (); plgx.GeneratorName = assm.Name; plgx.GeneratorVersion = StrUtil.ParseVersion (assm.Version.ToString ()); // read the optional config file to get the rest of the plgx header // information if (config != null) { var configDoc = new XmlDocument(); configDoc.Load (config); // mono xbuild adds namespaces for some reason, so we have to // strip them or else the serializer fails configDoc = XmlNamespaceStripper.StripNamespace (configDoc); var serializer = new XmlSerializer (typeof(PlgxConfiguration)); if (verbose) { #if DEBUG var writer = new XmlTextWriter(Console.OpenStandardOutput(), Encoding.UTF8); writer.Formatting = Formatting.Indented; configDoc.Save (writer); Console.WriteLine (); #endif serializer.UnknownAttribute += (sender, e) => Console.WriteLine ("Unknown attribute: {0} at {1}:{2}", e.Attr.Name, e.LineNumber, e.LinePosition); serializer.UnknownElement += (sender, e) => Console.WriteLine ("Unknown element: {0} at {1}:{2}", e.Element.Name, e.LineNumber, e.LinePosition); serializer.UnknownNode += (sender, e) => Console.WriteLine ("Unknown node: {0} at {1}:{2}", e.Name, e.LineNumber, e.LinePosition); serializer.UnreferencedObject += (sender, e) => Console.WriteLine ("Unreferenced object: {0}", e.UnreferencedId); } configDoc.Save (config); var plgxConfig = serializer.Deserialize (File.OpenRead (config)) as PlgxConfiguration; if (plgxConfig.Prerequisites != null) { if (!string.IsNullOrWhiteSpace (plgxConfig.Prerequisites.KeePassVersion)) { plgx.PrereqKP = StrUtil.ParseVersion (plgxConfig.Prerequisites.KeePassVersion); } if (!string.IsNullOrWhiteSpace (plgxConfig.Prerequisites.DotNetVersion)) { plgx.PrereqNet = StrUtil.ParseVersion (plgxConfig.Prerequisites.DotNetVersion); } if (plgxConfig.Prerequisites.OSSpecified) { plgx.PrereqOS = plgxConfig.Prerequisites.OS.GetValue (); } if (plgxConfig.Prerequisites.PointerSizeSpecified) { plgx.PrereqPtr = uint.Parse (plgxConfig.Prerequisites.PointerSize.GetValue ()); } } if (plgxConfig.BuildCommands != null) { if (!string.IsNullOrWhiteSpace (plgxConfig.BuildCommands.PreBuild)) { plgx.BuildPre = plgxConfig.BuildCommands.PreBuild; } if (!string.IsNullOrWhiteSpace (plgxConfig.BuildCommands.PostBuild)) { plgx.BuildPost = plgxConfig.BuildCommands.PostBuild; } } } // read the .csproj file to find which files we need to include in // the plgx var projectFiles = Directory.GetFiles (input, "*.csproj"); if (projectFiles.Length != 1) { Console.WriteLine ("Source directory must contain one and only on .csproj file"); return 1; } var project = new XmlDocument (); project.Load (projectFiles [0]); var assemblyNames = project.GetElementsByTagName ("AssemblyName"); foreach (XmlNode assemblyName in assemblyNames) { plgx.BaseFileName = assemblyName.InnerText; } // include any files from <PlgxExtras> elements var plgxExtras = project.GetElementsByTagName ("PlgxExtras"); foreach (XmlNode extra in plgxExtras) { foreach (XmlNode child in extra.ChildNodes) { if (child.LocalName == "Item") { var source = child.Attributes ["Source"]; var destination = child.Attributes ["Destination"]; if (source != null && !string.IsNullOrWhiteSpace (source.Value) && destination != null && !string.IsNullOrWhiteSpace (destination.Value)) { var sourcePath = UrlUtil.ConvertSeparators (source.Value); sourcePath = Path.Combine (input, sourcePath); sourcePath = Path.GetFullPath (sourcePath); plgx.AddFileFromDisk (sourcePath, destination.Value); } } } } // include all of the project files unless specifically excluded var itemGroups = project.GetElementsByTagName ("ItemGroup"); foreach (XmlNode itemGroup in itemGroups) { // make copy of nodes so that we can delete them inside of the for // loop if we need to var children = new List<XmlNode> (); foreach (XmlNode child in itemGroup.ChildNodes) { children.Add (child); } foreach (XmlNode child in children) { if (child.LocalName == "Reference") { foreach (XmlNode childMetadata in child.ChildNodes) { var assemblyPath = Path.GetFullPath ( Path.Combine (input, UrlUtil.ConvertSeparators (childMetadata.InnerText))); if (childMetadata.Name == "HintPath" && (child.Attributes ["Include"] == null || (!child.Attributes ["Include"].Value.StartsWith("KeePass,") && !child.Attributes ["Include"].Value.StartsWith("KeePass.exe")))) { if (!assemblyPath.StartsWith (input)) { // TODO - do we really want a fixed folder name here? childMetadata.InnerText = @"References\" + Path.GetFileName (assemblyPath); } plgx.AddFileFromDisk (assemblyPath, childMetadata.InnerText); } } continue; } // technically, the Include attribute is a semicolon separated // list and can include wildcards, but KeePass is only looking // for single files here, so we should not have to take this // into account var includeFile = child.Attributes ["Include"]; if (includeFile != null && !string.IsNullOrWhiteSpace (includeFile.Value)) { // skip "Include" files that are marked for exclusion from // the .plgx var exclude = false; foreach(XmlNode grandchild in child.ChildNodes) { if (grandchild.LocalName == "ExcludeFromPlgx") { exclude = true; break; } } if (exclude) { continue; } // copy all project items that have an Include attribute var includeFilePath = Path.GetFullPath ( Path.Combine (input, UrlUtil.ConvertSeparators (includeFile.Value))); // <ProjectReference> elements get deleted. // If the <ProjectReference> element has <PlgxReference> child // elements, new <Reference> elements will be created using the // data from the <PlgxReference> element if (child.LocalName == "ProjectReference") { foreach (XmlNode projectItem in child.ChildNodes) { if (projectItem.LocalName == "PlgxReference") { var source = Path.GetFullPath (Path.Combine (input, UrlUtil.ConvertSeparators (projectItem.InnerText))); var destination = @"Reference\" + Path.GetFileName (source); var projectReference = project.CreateElement ("Reference", child.NamespaceURI); projectReference.SetAttribute ("Include", Path.GetFileName (destination)); var hintPath = project.CreateElement ("HintPath", child.NamespaceURI); hintPath.InnerText = destination; projectReference.AppendChild (hintPath); child.ParentNode.AppendChild (projectReference); plgx.AddFileFromDisk (source, destination); } } child.ParentNode.RemoveChild (child); continue; } plgx.AddFileFromDisk (includeFilePath, includeFile.Value); } } } // write the in-memory project xml document (.csproj) to the plgx // instead of the file on disk since we may have changed it using (var stream = new MemoryStream()) { var writer = new XmlTextWriter (stream, Encoding.UTF8); writer.Formatting = Formatting.Indented; project.Save (writer); plgx.Files.Add (Path.GetFileName (projectFiles [0]), stream.ToArray ()); #if DEBUG if (verbose) { Console.WriteLine (Encoding.UTF8.GetString ( plgx.Files[Path.GetFileName (projectFiles[0])])); Console.WriteLine (); } #endif } if (verbose) { Console.WriteLine (plgx.ToString (true)); } plgx.WriteFile (output); } catch (Exception ex) { Console.WriteLine (ex.Message); return 1; } break; #endregion #region Extract Command case Command.Extract: Console.WriteLine ("Not implemented."); return 1; #endregion #region List Command case Command.List: try { var plgx = PlgxInfo.ReadFile (File.OpenRead (input)); Console.WriteLine (plgx.ToString (true)); } catch (Exception ex) { Console.WriteLine (ex.Message); return 1; } break; #endregion #region Package Command case Command.Package: Console.WriteLine ("Not implemented."); return 1; #endregion } return 0; }
/// <summary> /// Reads contents of plgx as PlgxInfo object. /// </summary> /// <returns>PlgxInfo object containing information from the plgx.</returns> /// <param name="stream">Stream containing plgx contents.</param> public static PlgxInfo ReadFile(Stream stream) { var reader = new BinaryReader(stream); var plgx = new PlgxInfo(); var signature1 = reader.ReadUInt32(); var signature2 = reader.ReadUInt32(); plgx.Version = reader.ReadUInt32(); if ((signature1 != PlgxSignature1) || (signature2 != PlgxSignature2)) { throw new PlgxException("Invalid signature at start of file"); } if ((plgx.Version & PlgxVersionMask) > (PlgxVersion1 & PlgxVersionMask)) { throw new PlgxException(KLRes.FileVersionUnsupported); } bool?content = null; while (true) { var pair = ReadObject(reader); if (pair.Key == PlgxEOF) { break; } else if (pair.Key == PlgxFileUuid) { plgx.FileUuid = new PwUuid(pair.Value); } else if (pair.Key == PlgxBaseFileName) { plgx.BaseFileName = StrUtil.Utf8.GetString(pair.Value); } else if (pair.Key == PlgxCreationTime) { plgx.CreationTime = StrUtil.Utf8.GetString(pair.Value); } else if (pair.Key == PlgxGeneratorName) { plgx.GeneratorName = StrUtil.Utf8.GetString(pair.Value); } else if (pair.Key == PlgxGeneratorVersion) { plgx.GeneratorVersion = MemUtil.BytesToUInt64(pair.Value); } else if (pair.Key == PlgxPrereqKP) { plgx.PrereqKP = MemUtil.BytesToUInt64(pair.Value); } else if (pair.Key == PlgxPrereqNet) { plgx.PrereqNet = MemUtil.BytesToUInt64(pair.Value); } else if (pair.Key == PlgxPrereqOS) { plgx.PrereqOS = StrUtil.Utf8.GetString(pair.Value); } else if (pair.Key == PlgxPrereqPtr) { plgx.PrereqPtr = MemUtil.BytesToUInt32(pair.Value); } else if (pair.Key == PlgxBuildPre) { plgx.BuildPre = StrUtil.Utf8.GetString(pair.Value); } else if (pair.Key == PlgxBuildPost) { plgx.BuildPost = StrUtil.Utf8.GetString(pair.Value); } else if (pair.Key == PlgxBeginContent) { if (content.HasValue) { throw new PlgxException(KLRes.FileCorrupted); } content = true; } else if (pair.Key == PlgxFile) { if (!content.HasValue || !content.Value) { throw new PlgxException(KLRes.FileCorrupted); } var file = ExtractFile(pair.Value); if (file != null) { plgx.Files.Add(file.Value); } } else if (pair.Key == PlgxEndContent) { if (!content.HasValue || !content.Value) { throw new PlgxException(KLRes.FileCorrupted); } content = false; } else { // TODO - do we want to list extra data? } } return(plgx); }