From a31d63e5db7ed9a97cdb1ec4f3481cfa9c2d2aa0 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 29 Oct 2015 12:21:11 +0100 Subject: [PATCH 01/17] 1.2.8.x preparations [skip ci] --- .../releases/additional_files/readme.txt.template | 10 ++++++++++ appveyor.yml | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Greenshot/releases/additional_files/readme.txt.template b/Greenshot/releases/additional_files/readme.txt.template index 6ec082c85..c1431d230 100644 --- a/Greenshot/releases/additional_files/readme.txt.template +++ b/Greenshot/releases/additional_files/readme.txt.template @@ -9,6 +9,16 @@ All details to our tickets can be found here: https://greenshot.atlassian.net @DETAILVERSION@ +Bugs Resolved: +* BUG-1850: Greenshot stops responding + +Workaround: +* BUG-1852: When using Imgur & clipboard destinations, the imgur export Uri overwrites the clipboard image + -> Change the CopyLinkToClipboard flag to false in the greenshot.ini + + +1.2.7.2-342a506 RELEASE + Bugs Resolved: * BUG-1809: OverflowException when changing the windows input language * BUG-1835: Imgur: uploads were cancelled due to a timeout which was set too small diff --git a/appveyor.yml b/appveyor.yml index 2b4283e3e..1b2ecabfe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.2.7.{build} +version: 1.2.8.{build} branches: only: - 1.2 @@ -37,7 +37,7 @@ environment: secure: bjKXhFZkDqaq98XBrz5oQKQfT8CLpuv2ZAiBIwkzloaAPUs97b5yx6h/xFaE4NLS credentials_picasa_consumer_secret: secure: yNptTpmJWypbu9alOQtetxU66drr2FKxoPflNgRJdag= - build_type: RELEASE + build_type: UNSTABLE rsakey: secure: GNomwdlwZOCyd8d7xEWTnMVs1lpOeHvF+tlnvcbXGovLRtwAp2Ufu0r7paGY7BHGGkIs2WE7xUfyQ9UauVB+58JZ6fwVega8ucUgVJhl4x0QQNN2d6sULUhHfhuEHmxw+FDO/FxKFE6Lmf+ZRY+OGiw0wKIl4qD7mGRHcDQTipNEsTbau8HzqRVCdu3dx7pODC61DlsbO71xLF7UlqnmuZE+91Zz3V6AgaqE246n1499d6bXBYw1AH+8opNnKDFLnTHf7hUVcZn9mj6tKZXeTCuVUOr/SVQcgHKxlBlqzhfaEkxCR5GPtzQRqwDMxEycmFvj2wNP/sie6UEGhQxE4YMCc2OgqNOkpc5BbP/fxLr/SLFOEf1XXzTWCFMhsgpHx7TZbgQH26sa0rK/xaBRacZlwAaNk7V2nFZT7TebYEFy6zWNr9Y+IyeXIofj42XQTNXv8d8hyh+UYLByVEFYRf2DnActQkZQyNdWjZ+CxDV50QSZZs8FT3IIqraHYKsj2ITAN5LrUtWCi7bpNJL0UGo0EJiB2i0bp++tEAAwyrCljxI8d4bbGl/flHk/xd+ysQPnomndijeObjguEzqT8pyXZluSZhF+lI50mIDhMdtdAfMi5yn5RW7P6NWOSlC8xgQQgMZylsuSvRflKbEd/gsoDyEOnakNcdH2jekt9OD6GnuYM7iHkbMC89LBZ0VaHNGvCC+BQXdGUG7O9R3NthZcDXE7q7xbtGRB5ncVQDRfKoT5HVfiV6bSDrcfRODiuR59mZgiSYtZG+3kQWYUKn2wagvZKckGukA0SlOuTRCKZhgLcVHhWeRWeGE3iJ8K6BeHf2EgB8Qr6ayTyTUjBcn+u4qqWKgkvG4qRavlvrBSdMrAXWIKE8vSq1od0A2ZzP6+HCsrkuUR+HFfpE2dpjeckoa5vATQgyn8j5x11iIOB9HnT3YKbZ0aTU4rQgYMJXA/fPcgKDGkAPdgtGbQLssy/mwSdsXBYtMgEcs7vI9laR8Ik+NK2dbFHGFPnxS43WToGyKBxojt8SZbgPJXm22WRrN1+9AZvvhI7/mpZiEE7HWgNRClZYuqbfCMpelLGvVq832OLjelrWMJ0XBVNHnOw0p8qZKI1UpqQJXX1nL8j3JttEVHsfryIanM03kNDL0dX1VAKECKUMCVQ6i6tG4VWsR0C2JccPJ3PSoPgo5KMJhuZNaBoiPjZ2eaMREV6vUYbBYzrvdDQzUcE2stacREl4eJzGJ4GP5h08GQmIirGF/SCyZV1CadAbKZVjqb70XpIbE6NT/+84O82LZR4ui5KgTAv87lTZgvNJ7LxM7rRg1awj/iBxQeARNJxuPMPlk1CVx8Z3091UdL1K1avPKa85lCRwCkDKLcJPO9tlqi4dVjCrwpoCJkQMm3fbTl/BgHn00/RsnFZ2qfl5m2DyF+XuaOPauzsRdLUFAC4h44qoUuzRb4Pv6RFhN5CI4fddRKafNBHU9f69UCkO080/hIjTdj0+bpr4oNY4UEi80huyJY/c0iUPE8o48qBB8F3cW30SwhPmuphn4/18lB8GEwEPqoatmli4QRaDFUCUf9Hj0DEUqEAya/OHOW7/PvWcw/l/ZaIMUpOZ6q0xvPDAXokFRJAWzZhG7hNbWNEzQ3f/BjlYlYsBtMY0JUU8mH6YxwIzIGbHiLTBC0OglH0rDd5W+3NaUG9FZ//o9MAP5j2QqwSuFWXppbigh4zk+h17eJn5zhld7dtvOr+YmgYULj6NFIDKBZHUJdqLYScVzdc1p812FCCBcLmmw4RnwuF+RldHixTdy4UZ17T/hD4OLpWCINl9lUAficC0OFeLJLHxFW6Em8SCbZ3aUtFDIQD8oTqzUHZhGWYF2ukrOc8Dzm4FQ8xy3BhqfntTod1gwoilIirsP/z+GGMnTltkqiqK+gCmkVOfICwNFmHltZeJrmDQ4YU5abR09Yr1TaAk3CzWjV1XGBaf/oek0+tFkMOtZNdFRdlzLLE90PsZZFFnZhFBoNoOhYnMB9K2VqgEpJs0nXvF6qBOllptcpBYUYMzMdb0Ggu6m1d/phxuBuOsm+Xtr0Zw8Xd0vxIOQNDGsskCDIEUYWYajw2i66MmRPRyFEennXfLA0WIPpztXvfsrKjf42rjE3RukBsRff1Sci68cel4fGfmvj2y7gW0Tt before_build: From f92dd4122c6d13e4ad57e1fc257c60fe9ff983d5 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 29 Oct 2015 12:21:51 +0100 Subject: [PATCH 02/17] BUG-1852: Added CopyLinkToClipboard property for Imgur [skip ci] --- GreenshotImgurPlugin/ImgurConfiguration.cs | 2 ++ GreenshotImgurPlugin/ImgurPlugin.cs | 28 +++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/GreenshotImgurPlugin/ImgurConfiguration.cs b/GreenshotImgurPlugin/ImgurConfiguration.cs index 4dfb5acb3..2955ad5dc 100644 --- a/GreenshotImgurPlugin/ImgurConfiguration.cs +++ b/GreenshotImgurPlugin/ImgurConfiguration.cs @@ -41,6 +41,8 @@ namespace GreenshotImgurPlugin { public int UploadJpegQuality; [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")] public bool UploadReduceColors; + [IniProperty("CopyLinkToClipboard", Description = "Copy the link, which one is controlled by the UsePageLink, on the clipboard", DefaultValue = "True")] + public bool CopyLinkToClipboard; [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")] public bool UsePageLink; [IniProperty("AnonymousAccess", Description = "Use anonymous access to Imgur", DefaultValue="true")] diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs index 6c7b4c57a..868024325 100644 --- a/GreenshotImgurPlugin/ImgurPlugin.cs +++ b/GreenshotImgurPlugin/ImgurPlugin.cs @@ -194,17 +194,27 @@ namespace GreenshotImgurPlugin { imgurInfo.Image = ImageHelper.CreateThumbnail(tmpImage, 90, 90); } IniConfig.Save(); - try { - if (config.UsePageLink) { - uploadURL = imgurInfo.Page; - ClipboardHelper.SetClipboardData(imgurInfo.Page); - } else { - uploadURL = imgurInfo.Original; + + if (config.UsePageLink) + { + uploadURL = imgurInfo.Page; + } + else + { + uploadURL = imgurInfo.Original; + } + if (string.IsNullOrEmpty(uploadURL) && config.CopyLinkToClipboard) + { + try + { ClipboardHelper.SetClipboardData(imgurInfo.Original); + + } + catch (Exception ex) + { + LOG.Error("Can't write to clipboard: ", ex); + uploadURL = null; } - } catch (Exception ex) { - LOG.Error("Can't write to clipboard: ", ex); - uploadURL = null; } return true; } From 06ae3d4901d07f54aa4713ee5e77a01ebb706ff1 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 29 Oct 2015 12:22:45 +0100 Subject: [PATCH 03/17] BUG-1850: Fixing disposing of WebResponse objects, which might cause the greenshot not responding issue --- Greenshot/Help/HelpFileLoader.cs | 13 +++- GreenshotPlugin/Core/NetworkHelper.cs | 105 +++++++++++++++++--------- 2 files changed, 80 insertions(+), 38 deletions(-) diff --git a/Greenshot/Help/HelpFileLoader.cs b/Greenshot/Help/HelpFileLoader.cs index 93759a850..c3acda86d 100644 --- a/Greenshot/Help/HelpFileLoader.cs +++ b/Greenshot/Help/HelpFileLoader.cs @@ -83,10 +83,15 @@ namespace Greenshot.Help private static HttpStatusCode? GetHttpStatus(string url) { try { HttpWebRequest req = NetworkHelper.CreateWebRequest(url); - HttpWebResponse res = (HttpWebResponse)req.GetResponse(); - return res.StatusCode; - } catch(WebException e) { - if(e.Response != null) return ((HttpWebResponse)e.Response).StatusCode; + using (HttpWebResponse res = (HttpWebResponse)req.GetResponse()) + { + return res.StatusCode; + } + } catch (WebException e) { + if (e.Response != null) + { + return ((HttpWebResponse)e.Response).StatusCode; + } return null; } } diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs index 0acf63bf3..429265834 100644 --- a/GreenshotPlugin/Core/NetworkHelper.cs +++ b/GreenshotPlugin/Core/NetworkHelper.cs @@ -77,12 +77,18 @@ namespace GreenshotPlugin.Core { Uri url = new Uri(baseUri, new Uri("favicon.ico")); try { HttpWebRequest request = CreateWebRequest(url); - HttpWebResponse response = (HttpWebResponse)request.GetResponse(); - if (request.HaveResponse) { - using (Stream responseStream = response.GetResponseStream()) { - if (responseStream != null) { - using (Image image = Image.FromStream(responseStream)) { - return (image.Height > 16 && image.Width > 16) ? new Bitmap(image, 16, 16) : new Bitmap(image); + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + if (request.HaveResponse) + { + using (Stream responseStream = response.GetResponseStream()) + { + if (responseStream != null) + { + using (Image image = Image.FromStream(responseStream)) + { + return (image.Height > 16 && image.Width > 16) ? new Bitmap(image, 16, 16) : new Bitmap(image); + } } } } @@ -424,6 +430,32 @@ namespace GreenshotPlugin.Core { return GetResponseAsString(webRequest, false); } + /// + /// Read the response as string + /// + /// + /// string or null + private static string GetResponseAsString(HttpWebResponse response) + { + string responseData = null; + if (response == null) + { + return null; + } + using (response) + { + Stream responseStream = response.GetResponseStream(); + if (responseStream != null) + { + using (StreamReader reader = new StreamReader(responseStream, true)) + { + responseData = reader.ReadToEnd(); + } + } + } + return responseData; + } + /// /// /// @@ -431,40 +463,43 @@ namespace GreenshotPlugin.Core { /// public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) { string responseData = null; - try { - HttpWebResponse response = (HttpWebResponse) webRequest.GetResponse(); + HttpWebResponse response = null; + bool isHttpError = false; + try { + response = (HttpWebResponse)webRequest.GetResponse(); LOG.InfoFormat("Response status: {0}", response.StatusCode); - bool isHttpError = (int) response.StatusCode >= 300; - DebugHeaders(response); - Stream responseStream = response.GetResponseStream(); - if (responseStream != null) { - using (StreamReader reader = new StreamReader(responseStream, true)) { - responseData = reader.ReadToEnd(); - } - if (isHttpError) { - LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); - } + isHttpError = (int)response.StatusCode >= 300; + if (isHttpError) + { + LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); } - } catch (WebException e) { - HttpWebResponse response = (HttpWebResponse) e.Response; + DebugHeaders(response); + responseData = GetResponseAsString(response); + } catch (WebException e) { + response = (HttpWebResponse) e.Response; if (response != null) { LOG.ErrorFormat("HTTP error {0}", response.StatusCode); - using (Stream responseStream = response.GetResponseStream()) { - if (responseStream != null) { - using (StreamReader streamReader = new StreamReader(responseStream, true)) { - string errorContent = streamReader.ReadToEnd(); - if (alsoReturnContentOnError) { - return errorContent; - } - LOG.ErrorFormat("Content: {0}", errorContent); - } - } + string errorContent = GetResponseAsString(response); + if (alsoReturnContentOnError) + { + return errorContent; } + LOG.ErrorFormat("Content: {0}", errorContent); } LOG.Error("WebException: ", e); throw; } - + finally + { + if (response != null) + { + if (isHttpError) + { + LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); + } + response.Close(); + } + } return responseData; } @@ -477,9 +512,11 @@ namespace GreenshotPlugin.Core { try { HttpWebRequest webRequest = CreateWebRequest(uri); webRequest.Method = HTTPMethod.HEAD.ToString(); - HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); - LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified); - return webResponse.LastModified; + using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) + { + LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified); + return webResponse.LastModified; + } } catch (Exception wE) { LOG.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri); LOG.Warn(wE.Message); From 337f671c2af8dc933e9315f6f1cfd8e90d5d6968 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 29 Oct 2015 12:28:16 +0100 Subject: [PATCH 04/17] Removed tagging, this is done with a Github feature. [skip ci] --- build.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 5327248e2..7e7e2f1d7 100644 --- a/build.ps1 +++ b/build.ps1 @@ -290,5 +290,3 @@ PackagePortable echo "Generating Debug Symbols ZIP" PackageDbgSymbolsZip -echo "build successful, tagging with $fileversion" -TagCode \ No newline at end of file From 7a1b5f80d76d28e40d712a4d4236e11b25d5b72e Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Thu, 5 Nov 2015 22:41:27 +0100 Subject: [PATCH 05/17] fixed imgur key/secret --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 1b2ecabfe..6c9f4bbd9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,9 +26,9 @@ environment: credentials_flickr_consumer_secret: secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw= credentials_imgur_consumer_key: - secure: z8S4QZ3/InPe3dgCf0CNyS0VGKuRyjjP8WMAq+AkK5OZJxZcbIxwobjgelE5CWYL + secure: XRTg1Ecs6ER9m4779CJAng== credentials_imgur_consumer_secret: - secure: ovfXJRorkkKUzbMXuZ4m0U6KF4icngmS+nzSljXJGSKfhI+GNXbMNa//mKYfTCXI + secure: gcCp/gJF8vqmnCUPKyb04H8Oz9mWmiB00U5X7iI/DGr5mxjoCG1khc6/zn6aSSqn credentials_photobucket_consumer_key: secure: oo9GD1Y8dkrli6hMfnnYsw== credentials_photobucket_consumer_secret: @@ -81,4 +81,4 @@ notifications: - jens@getgreenshot.org on_build_success: true on_build_failure: true - on_build_status_changed: false \ No newline at end of file + on_build_status_changed: false From 930061dc947125a2ad6637f4b787ef67946d83da Mon Sep 17 00:00:00 2001 From: RKrom Date: Fri, 6 Nov 2015 07:20:43 +0100 Subject: [PATCH 06/17] Cleanup before fixing [skip ci] --- GreenshotImgurPlugin/ImgurUtils.cs | 63 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index 7e4829a64..ce24270c1 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -33,38 +33,37 @@ namespace GreenshotImgurPlugin { /// public static class ImgurUtils { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ImgurUtils)); - private const string IMGUR_ANONYMOUS_API_KEY = "60e8838e21d6b66"; - private const string SMALL_URL_PATTERN = "http://i.imgur.com/{0}s.png"; - private static ImgurConfiguration config = IniConfig.GetIniSection(); + private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg"; + private static readonly ImgurConfiguration Config = IniConfig.GetIniSection(); /// /// Load the complete history of the imgur uploads, with the corresponding information /// public static void LoadHistory() { - if (config.runtimeImgurHistory.Count == config.ImgurUploadHistory.Count) { + if (Config.runtimeImgurHistory.Count == Config.ImgurUploadHistory.Count) { return; } // Load the ImUr history List hashes = new List(); - foreach(string hash in config.ImgurUploadHistory.Keys) { + foreach(string hash in Config.ImgurUploadHistory.Keys) { hashes.Add(hash); } bool saveNeeded = false; foreach(string hash in hashes) { - if (config.runtimeImgurHistory.ContainsKey(hash)) { + if (Config.runtimeImgurHistory.ContainsKey(hash)) { // Already loaded continue; } try { - ImgurInfo imgurInfo = RetrieveImgurInfo(hash, config.ImgurUploadHistory[hash]); + ImgurInfo imgurInfo = RetrieveImgurInfo(hash, Config.ImgurUploadHistory[hash]); if (imgurInfo != null) { RetrieveImgurThumbnail(imgurInfo); - config.runtimeImgurHistory.Add(hash, imgurInfo); + Config.runtimeImgurHistory.Add(hash, imgurInfo); } else { LOG.DebugFormat("Deleting not found ImgUr {0} from config.", hash); - config.ImgurUploadHistory.Remove(hash); + Config.ImgurUploadHistory.Remove(hash); saveNeeded = true; } } catch (WebException wE) { @@ -74,7 +73,7 @@ namespace GreenshotImgurPlugin { // Image no longer available if (response.StatusCode == HttpStatusCode.Redirect) { LOG.InfoFormat("ImgUr image for hash {0} is no longer available", hash); - config.ImgurUploadHistory.Remove(hash); + Config.ImgurUploadHistory.Remove(hash); redirected = true; } } @@ -96,7 +95,7 @@ namespace GreenshotImgurPlugin { /// /// private static void SetClientId(HttpWebRequest webRequest) { - webRequest.Headers.Add("Authorization", "Client-ID " + IMGUR_ANONYMOUS_API_KEY); + webRequest.Headers.Add("Authorization", "Client-ID " + ImgurCredentials.CONSUMER_KEY); } /// @@ -112,18 +111,18 @@ namespace GreenshotImgurPlugin { IDictionary uploadParameters = new Dictionary(); IDictionary otherParameters = new Dictionary(); // add title - if (title != null && config.AddTitle) { + if (title != null && Config.AddTitle) { otherParameters.Add("title", title); } // add filename - if (filename != null && config.AddFilename) { + if (filename != null && Config.AddFilename) { otherParameters.Add("name", filename); } - string responseString = null; - if (config.AnonymousAccess) { + string responseString; + if (Config.AnonymousAccess) { // add key, we only use the other parameters for the AnonymousAccess //otherParameters.Add("key", IMGUR_ANONYMOUS_API_KEY); - HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST); + HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(Config.ImgurApi3Url + "/upload.xml?" + NetworkHelper.GenerateQueryParameters(otherParameters), HTTPMethod.POST); webRequest.ContentType = "image/" + outputSettings.Format; webRequest.ServicePoint.Expect100Continue = false; @@ -151,17 +150,17 @@ namespace GreenshotImgurPlugin { oAuth.AuthorizeUrl = "http://api.imgur.com/oauth/authorize"; oAuth.RequestTokenUrl = "http://api.imgur.com/oauth/request_token"; oAuth.LoginTitle = "Imgur authorization"; - oAuth.Token = config.ImgurToken; - oAuth.TokenSecret = config.ImgurTokenSecret; + oAuth.Token = Config.ImgurToken; + oAuth.TokenSecret = Config.ImgurTokenSecret; if (string.IsNullOrEmpty(oAuth.Token)) { if (!oAuth.Authorize()) { return null; } if (!string.IsNullOrEmpty(oAuth.Token)) { - config.ImgurToken = oAuth.Token; + Config.ImgurToken = oAuth.Token; } if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { - config.ImgurTokenSecret = oAuth.TokenSecret; + Config.ImgurTokenSecret = oAuth.TokenSecret; } IniConfig.Save(); } @@ -173,10 +172,10 @@ namespace GreenshotImgurPlugin { throw; } finally { if (oAuth.Token != null) { - config.ImgurToken = oAuth.Token; + Config.ImgurToken = oAuth.Token; } if (oAuth.TokenSecret != null) { - config.ImgurTokenSecret = oAuth.TokenSecret; + Config.ImgurTokenSecret = oAuth.TokenSecret; } IniConfig.Save(); } @@ -194,15 +193,17 @@ namespace GreenshotImgurPlugin { return; } LOG.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare); - HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SMALL_URL_PATTERN, imgurInfo.Hash), HTTPMethod.GET); + HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; SetClientId(webRequest); using (WebResponse response = webRequest.GetResponse()) { LogRateLimitInfo(response); Stream responseStream = response.GetResponseStream(); - imgurInfo.Image = Image.FromStream(responseStream); + if (responseStream != null) + { + imgurInfo.Image = Image.FromStream(responseStream); + } } - return; } /// @@ -212,7 +213,7 @@ namespace GreenshotImgurPlugin { /// /// ImgurInfo public static ImgurInfo RetrieveImgurInfo(string hash, string deleteHash) { - string url = config.ImgurApiUrl + "/image/" + hash; + string url = Config.ImgurApiUrl + "/image/" + hash; LOG.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; @@ -247,7 +248,7 @@ namespace GreenshotImgurPlugin { LOG.InfoFormat("Deleting Imgur image for {0}", imgurInfo.DeleteHash); try { - string url = config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash; + string url = Config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash; HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; SetClientId(webRequest); @@ -268,8 +269,8 @@ namespace GreenshotImgurPlugin { } } // Make sure we remove it from the history, if no error occured - config.runtimeImgurHistory.Remove(imgurInfo.Hash); - config.ImgurUploadHistory.Remove(imgurInfo.Hash); + Config.runtimeImgurHistory.Remove(imgurInfo.Hash); + Config.ImgurUploadHistory.Remove(imgurInfo.Hash); imgurInfo.Image = null; } @@ -304,9 +305,9 @@ namespace GreenshotImgurPlugin { LogHeader(nameValues, "X-RateLimit-ClientRemaining"); // Update the credits in the config, this is shown in a form - int credits = 0; + int credits; if (nameValues.ContainsKey("X-RateLimit-Remaining") && int.TryParse(nameValues["X-RateLimit-Remaining"], out credits)) { - config.Credits = credits; + Config.Credits = credits; } } } From 4f9d6eb86551b5a23a14ce118788f9ada215eafd Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 6 Nov 2015 09:31:22 +0100 Subject: [PATCH 07/17] Updated csproj files, so we don't have to migrate every time. Added a fix for BUG-1863: Cannot get access to deleted object, and added some small code quality chances. [skip ci] --- Greenshot/Greenshot.csproj | 5 ++- Greenshot/Helpers/PluginHelper.cs | 2 +- GreenshotBoxPlugin/GreenshotBoxPlugin.csproj | 7 ++- .../GreenshotConfluencePlugin.csproj | 9 +++- .../GreenshotDropboxPlugin.csproj | 7 ++- .../GreenshotExternalCommandPlugin.csproj | 7 ++- GreenshotFlickrPlugin/FlickrPlugin.cs | 2 +- .../GreenshotFlickrPlugin.csproj | 6 ++- .../GreenshotImgurPlugin.csproj | 5 ++- .../GreenshotJiraPlugin.csproj | 9 ++-- .../GreenshotOCRCommand.csproj | 7 ++- GreenshotOCRPlugin/GreenshotOCRPlugin.csproj | 5 ++- .../GreenshotOfficePlugin.csproj | 7 ++- .../GreenshotPhotobucketPlugin.csproj | 7 ++- .../GreenshotPicasaPlugin.csproj | 7 ++- GreenshotPlugin/Core/NetworkHelper.cs | 16 +++++-- GreenshotPlugin/Core/OAuthHelper.cs | 45 +++++++++---------- GreenshotPlugin/Core/SourceForgeHelper.cs | 2 +- GreenshotPlugin/Core/WindowsHelper.cs | 2 +- GreenshotPlugin/GreenshotPlugin.csproj | 7 ++- GreenshotPlugin/UnmanagedHelpers/User32.cs | 2 - 21 files changed, 112 insertions(+), 54 deletions(-) diff --git a/Greenshot/Greenshot.csproj b/Greenshot/Greenshot.csproj index 79b2f4666..ee50aa76a 100644 --- a/Greenshot/Greenshot.csproj +++ b/Greenshot/Greenshot.csproj @@ -1,5 +1,5 @@  - + {CD642BF4-D815-4D67-A0B5-C69F0B8231AF} @@ -18,7 +18,8 @@ 3.5 - + + diff --git a/Greenshot/Helpers/PluginHelper.cs b/Greenshot/Helpers/PluginHelper.cs index 75a300bbf..9062490e3 100644 --- a/Greenshot/Helpers/PluginHelper.cs +++ b/Greenshot/Helpers/PluginHelper.cs @@ -213,7 +213,7 @@ namespace Greenshot.Helpers { /// /// /// - private void findPluginsOnPath(List pluginFiles, String path) { + private void findPluginsOnPath(List pluginFiles, string path) { if (Directory.Exists(path)) { try { foreach (string pluginFile in Directory.GetFiles(path, "*.gsp", SearchOption.AllDirectories)) { diff --git a/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj b/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj index 57a002359..7bc39f15a 100644 --- a/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj +++ b/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj @@ -1,5 +1,5 @@  - + {697CF066-9077-4F22-99D9-D989CCE7282B} @@ -14,6 +14,11 @@ false Always + + + + + 3.5 diff --git a/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj b/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj index a0722875c..b0535116e 100644 --- a/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj +++ b/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj @@ -1,8 +1,8 @@  - + - 1685 + 1685 {C3052651-598A-44E2-AAB3-2E41311D50F9} Library GreenshotConfluencePlugin @@ -15,6 +15,11 @@ false OnBuildSuccess Client + + + + + 3.5 diff --git a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj index a9f9a0092..58f8f231e 100644 --- a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj +++ b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj @@ -1,5 +1,5 @@  - + {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} @@ -14,6 +14,11 @@ false Always + + + + + 3.5 diff --git a/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj b/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj index ca0f6b424..2f534d1b4 100644 --- a/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj +++ b/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj @@ -1,5 +1,5 @@  - + {47F23C86-604E-4CC3-8767-B3D4088F30BB} @@ -14,6 +14,11 @@ false OnBuildSuccess + + + + + 3.5 diff --git a/GreenshotFlickrPlugin/FlickrPlugin.cs b/GreenshotFlickrPlugin/FlickrPlugin.cs index 6e3285afb..ba6210b6e 100644 --- a/GreenshotFlickrPlugin/FlickrPlugin.cs +++ b/GreenshotFlickrPlugin/FlickrPlugin.cs @@ -125,7 +125,7 @@ namespace GreenshotFlickrPlugin _config.ShowConfigDialog(); } - public bool Upload(ICaptureDetails captureDetails, ISurface surface, out String uploadUrl) { + public bool Upload(ICaptureDetails captureDetails, ISurface surface, out string uploadUrl) { SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false); uploadUrl = null; try { diff --git a/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj b/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj index 50ee51535..5c3c047e0 100644 --- a/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj +++ b/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj @@ -1,5 +1,5 @@  - + {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E} @@ -15,6 +15,10 @@ Always 3.5 + + + + diff --git a/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj b/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj index 8cdaff142..6dea91f73 100644 --- a/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj +++ b/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj @@ -1,5 +1,5 @@  - + {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} @@ -17,7 +17,8 @@ 3.5 - + + diff --git a/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj index f844ceb09..671d710a9 100644 --- a/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj +++ b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj @@ -1,5 +1,5 @@  - + {19FEEF09-313F-43C7-819D-F1BCA782B08B} @@ -17,7 +17,8 @@ 3.5 - + + @@ -37,7 +38,9 @@ JiraForm.cs - + + Form + Form diff --git a/GreenshotOCRCommand/GreenshotOCRCommand.csproj b/GreenshotOCRCommand/GreenshotOCRCommand.csproj index 49089a7fb..94b553e26 100644 --- a/GreenshotOCRCommand/GreenshotOCRCommand.csproj +++ b/GreenshotOCRCommand/GreenshotOCRCommand.csproj @@ -1,5 +1,5 @@  - + Debug x86 @@ -20,6 +20,11 @@ Off 4194304 x86 + + + + + 3.5 full diff --git a/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj b/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj index 7d0c78be1..56cbb92ca 100644 --- a/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj +++ b/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj @@ -1,5 +1,5 @@  - + {C6988EE8-2FEE-4349-9F09-F9628A0D8965} @@ -17,7 +17,8 @@ 3.5 - + + diff --git a/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj b/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj index 7709d4fb3..07bf79ccf 100644 --- a/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj +++ b/GreenshotOfficePlugin/GreenshotOfficePlugin.csproj @@ -1,5 +1,5 @@  - + {92599C09-FF29-4ABD-B6E6-C48ECD781BAB} Debug @@ -15,6 +15,11 @@ 4 false + + + + + 3.5 x86 diff --git a/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj index aaa61dcd4..2a5bfe70e 100644 --- a/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj +++ b/GreenshotPhotobucketPlugin/GreenshotPhotobucketPlugin.csproj @@ -1,5 +1,5 @@  - + {9C0ECC4C-7807-4111-916A-4F57BB29788A} @@ -14,6 +14,11 @@ false OnBuildSuccess + + + + + 3.5 diff --git a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj index 67beb0e1b..926f22050 100644 --- a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj +++ b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj @@ -1,5 +1,5 @@  - + {1893A2E4-A78A-4713-A8E7-E70058DABEE0} @@ -13,9 +13,12 @@ 4 false Always - + + 3.5 + + diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs index 429265834..82937517d 100644 --- a/GreenshotPlugin/Core/NetworkHelper.cs +++ b/GreenshotPlugin/Core/NetworkHelper.cs @@ -471,14 +471,20 @@ namespace GreenshotPlugin.Core { isHttpError = (int)response.StatusCode >= 300; if (isHttpError) { - LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); + LOG.ErrorFormat("HTTP error {0}", response.StatusCode); } DebugHeaders(response); responseData = GetResponseAsString(response); - } catch (WebException e) { + if (isHttpError) + { + LOG.ErrorFormat("HTTP response {0}", responseData); + } + } + catch (WebException e) { response = (HttpWebResponse) e.Response; + HttpStatusCode statusCode = response.StatusCode; if (response != null) { - LOG.ErrorFormat("HTTP error {0}", response.StatusCode); + LOG.ErrorFormat("HTTP error {0}", statusCode); string errorContent = GetResponseAsString(response); if (alsoReturnContentOnError) { @@ -487,6 +493,10 @@ namespace GreenshotPlugin.Core { LOG.ErrorFormat("Content: {0}", errorContent); } LOG.Error("WebException: ", e); + if (statusCode == HttpStatusCode.Unauthorized) + { + throw new UnauthorizedAccessException(e.Message); + } throw; } finally diff --git a/GreenshotPlugin/Core/OAuthHelper.cs b/GreenshotPlugin/Core/OAuthHelper.cs index 94b73dc8c..d744caced 100644 --- a/GreenshotPlugin/Core/OAuthHelper.cs +++ b/GreenshotPlugin/Core/OAuthHelper.cs @@ -499,7 +499,7 @@ namespace GreenshotPlugin.Core { /// Authorize the token by showing the dialog /// /// The request token. - private String GetAuthorizeToken() { + private string GetAuthorizeToken() { if (string.IsNullOrEmpty(Token)) { Exception e = new Exception("The request token is not set"); throw e; @@ -532,7 +532,7 @@ namespace GreenshotPlugin.Core { /// Get the access token /// /// The access token. - private String GetAccessToken() { + private string GetAccessToken() { if (string.IsNullOrEmpty(Token) || (CheckVerifier && string.IsNullOrEmpty(Verifier))) { Exception e = new Exception("The request token and verifier were not set"); throw e; @@ -663,39 +663,36 @@ namespace GreenshotPlugin.Core { } try { Sign(method, signUrl, parametersToSign); - + // Join all parameters IDictionary newParameters = new Dictionary(); - foreach(var parameter in parametersToSign) { + foreach (var parameter in parametersToSign) { newParameters.Add(parameter); } if (additionalParameters != null) { - foreach(var parameter in additionalParameters) { + foreach (var parameter in additionalParameters) { newParameters.Add(parameter); } } return MakeRequest(method, requestURL, headers, newParameters, postData); - } catch (WebException wEx) { - lastException = wEx; - if (wEx.Response != null) { - HttpWebResponse response = wEx.Response as HttpWebResponse; - if (response != null && response.StatusCode == HttpStatusCode.Unauthorized) { - Token = null; - TokenSecret = null; - // Remove oauth keys, so they aren't added double - List keysToDelete = new List(); - foreach (string parameterKey in parametersToSign.Keys) { - if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) { - keysToDelete.Add(parameterKey); - } - } - foreach(string keyToDelete in keysToDelete) { - parametersToSign.Remove(keyToDelete); - } - continue; + } catch (UnauthorizedAccessException uaEx) { + lastException = uaEx; + Token = null; + TokenSecret = null; + // Remove oauth keys, so they aren't added double + List keysToDelete = new List(); + foreach (string parameterKey in parametersToSign.Keys) + { + if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) + { + keysToDelete.Add(parameterKey); } } - throw; + foreach (string keyToDelete in keysToDelete) + { + parametersToSign.Remove(keyToDelete); + } + continue; } } if (lastException != null) { diff --git a/GreenshotPlugin/Core/SourceForgeHelper.cs b/GreenshotPlugin/Core/SourceForgeHelper.cs index c54c27ff5..ba1f7098c 100644 --- a/GreenshotPlugin/Core/SourceForgeHelper.cs +++ b/GreenshotPlugin/Core/SourceForgeHelper.cs @@ -97,7 +97,7 @@ namespace GreenshotPlugin.Core { /// public class SourceForgeHelper { private static ILog LOG = LogManager.GetLogger(typeof(SourceForgeHelper)); - private const String RSSFEED = "http://getgreenshot.org/project-feed/"; + private const string RSSFEED = "http://getgreenshot.org/project-feed/"; /// /// This is using the HTTP HEAD Method to check if the RSS Feed is modified after the supplied date diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs index 15dab04d1..4b69f88ad 100644 --- a/GreenshotPlugin/Core/WindowsHelper.cs +++ b/GreenshotPlugin/Core/WindowsHelper.cs @@ -1490,7 +1490,7 @@ namespace GreenshotPlugin.Core { /// /// IntPtr with the windows handle /// String with ClassName - public static String GetClassName(IntPtr hWnd) { + public static string GetClassName(IntPtr hWnd) { StringBuilder classNameBuilder = new StringBuilder(260, 260); User32.GetClassName(hWnd, classNameBuilder, classNameBuilder.Capacity); return classNameBuilder.ToString(); diff --git a/GreenshotPlugin/GreenshotPlugin.csproj b/GreenshotPlugin/GreenshotPlugin.csproj index e9c313f6f..917a12654 100644 --- a/GreenshotPlugin/GreenshotPlugin.csproj +++ b/GreenshotPlugin/GreenshotPlugin.csproj @@ -1,5 +1,5 @@  - + {5B924697-4DCD-4F98-85F1-105CB84B7341} @@ -14,6 +14,11 @@ 4 false + + + + + 3.5 diff --git a/GreenshotPlugin/UnmanagedHelpers/User32.cs b/GreenshotPlugin/UnmanagedHelpers/User32.cs index 90aabc66e..416a38823 100644 --- a/GreenshotPlugin/UnmanagedHelpers/User32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/User32.cs @@ -142,8 +142,6 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern bool ShowScrollBar(IntPtr hwnd, ScrollBarDirection scrollBar, bool show); [DllImport("user32", SetLastError = true)] public static extern int SetScrollPos(IntPtr hWnd, Orientation nBar, int nPos, bool bRedraw); - [DllImport("user32", SetLastError=true)] - public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam); [DllImport("user32", SetLastError = true)] public static extern RegionResult GetWindowRgn(IntPtr hWnd, SafeHandle hRgn); [DllImport("user32", SetLastError = true)] From 750d4ee4f971e8a398d698ad12a47a87634e961a Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 6 Nov 2015 09:53:48 +0100 Subject: [PATCH 08/17] BUG-1864: After uploading to imgur, greenshot does not copy link to clipboard. --- GreenshotImgurPlugin/ImgurPlugin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs index 868024325..c5c354eec 100644 --- a/GreenshotImgurPlugin/ImgurPlugin.cs +++ b/GreenshotImgurPlugin/ImgurPlugin.cs @@ -203,11 +203,11 @@ namespace GreenshotImgurPlugin { { uploadURL = imgurInfo.Original; } - if (string.IsNullOrEmpty(uploadURL) && config.CopyLinkToClipboard) + if (!string.IsNullOrEmpty(uploadURL) && config.CopyLinkToClipboard) { try { - ClipboardHelper.SetClipboardData(imgurInfo.Original); + ClipboardHelper.SetClipboardData(uploadURL); } catch (Exception ex) From 41255df991a974d5d2ddff2de80ce42175a8ae2e Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 6 Nov 2015 10:50:02 +0100 Subject: [PATCH 09/17] Added shallow_clone to appveyor.yml to speed up the build. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 6c9f4bbd9..4cb63923d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,7 @@ branches: skip_tags: true configuration: Release platform: Any CPU +shallow_clone: true clone_depth: 1 assembly_info: patch: true From b64de88b1ec5ffde6e1f452d8246cccd20f61295 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 6 Nov 2015 14:12:30 +0100 Subject: [PATCH 10/17] Making the imgur destination more stable, unfortunately Imgur has issues... --- GreenshotImgurPlugin/ImgurUtils.cs | 74 ++++++++++++++++++--------- GreenshotPlugin/Core/NetworkHelper.cs | 3 +- GreenshotPlugin/Core/OAuthHelper.cs | 16 +++--- appveyor.yml | 4 +- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index ce24270c1..26c786b58 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -35,7 +35,7 @@ namespace GreenshotImgurPlugin { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ImgurUtils)); private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg"; private static readonly ImgurConfiguration Config = IniConfig.GetIniSection(); - + private const string ImgurAnonymousClientId = "60e8838e21d6b66"; /// /// Load the complete history of the imgur uploads, with the corresponding information /// @@ -94,8 +94,8 @@ namespace GreenshotImgurPlugin { /// Use this to make sure Imgur knows from where the upload comes. /// /// - private static void SetClientId(HttpWebRequest webRequest) { - webRequest.Headers.Add("Authorization", "Client-ID " + ImgurCredentials.CONSUMER_KEY); + private static void SetClientId(HttpWebRequest webRequest, string clientId) { + webRequest.Headers.Add("Authorization", "Client-ID " + clientId); } /// @@ -126,7 +126,7 @@ namespace GreenshotImgurPlugin { webRequest.ContentType = "image/" + outputSettings.Format; webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest); + SetClientId(webRequest, ImgurAnonymousClientId); try { using (var requestStream = webRequest.GetRequestStream()) { ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings); @@ -152,17 +152,27 @@ namespace GreenshotImgurPlugin { oAuth.LoginTitle = "Imgur authorization"; oAuth.Token = Config.ImgurToken; oAuth.TokenSecret = Config.ImgurTokenSecret; - if (string.IsNullOrEmpty(oAuth.Token)) { - if (!oAuth.Authorize()) { - return null; + try + { + if (string.IsNullOrEmpty(oAuth.Token)) { + if (!oAuth.Authorize()) { + return null; + } + StoreOAuthToken(oAuth); } - if (!string.IsNullOrEmpty(oAuth.Token)) { - Config.ImgurToken = oAuth.Token; + } + catch (Exception ex) + { + // Retry + LOG.Error(ex); + if (string.IsNullOrEmpty(oAuth.Token)) + { + if (!oAuth.Authorize()) + { + return null; + } + StoreOAuthToken(oAuth); } - if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { - Config.ImgurTokenSecret = oAuth.TokenSecret; - } - IniConfig.Save(); } try { otherParameters.Add("image", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); @@ -171,18 +181,36 @@ namespace GreenshotImgurPlugin { LOG.Error("Upload to imgur gave an exeption: ", ex); throw; } finally { - if (oAuth.Token != null) { - Config.ImgurToken = oAuth.Token; - } - if (oAuth.TokenSecret != null) { - Config.ImgurTokenSecret = oAuth.TokenSecret; - } - IniConfig.Save(); + StoreOAuthToken(oAuth); } } return ImgurInfo.ParseResponse(responseString); } + /// + /// Helper method to store the OAuth output, also if the key is null we need to remove it + /// + /// OAuthSession + private static void StoreOAuthToken(OAuthSession oAuth) + { + bool hasChances = false; + + if (oAuth.Token != Config.ImgurToken) + { + Config.ImgurToken = oAuth.Token; + hasChances = true; + } + if (oAuth.TokenSecret != Config.ImgurTokenSecret) + { + Config.ImgurTokenSecret = oAuth.TokenSecret; + hasChances = true; + } + if (hasChances) + { + IniConfig.Save(); + } + } + /// /// Retrieve the thumbnail of an imgur image /// @@ -195,7 +223,7 @@ namespace GreenshotImgurPlugin { LOG.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest); + SetClientId(webRequest, ImgurCredentials.CONSUMER_KEY); using (WebResponse response = webRequest.GetResponse()) { LogRateLimitInfo(response); Stream responseStream = response.GetResponseStream(); @@ -217,7 +245,7 @@ namespace GreenshotImgurPlugin { LOG.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest); + SetClientId(webRequest, ImgurCredentials.CONSUMER_KEY); string responseString; try { using (WebResponse response = webRequest.GetResponse()) { @@ -251,7 +279,7 @@ namespace GreenshotImgurPlugin { string url = Config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash; HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest); + SetClientId(webRequest, ImgurCredentials.CONSUMER_KEY); string responseString; using (WebResponse response = webRequest.GetResponse()) { LogRateLimitInfo(response); diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs index 82937517d..dc816eab7 100644 --- a/GreenshotPlugin/Core/NetworkHelper.cs +++ b/GreenshotPlugin/Core/NetworkHelper.cs @@ -482,8 +482,9 @@ namespace GreenshotPlugin.Core { } catch (WebException e) { response = (HttpWebResponse) e.Response; - HttpStatusCode statusCode = response.StatusCode; + HttpStatusCode statusCode = HttpStatusCode.Unused; if (response != null) { + statusCode = response.StatusCode; LOG.ErrorFormat("HTTP error {0}", statusCode); string errorContent = GetResponseAsString(response); if (alsoReturnContentOnError) diff --git a/GreenshotPlugin/Core/OAuthHelper.cs b/GreenshotPlugin/Core/OAuthHelper.cs index d744caced..110736f5e 100644 --- a/GreenshotPlugin/Core/OAuthHelper.cs +++ b/GreenshotPlugin/Core/OAuthHelper.cs @@ -476,7 +476,8 @@ namespace GreenshotPlugin.Core { /// /// Get the request token using the consumer key and secret. Also initializes tokensecret /// - private void GetRequestToken() { + /// response, this doesn't need to be used!! + private string GetRequestToken() { IDictionary parameters = new Dictionary(); foreach(var value in _requestTokenParameters) { parameters.Add(value); @@ -493,15 +494,17 @@ namespace GreenshotPlugin.Core { TokenSecret = _requestTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY]; } } + return response; } /// /// Authorize the token by showing the dialog /// + /// Pass the response from the server's request token, so if there is something wrong we can show it. /// The request token. - private string GetAuthorizeToken() { + private string GetAuthorizeToken(string requestTokenResponse) { if (string.IsNullOrEmpty(Token)) { - Exception e = new Exception("The request token is not set"); + Exception e = new Exception("The request token is not set, service responded with: " + requestTokenResponse); throw e; } LOG.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink); @@ -567,13 +570,14 @@ namespace GreenshotPlugin.Core { TokenSecret = null; Verifier = null; LOG.Debug("Creating Token"); - try { - GetRequestToken(); + string requestTokenResponse; + try { + requestTokenResponse = GetRequestToken(); } catch (Exception ex) { LOG.Error(ex); throw new NotSupportedException("Service is not available: " + ex.Message); } - if (string.IsNullOrEmpty(GetAuthorizeToken())) { + if (string.IsNullOrEmpty(GetAuthorizeToken(requestTokenResponse))) { LOG.Debug("User didn't authenticate!"); return false; } diff --git a/appveyor.yml b/appveyor.yml index 4cb63923d..4d9cffd6c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,9 +27,9 @@ environment: credentials_flickr_consumer_secret: secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw= credentials_imgur_consumer_key: - secure: XRTg1Ecs6ER9m4779CJAng== + secure: z8S4QZ3/InPe3dgCf0CNyS0VGKuRyjjP8WMAq+AkK5OZJxZcbIxwobjgelE5CWYL credentials_imgur_consumer_secret: - secure: gcCp/gJF8vqmnCUPKyb04H8Oz9mWmiB00U5X7iI/DGr5mxjoCG1khc6/zn6aSSqn + secure: ovfXJRorkkKUzbMXuZ4m0U6KF4icngmS+nzSljXJGSKfhI+GNXbMNa//mKYfTCXI credentials_photobucket_consumer_key: secure: oo9GD1Y8dkrli6hMfnnYsw== credentials_photobucket_consumer_secret: From 0b60f4a471fe560a133eb5aea81adf5f1d91fa80 Mon Sep 17 00:00:00 2001 From: RKrom Date: Fri, 6 Nov 2015 21:31:09 +0100 Subject: [PATCH 11/17] Rename appveyor.yml to appveyor12.yml, will change the appveyor project to match the names... With this we can make sure that only that project runs which is actually commited to. --- appveyor.yml => appveyor12.yml | 0 appveyor13.yml | 92 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) rename appveyor.yml => appveyor12.yml (100%) create mode 100644 appveyor13.yml diff --git a/appveyor.yml b/appveyor12.yml similarity index 100% rename from appveyor.yml rename to appveyor12.yml diff --git a/appveyor13.yml b/appveyor13.yml new file mode 100644 index 000000000..42be232f5 --- /dev/null +++ b/appveyor13.yml @@ -0,0 +1,92 @@ +version: 1.3.0.{build} +branches: + only: + - 1.3 +skip_tags: true +configuration: Release +platform: Any CPU +shallow_clone: true +assembly_info: + patch: true + file: '**\AssemblyInfo.*' + assembly_version: '{version}' + assembly_file_version: '{version}' + assembly_informational_version: '{version}-$(build_type)-$(APPVEYOR_REPO_COMMIT)' +environment: + credentials_box_client_id: + secure: 8MKxTOowo2fat6cNXGbFfvn6typiEtmCKsrptrWiEFUEoKlT1DUn40iGNcIELRA1 + credentials_box_client_secret: + secure: hJhzDVJuGd/WMnoSXhosvOM/1PGcYlKbtQjA6xyrmnmZcqCTMzqIdA6JXlo/V2Br + credentials_dropbox_consumer_key: + secure: Da/6KY1cu9CUM3iOqSpcUw== + credentials_dropbox_consumer_secret: + secure: KkyKyUY+buT/MZagXDP4cw== + credentials_flickr_consumer_key: + secure: fY8s0OkOMYwCjSZoL/6yZcP8xeT6J2EJLjbUMI5lAW42S5QT2U2B41KrmeP2NpnQ + credentials_flickr_consumer_secret: + secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw= + credentials_imgur_consumer_key: + secure: XRTg1Ecs6ER9m4779CJAng== + credentials_imgur_consumer_secret: + secure: gcCp/gJF8vqmnCUPKyb04H8Oz9mWmiB00U5X7iI/DGr5mxjoCG1khc6/zn6aSSqn + credentials_photobucket_consumer_key: + secure: oo9GD1Y8dkrli6hMfnnYsw== + credentials_photobucket_consumer_secret: + secure: GiNPoe9klM/YkoHIA/YHqOYrIaYwSFK7Ph9m8jT9uPP1l6+Hd5K8dVMw5DNa50oG + credentials_picasa_consumer_key: + secure: bjKXhFZkDqaq98XBrz5oQKQfT8CLpuv2ZAiBIwkzloaAPUs97b5yx6h/xFaE4NLS + credentials_picasa_consumer_secret: + secure: yNptTpmJWypbu9alOQtetxU66drr2FKxoPflNgRJdag= + build_type: ALPHA +before_build: + - nuget restore + - ps: Build/prebuild.ps1 +build: + project: greenshot.sln + verbosity: normal +after_build: +- ps: Build/build.ps1 +test: off +artifacts: +- path: AssemblyDir\Greenshot*INSTALLER*.exe + name: Installer +- path: AssemblyDir\Greenshot*paf.exe + name: Portable +- path: AssemblyDir\Greenshot-NO*.zip + name: Zip +- path: Build\additional_files\readme.txt + name: Readme +- path: AssemblyDir\Greenshot-DEBUGSYMBOLS*.zip + name: DEBUGSYMBOLS +deploy: +- provider: GitHub + tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION) + description: + auth_token: + secure: h0R+O/UoDM5Fy9XBfpRWLxFdR4a6CS+hDxr/MUeiRSviAmUsSlvsGSyOG6KiAVrL + prerelease: true + on: + build_type: RELEASE_CANDIDATE +- provider: GitHub + tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION) + description: + auth_token: + secure: h0R+O/UoDM5Fy9XBfpRWLxFdR4a6CS+hDxr/MUeiRSviAmUsSlvsGSyOG6KiAVrL + prerelease: true + on: + build_type: BETA +- provider: GitHub + tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION) + auth_token: + secure: h0R+O/UoDM5Fy9XBfpRWLxFdR4a6CS+hDxr/MUeiRSviAmUsSlvsGSyOG6KiAVrL + on: + build_type: RELEASE +notifications: +- provider: Email + to: + - robin@getgreenshot.org + - jens@getgreenshot.org + - thomas@getgreenshot.org + on_build_success: true + on_build_failure: true + on_build_status_changed: true \ No newline at end of file From f77d35e1047e3361b473271c41efe31221cef59f Mon Sep 17 00:00:00 2001 From: RKrom Date: Fri, 6 Nov 2015 22:48:19 +0100 Subject: [PATCH 12/17] A small fix to see if our build works... --- GreenshotOfficePlugin/OfficePlugin.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/GreenshotOfficePlugin/OfficePlugin.cs b/GreenshotOfficePlugin/OfficePlugin.cs index 0f90a6243..234171a74 100644 --- a/GreenshotOfficePlugin/OfficePlugin.cs +++ b/GreenshotOfficePlugin/OfficePlugin.cs @@ -31,7 +31,6 @@ namespace GreenshotOfficePlugin { public class OfficePlugin : IGreenshotPlugin { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OfficePlugin)); public static PluginAttribute Attributes; - private IGreenshotHost host; public void Dispose() { Dispose(true); @@ -42,11 +41,8 @@ namespace GreenshotOfficePlugin { //if (disposing) {} } - public OfficePlugin() { - } - public IEnumerable Destinations() { - IDestination destination = null; + IDestination destination; try { destination = new ExcelDestination(); } catch { @@ -100,12 +96,10 @@ namespace GreenshotOfficePlugin { /// /// Implementation of the IGreenshotPlugin.Initialize /// - /// Use the IGreenshotPluginHost interface to register events - /// Use the ICaptureHost interface to register in the MainContextMenu - /// My own attributes + /// Use the IGreenshotPluginHost interface to register events + /// My own attributes /// true if plugin is initialized, false if not (doesn't show) public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) { - this.host = (IGreenshotHost)pluginHost; Attributes = myAttributes; return true; } From 56339b629c9451b32eae816954daaff24fc669de Mon Sep 17 00:00:00 2001 From: RKrom Date: Sat, 7 Nov 2015 11:56:03 +0100 Subject: [PATCH 13/17] BUG-1862: Changed the Imgur API from v2 to v3 --- GreenshotImgurPlugin/ImgurConfiguration.cs | 20 +++- GreenshotImgurPlugin/ImgurInfo.cs | 17 +--- GreenshotImgurPlugin/ImgurUtils.cs | 107 ++++++++------------- appveyor12.yml | 4 +- 4 files changed, 62 insertions(+), 86 deletions(-) diff --git a/GreenshotImgurPlugin/ImgurConfiguration.cs b/GreenshotImgurPlugin/ImgurConfiguration.cs index 2955ad5dc..104839352 100644 --- a/GreenshotImgurPlugin/ImgurConfiguration.cs +++ b/GreenshotImgurPlugin/ImgurConfiguration.cs @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using System; using System.Collections.Generic; using System.Windows.Forms; using Greenshot.IniFile; @@ -47,10 +49,20 @@ namespace GreenshotImgurPlugin { public bool UsePageLink; [IniProperty("AnonymousAccess", Description = "Use anonymous access to Imgur", DefaultValue="true")] public bool AnonymousAccess; - [IniProperty("ImgurToken", Description = "The Imgur token", Encrypted=true, ExcludeIfNull=true)] - public string ImgurToken; - [IniProperty("ImgurTokenSecret", Description = "The Imgur token secret", Encrypted=true, ExcludeIfNull=true)] - public string ImgurTokenSecret; + + [IniProperty("RefreshToken", Description = "Imgur refresh Token", Encrypted = true, ExcludeIfNull = true)] + public string RefreshToken; + + /// + /// AccessToken, not stored + /// + public string AccessToken; + + /// + /// AccessTokenExpires, not stored + /// + public DateTimeOffset AccessTokenExpires; + [IniProperty("AddTitle", Description = "Is the title passed on to Imgur", DefaultValue = "False")] public bool AddTitle; [IniProperty("AddFilename", Description = "Is the filename passed on to Imgur", DefaultValue = "False")] diff --git a/GreenshotImgurPlugin/ImgurInfo.cs b/GreenshotImgurPlugin/ImgurInfo.cs index fd8b61d20..735fe96af 100644 --- a/GreenshotImgurPlugin/ImgurInfo.cs +++ b/GreenshotImgurPlugin/ImgurInfo.cs @@ -166,19 +166,12 @@ namespace GreenshotImgurPlugin } nodes = doc.GetElementsByTagName("datetime"); if(nodes.Count > 0) { - try + // Version 3 has seconds since Epoch + double secondsSince; + if (double.TryParse(nodes.Item(0).InnerText, out secondsSince)) { - imgurInfo.Timestamp = DateTime.Parse(nodes.Item(0).InnerText); - } - catch (Exception) - { - // Version 3 has seconds since Epoch - double secondsSince; - if (double.TryParse(nodes.Item(0).InnerText, out secondsSince)) - { - var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime; - } + var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + imgurInfo.Timestamp = epoch.AddSeconds(secondsSince).DateTime; } } nodes = doc.GetElementsByTagName("original"); diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index 26c786b58..a3a2f14f4 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -35,7 +35,9 @@ namespace GreenshotImgurPlugin { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ImgurUtils)); private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg"; private static readonly ImgurConfiguration Config = IniConfig.GetIniSection(); - private const string ImgurAnonymousClientId = "60e8838e21d6b66"; + private const string AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}"; + private const string TokenUrl = "https://api.imgur.com/oauth2/token"; + /// /// Load the complete history of the imgur uploads, with the corresponding information /// @@ -94,8 +96,8 @@ namespace GreenshotImgurPlugin { /// Use this to make sure Imgur knows from where the upload comes. /// /// - private static void SetClientId(HttpWebRequest webRequest, string clientId) { - webRequest.Headers.Add("Authorization", "Client-ID " + clientId); + private static void SetClientId(HttpWebRequest webRequest) { + webRequest.Headers.Add("Authorization", "Client-ID " + ImgurCredentials.CONSUMER_KEY); } /// @@ -108,7 +110,6 @@ namespace GreenshotImgurPlugin { /// Filename /// ImgurInfo with details public static ImgurInfo UploadToImgur(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { - IDictionary uploadParameters = new Dictionary(); IDictionary otherParameters = new Dictionary(); // add title if (title != null && Config.AddTitle) { @@ -126,7 +127,7 @@ namespace GreenshotImgurPlugin { webRequest.ContentType = "image/" + outputSettings.Format; webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest, ImgurAnonymousClientId); + SetClientId(webRequest); try { using (var requestStream = webRequest.GetRequestStream()) { ImageOutput.SaveToStream(surfaceToUpload, requestStream, outputSettings); @@ -143,74 +144,44 @@ namespace GreenshotImgurPlugin { throw; } } else { - OAuthSession oAuth = new OAuthSession(ImgurCredentials.CONSUMER_KEY, ImgurCredentials.CONSUMER_SECRET); - oAuth.BrowserSize = new Size(650, 500); - oAuth.CallbackUrl = "http://getgreenshot.org"; - oAuth.AccessTokenUrl = "http://api.imgur.com/oauth/access_token"; - oAuth.AuthorizeUrl = "http://api.imgur.com/oauth/authorize"; - oAuth.RequestTokenUrl = "http://api.imgur.com/oauth/request_token"; - oAuth.LoginTitle = "Imgur authorization"; - oAuth.Token = Config.ImgurToken; - oAuth.TokenSecret = Config.ImgurTokenSecret; + + var oauth2Settings = new OAuth2Settings(); + oauth2Settings.AuthUrlPattern = AuthUrlPattern; + oauth2Settings.TokenUrl = TokenUrl; + oauth2Settings.RedirectUrl = "https://imgur.com"; + oauth2Settings.CloudServiceName = "Imgur"; + oauth2Settings.ClientId = ImgurCredentials.CONSUMER_KEY; + oauth2Settings.ClientSecret = ImgurCredentials.CONSUMER_SECRET; + oauth2Settings.AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser; + oauth2Settings.BrowserSize = new Size(680, 880); + + // Copy the settings from the config, which is kept in memory and on the disk + oauth2Settings.RefreshToken = Config.RefreshToken; + oauth2Settings.AccessToken = Config.AccessToken; + oauth2Settings.AccessTokenExpires = Config.AccessTokenExpires; + try { - if (string.IsNullOrEmpty(oAuth.Token)) { - if (!oAuth.Authorize()) { - return null; - } - StoreOAuthToken(oAuth); - } - } - catch (Exception ex) - { - // Retry - LOG.Error(ex); - if (string.IsNullOrEmpty(oAuth.Token)) - { - if (!oAuth.Authorize()) - { - return null; - } - StoreOAuthToken(oAuth); - } - } - try { + var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, Config.ImgurApi3Url + "upload.xml", oauth2Settings); otherParameters.Add("image", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); - responseString = oAuth.MakeOAuthRequest(HTTPMethod.POST, "http://api.imgur.com/2/account/images.xml", uploadParameters, otherParameters, null); - } catch (Exception ex) { - LOG.Error("Upload to imgur gave an exeption: ", ex); - throw; - } finally { - StoreOAuthToken(oAuth); + + NetworkHelper.WriteMultipartFormData(webRequest, otherParameters); + + responseString = NetworkHelper.GetResponseAsString(webRequest); + } + finally + { + // Copy the settings back to the config, so they are stored. + Config.RefreshToken = oauth2Settings.RefreshToken; + Config.AccessToken = oauth2Settings.AccessToken; + Config.AccessTokenExpires = oauth2Settings.AccessTokenExpires; + Config.IsDirty = true; + IniConfig.Save(); } } return ImgurInfo.ParseResponse(responseString); } - /// - /// Helper method to store the OAuth output, also if the key is null we need to remove it - /// - /// OAuthSession - private static void StoreOAuthToken(OAuthSession oAuth) - { - bool hasChances = false; - - if (oAuth.Token != Config.ImgurToken) - { - Config.ImgurToken = oAuth.Token; - hasChances = true; - } - if (oAuth.TokenSecret != Config.ImgurTokenSecret) - { - Config.ImgurTokenSecret = oAuth.TokenSecret; - hasChances = true; - } - if (hasChances) - { - IniConfig.Save(); - } - } - /// /// Retrieve the thumbnail of an imgur image /// @@ -223,7 +194,7 @@ namespace GreenshotImgurPlugin { LOG.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest, ImgurCredentials.CONSUMER_KEY); + SetClientId(webRequest); using (WebResponse response = webRequest.GetResponse()) { LogRateLimitInfo(response); Stream responseStream = response.GetResponseStream(); @@ -245,7 +216,7 @@ namespace GreenshotImgurPlugin { LOG.InfoFormat("Retrieving Imgur info for {0} with url {1}", hash, url); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest, ImgurCredentials.CONSUMER_KEY); + SetClientId(webRequest); string responseString; try { using (WebResponse response = webRequest.GetResponse()) { @@ -279,7 +250,7 @@ namespace GreenshotImgurPlugin { string url = Config.ImgurApiUrl + "/delete/" + imgurInfo.DeleteHash; HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - SetClientId(webRequest, ImgurCredentials.CONSUMER_KEY); + SetClientId(webRequest); string responseString; using (WebResponse response = webRequest.GetResponse()) { LogRateLimitInfo(response); diff --git a/appveyor12.yml b/appveyor12.yml index 4d9cffd6c..4cb63923d 100644 --- a/appveyor12.yml +++ b/appveyor12.yml @@ -27,9 +27,9 @@ environment: credentials_flickr_consumer_secret: secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw= credentials_imgur_consumer_key: - secure: z8S4QZ3/InPe3dgCf0CNyS0VGKuRyjjP8WMAq+AkK5OZJxZcbIxwobjgelE5CWYL + secure: XRTg1Ecs6ER9m4779CJAng== credentials_imgur_consumer_secret: - secure: ovfXJRorkkKUzbMXuZ4m0U6KF4icngmS+nzSljXJGSKfhI+GNXbMNa//mKYfTCXI + secure: gcCp/gJF8vqmnCUPKyb04H8Oz9mWmiB00U5X7iI/DGr5mxjoCG1khc6/zn6aSSqn credentials_photobucket_consumer_key: secure: oo9GD1Y8dkrli6hMfnnYsw== credentials_photobucket_consumer_secret: From 3ccc1c0f9f12bef6a6d120a052db712f6de89208 Mon Sep 17 00:00:00 2001 From: RKrom Date: Sat, 7 Nov 2015 15:39:41 +0100 Subject: [PATCH 14/17] Fix for missing / --- .../releases/additional_files/readme.txt.template | 15 ++++++++++----- GreenshotImgurPlugin/ImgurUtils.cs | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Greenshot/releases/additional_files/readme.txt.template b/Greenshot/releases/additional_files/readme.txt.template index c1431d230..52cd4ff5a 100644 --- a/Greenshot/releases/additional_files/readme.txt.template +++ b/Greenshot/releases/additional_files/readme.txt.template @@ -9,12 +9,17 @@ All details to our tickets can be found here: https://greenshot.atlassian.net @DETAILVERSION@ -Bugs Resolved: -* BUG-1850: Greenshot stops responding +There were some major issues with the non anonymous uploads to Imgur, after contacting Imgur they told us that their old API was deprecated or disabled, unfortunately this was not communicated. Although we are working hard on Greenshot 1.3 we did see a need to fix the imgur uploads, so we moved to their new API as quickly as was possible. This should resolve a lot of tickets that were reported to us. -Workaround: -* BUG-1852: When using Imgur & clipboard destinations, the imgur export Uri overwrites the clipboard image - -> Change the CopyLinkToClipboard flag to false in the greenshot.ini +Bugs Resolved: + +BUG-1850: Greenshot stops responding +BUG-1864: Imgur link wasn't copied to the clipboard + + +Known bugs: +* BUG-1852: When using the Imgur & clipboard destinations together, the imgur export Uri overwrites the clipboard image + The current workaround -> Change the CopyLinkToClipboard flag to false in the greenshot.ini 1.2.7.2-342a506 RELEASE diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index a3a2f14f4..3bb80e0f8 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -162,7 +162,7 @@ namespace GreenshotImgurPlugin { try { - var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, Config.ImgurApi3Url + "upload.xml", oauth2Settings); + var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, Config.ImgurApi3Url + "/upload.xml", oauth2Settings); otherParameters.Add("image", new SurfaceContainer(surfaceToUpload, outputSettings, filename)); NetworkHelper.WriteMultipartFormData(webRequest, otherParameters); From c2b0bb98b46d3ccd3bc8e3c63b3b7ff925871e64 Mon Sep 17 00:00:00 2001 From: RKrom Date: Sat, 7 Nov 2015 23:05:17 +0100 Subject: [PATCH 15/17] BUG-1850: minimizing the impact of SF down --- Greenshot/Helpers/UpdateHelper.cs | 36 +++++++++++------------ GreenshotPlugin/Core/SourceForgeHelper.cs | 8 ++++- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Greenshot/Helpers/UpdateHelper.cs b/Greenshot/Helpers/UpdateHelper.cs index a8a5bcda1..723331d25 100644 --- a/Greenshot/Helpers/UpdateHelper.cs +++ b/Greenshot/Helpers/UpdateHelper.cs @@ -34,21 +34,20 @@ namespace Greenshot.Experimental { /// Description of RssFeedHelper. /// public static class UpdateHelper { - private static ILog LOG = LogManager.GetLogger(typeof(UpdateHelper)); + private static readonly ILog LOG = LogManager.GetLogger(typeof(UpdateHelper)); private static CoreConfiguration conf = IniConfig.GetIniSection(); private const string STABLE_DOWNLOAD_LINK = "http://getgreenshot.org/downloads/"; private const string VERSION_HISTORY_LINK = "http://getgreenshot.org/version-history/"; - private static object lockObject = new object(); - private static SourceforgeFile latestGreenshot; - private static SourceforgeFile currentGreenshot; - private static string downloadLink = STABLE_DOWNLOAD_LINK; + private static readonly object LockObject = new object(); + private static SourceforgeFile _latestGreenshot; + private static string _downloadLink = STABLE_DOWNLOAD_LINK; /// /// Is an update check needed? /// /// bool true if yes public static bool IsUpdateCheckNeeded() { - lock (lockObject) { + lock (LockObject) { if (conf.UpdateCheckInterval == 0) { return false; } @@ -60,7 +59,7 @@ namespace Greenshot.Experimental { return false; } LOG.DebugFormat("Update check is due, last check was {0} check needs to be made after {1} (which is one {2} later)", conf.LastUpdateCheck, checkTime, conf.UpdateCheckInterval); - if (!SourceForgeHelper.isRSSModifiedAfter(conf.LastUpdateCheck)) { + if (!SourceForgeHelper.IsRSSModifiedAfter(conf.LastUpdateCheck)) { LOG.DebugFormat("RSS feed has not been updated since after {0}", conf.LastUpdateCheck); return false; } @@ -73,18 +72,18 @@ namespace Greenshot.Experimental { /// Read the RSS feed to see if there is a Greenshot update /// public static void CheckAndAskForUpdate() { - lock (lockObject) { + lock (LockObject) { Version currentVersion = Assembly.GetExecutingAssembly().GetName().Version; // Test like this: // currentVersion = new Version("0.8.1.1198"); try { - latestGreenshot = null; + _latestGreenshot = null; ProcessRSSInfo(currentVersion); - if (latestGreenshot != null) { + if (_latestGreenshot != null) { MainForm.Instance.NotifyIcon.BalloonTipClicked += HandleBalloonTipClick; MainForm.Instance.NotifyIcon.BalloonTipClosed += CleanupBalloonTipClick; - MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", Language.GetFormattedString(LangKey.update_found, "'" + latestGreenshot.File + "'"), ToolTipIcon.Info); + MainForm.Instance.NotifyIcon.ShowBalloonTip(10000, "Greenshot", Language.GetFormattedString(LangKey.update_found, "'" + _latestGreenshot.File + "'"), ToolTipIcon.Info); } conf.LastUpdateCheck = DateTime.Now; } catch (Exception e) { @@ -100,14 +99,14 @@ namespace Greenshot.Experimental { private static void HandleBalloonTipClick(object sender, EventArgs e) { try { - if (latestGreenshot != null) { + if (_latestGreenshot != null) { // "Direct" download link // Process.Start(latestGreenshot.Link); // Go to getgreenshot.org - Process.Start(downloadLink); + Process.Start(_downloadLink); } } catch (Exception) { - MessageBox.Show(Language.GetFormattedString(LangKey.error_openlink, downloadLink), Language.GetString(LangKey.error)); + MessageBox.Show(Language.GetFormattedString(LangKey.error_openlink, _downloadLink), Language.GetString(LangKey.error)); } finally { CleanupBalloonTipClick(sender, e); } @@ -158,18 +157,17 @@ namespace Greenshot.Experimental { int versionCompare = rssFile.Version.CompareTo(currentVersion); if (versionCompare > 0) { LOG.DebugFormat("Found newer Greenshot '{0}' with version {1} published at {2} : {3}", file, rssFile.Version, rssFile.Pubdate.ToLocalTime(), rssFile.Link); - if (latestGreenshot == null || rssFile.Version.CompareTo(latestGreenshot.Version) > 0) { - latestGreenshot = rssFile; + if (_latestGreenshot == null || rssFile.Version.CompareTo(_latestGreenshot.Version) > 0) { + _latestGreenshot = rssFile; if (rssFile.isReleaseCandidate || rssFile.isUnstable) { - downloadLink = VERSION_HISTORY_LINK; + _downloadLink = VERSION_HISTORY_LINK; } else { - downloadLink = STABLE_DOWNLOAD_LINK; + _downloadLink = STABLE_DOWNLOAD_LINK; } } } else if (versionCompare < 0) { LOG.DebugFormat("Skipping older greenshot with version {0}", rssFile.Version); } else if (versionCompare == 0) { - currentGreenshot = rssFile; LOG.DebugFormat("Found current version as exe {0} with version {1} published at {2} : {3}", file, rssFile.Version, rssFile.Pubdate.ToLocalTime(), rssFile.Link); } } diff --git a/GreenshotPlugin/Core/SourceForgeHelper.cs b/GreenshotPlugin/Core/SourceForgeHelper.cs index ba1f7098c..3a027cbbb 100644 --- a/GreenshotPlugin/Core/SourceForgeHelper.cs +++ b/GreenshotPlugin/Core/SourceForgeHelper.cs @@ -104,8 +104,14 @@ namespace GreenshotPlugin.Core { /// /// DateTime /// true if the feed is newer - public static bool isRSSModifiedAfter(DateTime updateTime) { + public static bool IsRSSModifiedAfter(DateTime updateTime) { DateTime lastModified = NetworkHelper.GetLastModified(new Uri(RSSFEED)); + if (lastModified == DateTime.MinValue) + { + // Time could not be read, just take now and add one hour to it. + // This assist BUG-1850 + lastModified = DateTime.Now.AddHours(1); + } return updateTime.CompareTo(lastModified) < 0; } From 0fe30831229096451ba9b7dcb9d99351ca75e557 Mon Sep 17 00:00:00 2001 From: RKrom Date: Sat, 7 Nov 2015 23:10:08 +0100 Subject: [PATCH 16/17] FEATURE-896: Added HTTPS to the Imgur links --- .../additional_files/readme.txt.template | 2 + GreenshotImgurPlugin/ImgurInfo.cs | 92 ++++++++++--------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/Greenshot/releases/additional_files/readme.txt.template b/Greenshot/releases/additional_files/readme.txt.template index 52cd4ff5a..67fc3834f 100644 --- a/Greenshot/releases/additional_files/readme.txt.template +++ b/Greenshot/releases/additional_files/readme.txt.template @@ -16,6 +16,8 @@ Bugs Resolved: BUG-1850: Greenshot stops responding BUG-1864: Imgur link wasn't copied to the clipboard +Features: +FEATURE-896: Use Imgur with HTTPS (with changing the Imgur API from V2 to V3 this was already required for the upload anyway.) Known bugs: * BUG-1852: When using the Imgur & clipboard destinations together, the imgur export Uri overwrites the clipboard image diff --git a/GreenshotImgurPlugin/ImgurInfo.cs b/GreenshotImgurPlugin/ImgurInfo.cs index 735fe96af..37e5a3ce8 100644 --- a/GreenshotImgurPlugin/ImgurInfo.cs +++ b/GreenshotImgurPlugin/ImgurInfo.cs @@ -29,10 +29,11 @@ namespace GreenshotImgurPlugin /// public class ImgurInfo : IDisposable { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ImgurInfo)); - private string hash; - public string Hash { - get {return hash;} - set {hash = value;} + + public string Hash + { + get; + set; } private string deleteHash; @@ -40,57 +41,58 @@ namespace GreenshotImgurPlugin get {return deleteHash;} set { deleteHash = value; - deletePage = "http://imgur.com/delete/" + value; + DeletePage = "https://imgur.com/delete/" + value; } } - private string title; - public string Title { - get {return title;} - set {title = value;} + public string Title + { + get; + set; } - private string imageType; - public string ImageType { - get {return imageType;} - set {imageType = value;} + public string ImageType + { + get; + set; } - private DateTime timestamp; - public DateTime Timestamp { - get {return timestamp;} - set {timestamp = value;} + public DateTime Timestamp + { + get; + set; } - private string original; - public string Original { - get {return original;} - set {original = value;} + public string Original + { + get; + set; } - private string page; - public string Page { - get {return page;} - set {page = value;} + public string Page + { + get; + set; } - private string smallSquare; - public string SmallSquare { - get {return smallSquare;} - set {smallSquare = value;} + public string SmallSquare + { + get; + set; } - private string largeThumbnail; - public string LargeThumbnail { - get {return largeThumbnail;} - set {largeThumbnail = value;} + public string LargeThumbnail + { + get; + set; } - private string deletePage; - public string DeletePage { - get {return deletePage;} - set {deletePage = value;} + public string DeletePage + { + get; + set; } + private Image image; public Image Image { get {return image;} @@ -175,32 +177,34 @@ namespace GreenshotImgurPlugin } } nodes = doc.GetElementsByTagName("original"); - if(nodes.Count > 0) { - imgurInfo.Original = nodes.Item(0).InnerText; + if (nodes.Count > 0) + { + imgurInfo.Original = nodes.Item(0).InnerText.Replace("http:", "https:"); } // Version 3 API only has Link nodes = doc.GetElementsByTagName("link"); if (nodes.Count > 0) { - imgurInfo.Original = nodes.Item(0).InnerText; + imgurInfo.Original = nodes.Item(0).InnerText.Replace("http:", "https:"); } nodes = doc.GetElementsByTagName("imgur_page"); if (nodes.Count > 0) { - imgurInfo.Page = nodes.Item(0).InnerText; + imgurInfo.Page = nodes.Item(0).InnerText.Replace("http:", "https:"); } else { // Version 3 doesn't have a page link in the response - imgurInfo.Page = string.Format("http://imgur.com/{0}", imgurInfo.Hash); + imgurInfo.Page = string.Format("https://imgur.com/{0}", imgurInfo.Hash); } nodes = doc.GetElementsByTagName("small_square"); if(nodes.Count > 0) { imgurInfo.SmallSquare = nodes.Item(0).InnerText; } nodes = doc.GetElementsByTagName("large_thumbnail"); - if(nodes.Count > 0) { - imgurInfo.LargeThumbnail = nodes.Item(0).InnerText; + if(nodes.Count > 0) + { + imgurInfo.LargeThumbnail = nodes.Item(0).InnerText.Replace("http:", "https:"); } } catch(Exception e) { LOG.ErrorFormat("Could not parse Imgur response due to error {0}, response was: {1}", e.Message, response); From cab854b7229994fc9e4deaccd47885df500d7e1a Mon Sep 17 00:00:00 2001 From: RKrom Date: Tue, 10 Nov 2015 11:56:51 +0100 Subject: [PATCH 17/17] Changes for the 1.2.8 release --- .../additional_files/readme.txt.template | 18 +++++++++++++----- appveyor12.yml | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Greenshot/releases/additional_files/readme.txt.template b/Greenshot/releases/additional_files/readme.txt.template index 67fc3834f..0881700f2 100644 --- a/Greenshot/releases/additional_files/readme.txt.template +++ b/Greenshot/releases/additional_files/readme.txt.template @@ -9,19 +9,27 @@ All details to our tickets can be found here: https://greenshot.atlassian.net @DETAILVERSION@ -There were some major issues with the non anonymous uploads to Imgur, after contacting Imgur they told us that their old API was deprecated or disabled, unfortunately this was not communicated. Although we are working hard on Greenshot 1.3 we did see a need to fix the imgur uploads, so we moved to their new API as quickly as was possible. This should resolve a lot of tickets that were reported to us. +There were some major issues with the authenticated (non anonymous) uploads to Imgur. +After contacting Imgur they told us that their old API was deprecated or disabled, unfortunately this was not communicated. +Although we are working hard on Greenshot 1.3, where we changed most of the Imgur code already, we can't release it. +We did see a need to fix the imgur uploads, so in this release we quickly updated the Imgur API. +This should resolve a lot of tickets that were reported to us. + +Additionally our website http://getgreenshot.org is hosted by sourceforge and they seem to have a lot of stability problems. +Due to these problems a bug in the Greenshot update check manifested itself and causes Greenshot to get slow or even stop responding. +In this version we fix the bug in the update check, and we are also working on a solution for the instability with our website. + +Here is the list of chances: Bugs Resolved: -BUG-1850: Greenshot stops responding +BUG-1527 / BUG-1848 / BUG-1850 / BUG-1851 / BUG-1859 : Greenshot stops responding, hangs or crashes +BUG-1843 / BUG-1844 / BUG-1846 : Imgur problems with authenticated uploads BUG-1864: Imgur link wasn't copied to the clipboard Features: FEATURE-896: Use Imgur with HTTPS (with changing the Imgur API from V2 to V3 this was already required for the upload anyway.) -Known bugs: -* BUG-1852: When using the Imgur & clipboard destinations together, the imgur export Uri overwrites the clipboard image - The current workaround -> Change the CopyLinkToClipboard flag to false in the greenshot.ini 1.2.7.2-342a506 RELEASE diff --git a/appveyor12.yml b/appveyor12.yml index 4cb63923d..e8532425e 100644 --- a/appveyor12.yml +++ b/appveyor12.yml @@ -38,7 +38,7 @@ environment: secure: bjKXhFZkDqaq98XBrz5oQKQfT8CLpuv2ZAiBIwkzloaAPUs97b5yx6h/xFaE4NLS credentials_picasa_consumer_secret: secure: yNptTpmJWypbu9alOQtetxU66drr2FKxoPflNgRJdag= - build_type: UNSTABLE + build_type: RELEASE rsakey: secure: GNomwdlwZOCyd8d7xEWTnMVs1lpOeHvF+tlnvcbXGovLRtwAp2Ufu0r7paGY7BHGGkIs2WE7xUfyQ9UauVB+58JZ6fwVega8ucUgVJhl4x0QQNN2d6sULUhHfhuEHmxw+FDO/FxKFE6Lmf+ZRY+OGiw0wKIl4qD7mGRHcDQTipNEsTbau8HzqRVCdu3dx7pODC61DlsbO71xLF7UlqnmuZE+91Zz3V6AgaqE246n1499d6bXBYw1AH+8opNnKDFLnTHf7hUVcZn9mj6tKZXeTCuVUOr/SVQcgHKxlBlqzhfaEkxCR5GPtzQRqwDMxEycmFvj2wNP/sie6UEGhQxE4YMCc2OgqNOkpc5BbP/fxLr/SLFOEf1XXzTWCFMhsgpHx7TZbgQH26sa0rK/xaBRacZlwAaNk7V2nFZT7TebYEFy6zWNr9Y+IyeXIofj42XQTNXv8d8hyh+UYLByVEFYRf2DnActQkZQyNdWjZ+CxDV50QSZZs8FT3IIqraHYKsj2ITAN5LrUtWCi7bpNJL0UGo0EJiB2i0bp++tEAAwyrCljxI8d4bbGl/flHk/xd+ysQPnomndijeObjguEzqT8pyXZluSZhF+lI50mIDhMdtdAfMi5yn5RW7P6NWOSlC8xgQQgMZylsuSvRflKbEd/gsoDyEOnakNcdH2jekt9OD6GnuYM7iHkbMC89LBZ0VaHNGvCC+BQXdGUG7O9R3NthZcDXE7q7xbtGRB5ncVQDRfKoT5HVfiV6bSDrcfRODiuR59mZgiSYtZG+3kQWYUKn2wagvZKckGukA0SlOuTRCKZhgLcVHhWeRWeGE3iJ8K6BeHf2EgB8Qr6ayTyTUjBcn+u4qqWKgkvG4qRavlvrBSdMrAXWIKE8vSq1od0A2ZzP6+HCsrkuUR+HFfpE2dpjeckoa5vATQgyn8j5x11iIOB9HnT3YKbZ0aTU4rQgYMJXA/fPcgKDGkAPdgtGbQLssy/mwSdsXBYtMgEcs7vI9laR8Ik+NK2dbFHGFPnxS43WToGyKBxojt8SZbgPJXm22WRrN1+9AZvvhI7/mpZiEE7HWgNRClZYuqbfCMpelLGvVq832OLjelrWMJ0XBVNHnOw0p8qZKI1UpqQJXX1nL8j3JttEVHsfryIanM03kNDL0dX1VAKECKUMCVQ6i6tG4VWsR0C2JccPJ3PSoPgo5KMJhuZNaBoiPjZ2eaMREV6vUYbBYzrvdDQzUcE2stacREl4eJzGJ4GP5h08GQmIirGF/SCyZV1CadAbKZVjqb70XpIbE6NT/+84O82LZR4ui5KgTAv87lTZgvNJ7LxM7rRg1awj/iBxQeARNJxuPMPlk1CVx8Z3091UdL1K1avPKa85lCRwCkDKLcJPO9tlqi4dVjCrwpoCJkQMm3fbTl/BgHn00/RsnFZ2qfl5m2DyF+XuaOPauzsRdLUFAC4h44qoUuzRb4Pv6RFhN5CI4fddRKafNBHU9f69UCkO080/hIjTdj0+bpr4oNY4UEi80huyJY/c0iUPE8o48qBB8F3cW30SwhPmuphn4/18lB8GEwEPqoatmli4QRaDFUCUf9Hj0DEUqEAya/OHOW7/PvWcw/l/ZaIMUpOZ6q0xvPDAXokFRJAWzZhG7hNbWNEzQ3f/BjlYlYsBtMY0JUU8mH6YxwIzIGbHiLTBC0OglH0rDd5W+3NaUG9FZ//o9MAP5j2QqwSuFWXppbigh4zk+h17eJn5zhld7dtvOr+YmgYULj6NFIDKBZHUJdqLYScVzdc1p812FCCBcLmmw4RnwuF+RldHixTdy4UZ17T/hD4OLpWCINl9lUAficC0OFeLJLHxFW6Em8SCbZ3aUtFDIQD8oTqzUHZhGWYF2ukrOc8Dzm4FQ8xy3BhqfntTod1gwoilIirsP/z+GGMnTltkqiqK+gCmkVOfICwNFmHltZeJrmDQ4YU5abR09Yr1TaAk3CzWjV1XGBaf/oek0+tFkMOtZNdFRdlzLLE90PsZZFFnZhFBoNoOhYnMB9K2VqgEpJs0nXvF6qBOllptcpBYUYMzMdb0Ggu6m1d/phxuBuOsm+Xtr0Zw8Xd0vxIOQNDGsskCDIEUYWYajw2i66MmRPRyFEennXfLA0WIPpztXvfsrKjf42rjE3RukBsRff1Sci68cel4fGfmvj2y7gW0Tt before_build: