/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.IO; using System.Reflection; using System.Text; using dnlib.DotNet.Resources; using dnSpy.Contracts.Decompiler; using dnSpy.Contracts.Documents.Tabs.DocViewer; using dnSpy.Contracts.Images; using dnSpy.Contracts.Text; namespace dnSpy.Contracts.Documents.TreeView.Resources { /// /// Resource utilities /// public static class ResourceUtilities { /// /// Creates an image reference /// /// dnSpy assembly /// Name of resource element /// public static ImageReference? TryGetImageReference(Assembly dnSpyAsm, string name) { // Don't use Path.GetExtension() since it can throw int index = name.LastIndexOf('.'); if (index >= 0) { switch (name.Substring(index + 1).ToUpperInvariant()) { case "CS": case "CSX": return DsImages.CSFileNode; case "VB": case "VBX": return DsImages.VBFileNode; case "TXT": return DsImages.TextFile; case "XAML": case "BAML": return DsImages.WPFFile; case "XML": return DsImages.XMLFile; case "XSD": return DsImages.XMLSchema; case "XSLT": return DsImages.XSLTransform; } } return null; } /// /// Returns if it's a user type, else is returned /// /// Resource type code /// public static ResourceTypeCode FixUserType(this ResourceTypeCode code) { if (code < ResourceTypeCode.UserTypes) return code; return ResourceTypeCode.UserTypes; } /// /// Converts a string to a stream /// /// String /// public static MemoryStream StringToStream(string? s) { var outStream = new MemoryStream(); var writer = new StreamWriter(outStream, Encoding.UTF8); writer.Write(s); writer.Close(); return new MemoryStream(outStream.ToArray()); } /// /// Writes the offset /// /// Output /// Node /// true if the offset and comment should be written public static void WriteOffsetComment(this IDecompilerOutput output, IResourceDataProvider node, bool showOffsetComment) { if (!showOffsetComment) return; var fo = node.FileOffset; if (fo == 0) return; var mod = (node as DocumentTreeNodeData)?.GetModule(); var filename = mod?.Location; output.Write($"0x{fo:X8}", new AddressReference(filename, false, fo, node.Length), DecompilerReferenceFlags.None, BoxedTextColor.Comment); output.Write(": ", BoxedTextColor.Comment); } /// /// Returns the string contents of if it's text, else null is returned /// /// Stream /// public static string? TryGetString(Stream stream) { if (stream is null) return null; stream.Position = 0; if (GuessFileType.DetectFileType(stream) == FileType.Binary) return null; stream.Position = 0; return new StreamReader(stream, true).ReadToEnd(); } /// /// "Decompiles" the data /// /// Context /// Stream /// Name /// public static bool Decompile(IDecompileNodeContext context, Stream stream, string name) { if (stream is null || stream.Length > 500 * 1024) return false; stream.Position = 0; var type = GuessFileType.DetectFileType(stream); if (type == FileType.Binary) return false; string ext; if (type == FileType.Xml) ext = ".xml"; else { try { ext = Path.GetExtension(NameUtilities.CleanName(name)); } catch (ArgumentException) { ext = ".txt"; } } context.ContentTypeString = ContentTypesHelper.TryGetContentTypeStringByExtension(ext) ?? ContentTypes.PlainText; stream.Position = 0; context.DocumentWriterService.Write(context.Output, new StreamReader(stream, true).ReadToEnd(), context.ContentTypeString); return true; } } }