diff --git a/src/Greenshot.Base/Core/ClipboardHelper.cs b/src/Greenshot.Base/Core/ClipboardHelper.cs
index 7da99f216..02a7f03f1 100644
--- a/src/Greenshot.Base/Core/ClipboardHelper.cs
+++ b/src/Greenshot.Base/Core/ClipboardHelper.cs
@@ -299,39 +299,24 @@ EndSelection:<<<<<<<4
return true;
}
- var fileDescriptor = (MemoryStream) dataObject.GetData("FileGroupDescriptorW");
- var files = FileDescriptorReader.Read(fileDescriptor);
- var fileIndex = 0;
- foreach (var fileContentFile in files)
+ foreach (var fileData in IterateClipboardContent(dataObject))
{
- if ((fileContentFile.FileAttributes & FileAttributes.Directory) != 0)
- {
- //Do something with directories?
- //Note that directories do not have FileContents
- //And will throw if we try to read them
- continue;
- }
-
- var fileData = FileDescriptorReader.GetFileContents(dataObject, fileIndex);
try
{
- //Do something with the fileContent Stream
- if (IsValidStream(fileData))
+ using (ImageHelper.FromStream(fileData))
{
- fileData.Position = 0;
- using (ImageHelper.FromStream(fileData))
- {
- // If we get here, there is an image
- return true;
- }
+ // If we get here, there is an image
+ return true;
}
}
+ catch (Exception ex)
+ {
+ Log.Error("Couldn't read file contents", ex);
+ }
finally
{
fileData?.Dispose();
}
-
- fileIndex++;
}
if (dataObject.GetDataPresent(FORMAT_FILECONTENTS))
@@ -357,28 +342,116 @@ EndSelection:<<<<<<<4
// Try to get the image from the HTML code
var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8);
- if (textObject != null)
+ if (textObject == null)
{
- var doc = new HtmlDocument();
- doc.LoadHtml(textObject);
- var imgNodes = doc.DocumentNode.SelectNodes("//img");
- if (imgNodes != null)
+ return false;
+ }
+
+ var doc = new HtmlDocument();
+ doc.LoadHtml(textObject);
+ var imgNodes = doc.DocumentNode.SelectNodes("//img");
+
+ if (imgNodes == null)
+ {
+ return false;
+ }
+
+ foreach (var imgNode in imgNodes)
+ {
+ var srcAttribute = imgNode.Attributes["src"];
+ var imageUrl = srcAttribute.Value;
+ if (!string.IsNullOrEmpty(imageUrl))
{
- foreach (var imgNode in imgNodes)
- {
- var srcAttribute = imgNode.Attributes["src"];
- var imageUrl = srcAttribute.Value;
- if (!string.IsNullOrEmpty(imageUrl))
- {
- return true;
- }
- }
+ return true;
}
}
return false;
}
+ ///
+ /// Iterate the clipboard content
+ ///
+ /// IDataObject
+ /// IEnumerable{MemoryStream}
+ private static IEnumerable IterateClipboardContent(IDataObject dataObject)
+ {
+ var fileDescriptors = AvailableFileDescriptors(dataObject);
+ if (fileDescriptors == null) yield break;
+
+ foreach (var fileData in IterateFileDescriptors(fileDescriptors, dataObject))
+ {
+ yield return fileData;
+ }
+ }
+
+ ///
+ /// Retrieve the FileDescriptor on the clipboard
+ ///
+ /// IDataObject
+ /// IEnumerable{FileDescriptor}
+ private static IEnumerable AvailableFileDescriptors(IDataObject dataObject)
+ {
+ var fileDescriptor = (MemoryStream) dataObject.GetData("FileGroupDescriptorW");
+ if (fileDescriptor != null)
+ {
+ try
+ {
+ return FileDescriptorReader.Read(fileDescriptor);
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Couldn't use FileDescriptorReader.", ex);
+ }
+ }
+
+ return Enumerable.Empty();
+ }
+
+ ///
+ /// Iterate the file descriptors on the clipboard
+ ///
+ /// IEnumerable{FileDescriptor}
+ /// IDataObject
+ /// IEnumerable{MemoryStream}
+ private static IEnumerable IterateFileDescriptors(IEnumerable fileDescriptors, IDataObject dataObject)
+ {
+ if (fileDescriptors == null)
+ {
+ yield break;
+ }
+
+ var fileIndex = 0;
+ foreach (var fileDescriptor in fileDescriptors)
+ {
+ if ((fileDescriptor.FileAttributes & FileAttributes.Directory) != 0)
+ {
+ //Do something with directories?
+ //Note that directories do not have FileContents
+ //And will throw if we try to read them
+ continue;
+ }
+
+ MemoryStream fileData = null;
+ try
+ {
+ fileData = FileDescriptorReader.GetFileContents(dataObject, fileIndex);
+ //Do something with the fileContent Stream
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Couldn't read file contents for {fileDescriptor.FileName}.", ex);
+ }
+ if (fileData?.Length > 0)
+ {
+ fileData.Position = 0;
+ yield return fileData;
+ }
+
+ fileIndex++;
+ }
+ }
+
///
/// Get the specified IDataObject format as a string
///
@@ -403,10 +476,10 @@ EndSelection:<<<<<<<4
/// Simple helper to check the stream
///
///
- ///
+ /// true if there is a valid stream
private static bool IsValidStream(MemoryStream memoryStream)
{
- return memoryStream != null && memoryStream.Length > 0;
+ return memoryStream?.Length > 0;
}
///
@@ -426,7 +499,7 @@ EndSelection:<<<<<<<4
}
///
- /// Get all images (multiple if filenames are available) from the dataObject
+ /// Get all images (multiple if file names are available) from the dataObject
/// Returned images must be disposed by the calling code!
///
///
@@ -442,6 +515,26 @@ EndSelection:<<<<<<<4
}
else
{
+ foreach (var fileData in IterateClipboardContent(dataObject))
+ {
+ Image image;
+ try
+ {
+ image = ImageHelper.FromStream(fileData);
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Couldn't read file contents", ex);
+ continue;
+ }
+ finally
+ {
+ fileData?.Dispose();
+ }
+ // If we get here, there is an image
+ yield return image;
+ }
+
// check if files are supplied
foreach (string imageFile in GetImageFilenames(dataObject))
{
@@ -478,7 +571,7 @@ EndSelection:<<<<<<<4
string[] retrieveFormats;
// Found a weird bug, where PNG's from Outlook 2010 are clipped
- // So I build some special logik to get the best format:
+ // So I build some special logic to get the best format:
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
{
// Outlook ??
@@ -729,7 +822,7 @@ EndSelection:<<<<<<<4
/// This method will place images to the clipboard depending on the ClipboardFormats setting.
/// e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice
/// because OpenOffice has a bug https://qa.openoffice.org/issues/show_bug.cgi?id=85661
- /// The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003!
+ /// The Dib (Device Independent Bitmap) in 32bpp actually won't work with Powerpoint 2003!
/// When pasting a Dib in PP 2003 the Bitmap is somehow shifted left!
/// For this problem the user should not use the direct paste (=Dib), but select Bitmap
///
diff --git a/src/Greenshot.Base/Core/FileDescriptor.cs b/src/Greenshot.Base/Core/FileDescriptor.cs
new file mode 100644
index 000000000..5306cf3b8
--- /dev/null
+++ b/src/Greenshot.Base/Core/FileDescriptor.cs
@@ -0,0 +1,76 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: https://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program 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 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+using System;
+using System.IO;
+using System.Text;
+using Greenshot.Base.UnmanagedHelpers.Structs;
+
+namespace Greenshot.Base.Core
+{
+ public sealed class FileDescriptor
+ {
+ public FileDescriptorFlags Flags { get; set; }
+ public Guid ClassId { get; set; }
+ public SIZE Size { get; set; }
+ public POINT Point { get; set; }
+ public FileAttributes FileAttributes { get; set; }
+ public DateTime CreationTime { get; set; }
+ public DateTime LastAccessTime { get; set; }
+ public DateTime LastWriteTime { get; set; }
+ public Int64 FileSize { get; set; }
+ public string FileName { get; set; }
+
+ public FileDescriptor(BinaryReader reader)
+ {
+ //Flags
+ Flags = (FileDescriptorFlags)reader.ReadUInt32();
+ //ClassID
+ ClassId = new Guid(reader.ReadBytes(16));
+ //Size
+ Size = new SIZE(reader.ReadInt32(), reader.ReadInt32());
+ //Point
+ Point = new POINT(reader.ReadInt32(), reader.ReadInt32());
+ //FileAttributes
+ FileAttributes = (FileAttributes)reader.ReadUInt32();
+ //CreationTime
+ CreationTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64());
+ //LastAccessTime
+ LastAccessTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64());
+ //LastWriteTime
+ LastWriteTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64());
+ //FileSize
+ FileSize = reader.ReadInt64();
+ //FileName
+ byte[] nameBytes = reader.ReadBytes(520);
+ int i = 0;
+ while (i < nameBytes.Length)
+ {
+ if (nameBytes[i] == 0 && nameBytes[i + 1] == 0)
+ break;
+ i++;
+ i++;
+ }
+
+ FileName = Encoding.Unicode.GetString(nameBytes, 0, i);
+ }
+ }
+}
diff --git a/src/Greenshot.Base/Core/FileDescriptorReader.cs b/src/Greenshot.Base/Core/FileDescriptorReader.cs
index 628e6d81a..69ad0af7d 100644
--- a/src/Greenshot.Base/Core/FileDescriptorReader.cs
+++ b/src/Greenshot.Base/Core/FileDescriptorReader.cs
@@ -24,8 +24,6 @@ using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
-using System.Text;
-using Greenshot.Base.UnmanagedHelpers.Structs;
namespace Greenshot.Base.Core
{
@@ -33,60 +31,12 @@ namespace Greenshot.Base.Core
/// Specifies which fields are valid in a FileDescriptor Structure
///
[Flags]
- internal enum FileDescriptorFlags : uint
+ public enum FileDescriptorFlags : uint
{
}
internal static class FileDescriptorReader
{
- internal sealed class FileDescriptor
- {
- public FileDescriptorFlags Flags { get; set; }
- public Guid ClassId { get; set; }
- public SIZE Size { get; set; }
- public POINT Point { get; set; }
- public FileAttributes FileAttributes { get; set; }
- public DateTime CreationTime { get; set; }
- public DateTime LastAccessTime { get; set; }
- public DateTime LastWriteTime { get; set; }
- public Int64 FileSize { get; set; }
- public string FileName { get; set; }
-
- public FileDescriptor(BinaryReader reader)
- {
- //Flags
- Flags = (FileDescriptorFlags) reader.ReadUInt32();
- //ClassID
- ClassId = new Guid(reader.ReadBytes(16));
- //Size
- Size = new SIZE(reader.ReadInt32(), reader.ReadInt32());
- //Point
- Point = new POINT(reader.ReadInt32(), reader.ReadInt32());
- //FileAttributes
- FileAttributes = (FileAttributes) reader.ReadUInt32();
- //CreationTime
- CreationTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64());
- //LastAccessTime
- LastAccessTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64());
- //LastWriteTime
- LastWriteTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64());
- //FileSize
- FileSize = reader.ReadInt64();
- //FileName
- byte[] nameBytes = reader.ReadBytes(520);
- int i = 0;
- while (i < nameBytes.Length)
- {
- if (nameBytes[i] == 0 && nameBytes[i + 1] == 0)
- break;
- i++;
- i++;
- }
-
- FileName = Encoding.Unicode.GetString(nameBytes, 0, i);
- }
- }
-
public static IEnumerable Read(Stream fileDescriptorStream)
{
if (fileDescriptorStream == null)
diff --git a/src/Greenshot/Destinations/FileDestination.cs b/src/Greenshot/Destinations/FileDestination.cs
index 677fc0e18..9389c3d26 100644
--- a/src/Greenshot/Destinations/FileDestination.cs
+++ b/src/Greenshot/Destinations/FileDestination.cs
@@ -55,12 +55,12 @@ namespace Greenshot.Destinations
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails)
{
- ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ var exportInformation = new ExportInformation(Designation, Description);
bool outputMade;
bool overwrite;
string fullPath;
// Get output settings from the configuration
- SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
+ var outputSettings = new SurfaceOutputSettings();
if (captureDetails?.Filename != null)
{
@@ -79,7 +79,7 @@ namespace Greenshot.Destinations
if (CoreConfig.OutputFilePromptQuality)
{
- QualityDialog qualityDialog = new QualityDialog(outputSettings);
+ var qualityDialog = new QualityDialog(outputSettings);
qualityDialog.ShowDialog();
}