/*
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;
}
}
}