From b7b89ade046480e562980b7f520a151d2731f777 Mon Sep 17 00:00:00 2001 From: RKrom Date: Thu, 7 Mar 2013 10:08:57 +0000 Subject: [PATCH] cleanup & small fixes. Added some more IBinaryContainer implementations which are used by plugins which aren't rolled out yet. (but I didn't want to loose the code) git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2524 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- Greenshot/Helpers/CaptureHelper.cs | 27 ++++- Greenshot/Helpers/CopyData.cs | 2 +- GreenshotDropboxPlugin/DropboxUtils.cs | 10 +- GreenshotPicasaPlugin/PicasaUtils.cs | 3 + GreenshotPlugin/Core/ImageHelper.cs | 2 +- GreenshotPlugin/Core/ImageOutput.cs | 5 +- GreenshotPlugin/Core/NetworkHelper.cs | 156 ++++++++++++++++++++----- 7 files changed, 167 insertions(+), 38 deletions(-) diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs index 0719b5a74..335f4a4d0 100644 --- a/Greenshot/Helpers/CaptureHelper.cs +++ b/Greenshot/Helpers/CaptureHelper.cs @@ -55,7 +55,32 @@ namespace Greenshot.Helpers { private CaptureMode captureMode; private ScreenCaptureMode screenCaptureMode = ScreenCaptureMode.Auto; private Thread windowDetailsThread = null; - + + /// + /// The public accessible Dispose + /// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice + /// + public void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } + + // The bulk of the clean-up code is implemented in Dispose(bool) + + /// + /// This Dispose is called from the Dispose and the Destructor. + /// When disposing==true all non-managed resources should be freed too! + /// + /// + protected virtual void Dispose(bool disposing) { + if (disposing) { + // Cleanup + } + windows = null; + selectedCaptureWindow = null; + windowDetailsThread = null; + capture = null; + } public static void CaptureClipboard() { new CaptureHelper(CaptureMode.Clipboard).MakeCapture(); } diff --git a/Greenshot/Helpers/CopyData.cs b/Greenshot/Helpers/CopyData.cs index b877fef9f..c8889df84 100644 --- a/Greenshot/Helpers/CopyData.cs +++ b/Greenshot/Helpers/CopyData.cs @@ -183,7 +183,7 @@ namespace Greenshot.Helpers { /// after the form it is associated with. /// ~CopyData() { - Dispose(); + Dispose(false); } } diff --git a/GreenshotDropboxPlugin/DropboxUtils.cs b/GreenshotDropboxPlugin/DropboxUtils.cs index cec342cfd..fbe629b73 100644 --- a/GreenshotDropboxPlugin/DropboxUtils.cs +++ b/GreenshotDropboxPlugin/DropboxUtils.cs @@ -66,10 +66,12 @@ namespace GreenshotDropboxPlugin { // Try to get a URL to the uploaded image try { string responseString = oAuth.MakeOAuthRequest(HTTPMethod.GET, "https://api.dropbox.com/1/shares/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, null); - LOG.DebugFormat("Parsing output: {0}", responseString); - IDictionary returnValues = JSONHelper.JsonDecode(responseString); - if (returnValues.ContainsKey("url")) { - return returnValues["url"] as string; + if (responseString != null) { + LOG.DebugFormat("Parsing output: {0}", responseString); + IDictionary returnValues = JSONHelper.JsonDecode(responseString); + if (returnValues.ContainsKey("url")) { + return returnValues["url"] as string; + } } } catch (Exception ex) { LOG.Error("Can't parse response.", ex); diff --git a/GreenshotPicasaPlugin/PicasaUtils.cs b/GreenshotPicasaPlugin/PicasaUtils.cs index e5316ca0d..a7aae24a7 100644 --- a/GreenshotPicasaPlugin/PicasaUtils.cs +++ b/GreenshotPicasaPlugin/PicasaUtils.cs @@ -83,6 +83,9 @@ namespace GreenshotPicasaPlugin { } public static string ParseResponse(string response) { + if (response == null) { + return null; + } try { XmlDocument doc = new XmlDocument(); doc.LoadXml(response); diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs index ebd21390e..37f89370b 100644 --- a/GreenshotPlugin/Core/ImageHelper.cs +++ b/GreenshotPlugin/Core/ImageHelper.cs @@ -1020,7 +1020,7 @@ namespace GreenshotPlugin.Core { imageAttributes.SetColorMatrix(colorMatrix); ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes); } - + /// /// Apply image attributes to the image /// diff --git a/GreenshotPlugin/Core/ImageOutput.cs b/GreenshotPlugin/Core/ImageOutput.cs index 75b4371d4..4407a00da 100644 --- a/GreenshotPlugin/Core/ImageOutput.cs +++ b/GreenshotPlugin/Core/ImageOutput.cs @@ -91,13 +91,16 @@ namespace GreenshotPlugin.Core { /// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used. /// /// image to save - /// surface for the elements, if the greenshot format is used + /// surface for the elements, needed if the greenshot format is used /// Stream to save to /// SurfaceOutputSettings public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings) { ImageFormat imageFormat = null; bool useMemoryStream = false; MemoryStream memoryStream = null; + if (outputSettings.Format == OutputFormat.greenshot && surface == null) { + throw new ArgumentException("Surface needs to be se when using OutputFormat.Greenshot"); + } try { switch (outputSettings.Format) { diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs index b7efdc0c6..3fba80dee 100644 --- a/GreenshotPlugin/Core/NetworkHelper.cs +++ b/GreenshotPlugin/Core/NetworkHelper.cs @@ -254,41 +254,61 @@ namespace GreenshotPlugin.Core { } /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream + /// Write Multipart Form Data directly to the HttpWebRequest /// /// HttpWebRequest to write the multipart form data to /// Parameters to include in the multipart form data public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) { string boundary = String.Format("----------{0:N}", Guid.NewGuid()); webRequest.ContentType = "multipart/form-data; boundary=" + boundary; - - bool needsCLRF = false; using (Stream formDataStream = webRequest.GetRequestStream()) { - foreach (var param in postParameters) { - // Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added. - // Skip it on the first parameter, add it to subsequent parameters. - if (needsCLRF) { - formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); - } + WriteMultipartFormData(formDataStream, boundary, postParameters); + } + } - needsCLRF = true; + /// + /// Write Multipart Form Data to the HttpListenerResponse + /// + /// HttpWebRequest to write the multipart form data to + /// Parameters to include in the multipart form data + public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary postParameters) { + string boundary = String.Format("----------{0:N}", Guid.NewGuid()); + response.ContentType = "multipart/form-data; boundary=" + boundary; + WriteMultipartFormData(response.OutputStream, boundary, postParameters); + } - if (param.Value is IBinaryContainer) { - IBinaryContainer binaryParameter = (IBinaryContainer)param.Value; - binaryParameter.WriteFormDataToStream(boundary, param.Key, formDataStream); - } else { - string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", - boundary, - param.Key, - param.Value); - formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); - } + /// + /// Write Multipart Form Data to a Stream, content-type should be set before this! + /// + /// Stream to write the multipart form data to + /// String boundary for the multipart/form-data + /// Parameters to include in the multipart form data + public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) { + bool needsCLRF = false; + foreach (var param in postParameters) { + // Add a CRLF to allow multiple parameters to be added. + // Skip it on the first parameter, add it to subsequent parameters. + if (needsCLRF) { + formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); } - // Add the end of the request. Start with a newline - string footer = "\r\n--" + boundary + "--\r\n"; - formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); + needsCLRF = true; + + if (param.Value is IBinaryContainer) { + IBinaryContainer binaryParameter = (IBinaryContainer)param.Value; + binaryParameter.WriteFormDataToStream(boundary, param.Key, formDataStream); + } else { + string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", + boundary, + param.Key, + param.Value); + formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); + } } + + // Add the end of the request. Start with a newline + string footer = "\r\n--" + boundary + "--\r\n"; + formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); } /// @@ -330,18 +350,18 @@ namespace GreenshotPlugin.Core { /// /// A container to supply files to a Multi-part form data upload /// - public class FileContainer : IBinaryContainer { + public class ByteContainer : IBinaryContainer { private byte[] file; private string fileName; private string contentType; private int fileSize; - public FileContainer(byte[] file) : this(file, null) { + public ByteContainer(byte[] file) : this(file, null) { } - public FileContainer(byte[] file, string filename) : this(file, filename, null) { + public ByteContainer(byte[] file, string filename) : this(file, filename, null) { } - public FileContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) { + public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) { } - public FileContainer(byte[] file, string filename, string contenttype, int filesize) { + public ByteContainer(byte[] file, string filename, string contenttype, int filesize) { this.file = file; this.fileName = filename; this.contentType = contenttype; @@ -412,6 +432,82 @@ namespace GreenshotPlugin.Core { /// /// A container to supply images to a Multi-part form data upload /// + public class BitmapContainer : IBinaryContainer { + private Bitmap bitmap; + private SurfaceOutputSettings outputSettings; + private string fileName; + + public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename) { + this.bitmap = bitmap; + this.outputSettings = outputSettings; + this.fileName = filename; + } + + /// + /// Create a Base64String from the image by saving it to a memory stream and converting it. + /// Should be avoided if possible, as this uses a lot of memory. + /// + /// string + public string ToBase64String(Base64FormattingOptions formattingOptions) { + using (MemoryStream stream = new MemoryStream()) { + ImageOutput.SaveToStream(bitmap, null, stream, outputSettings); + return System.Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions); + } + } + + /// + /// Create a byte[] from the image by saving it to a memory stream. + /// Should be avoided if possible, as this uses a lot of memory. + /// + /// byte[] + public byte[] ToByteArray() { + using (MemoryStream stream = new MemoryStream()) { + ImageOutput.SaveToStream(bitmap, null, stream, outputSettings); + return stream.ToArray(); + } + } + + /// + /// Write Multipart Form Data directly to the HttpWebRequest response stream + /// + /// HttpWebRequest to write the multipart form data to + /// Parameters to include in the multipart form data + public void WriteFormDataToStream(string boundary, string key, Stream formDataStream) { + // Add just the first part of this param, since we will write the file data directly to the Stream + string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", + boundary, + key, + fileName ?? key, + "image/" + outputSettings.Format.ToString()); + + formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); + ImageOutput.SaveToStream(bitmap, null, formDataStream, outputSettings); + } + + /// + /// A plain "write data to stream" + /// + /// + public void WriteToStream(Stream dataStream) { + // Write the file data directly to the Stream, rather than serializing it to a string. + ImageOutput.SaveToStream(bitmap, null, dataStream, outputSettings); + } + + /// + /// Upload the image to the webrequest + /// + /// + public void Upload(HttpWebRequest webRequest) { + webRequest.ContentType = "image/" + outputSettings.Format.ToString(); + using (var requestStream = webRequest.GetRequestStream()) { + WriteToStream(requestStream); + } + } + } + + /// + /// A container to supply surfaces to a Multi-part form data upload + /// public class SurfaceContainer : IBinaryContainer { private ISurface surface; private SurfaceOutputSettings outputSettings; @@ -424,7 +520,7 @@ namespace GreenshotPlugin.Core { } /// - /// Create a Base64String from the image by saving it to a memory stream and converting it. + /// Create a Base64String from the Surface by saving it to a memory stream and converting it. /// Should be avoided if possible, as this uses a lot of memory. /// /// string @@ -474,7 +570,7 @@ namespace GreenshotPlugin.Core { } /// - /// Upload the image to the webrequest + /// Upload the Surface as image to the webrequest /// /// public void Upload(HttpWebRequest webRequest) {