From 56339b629c9451b32eae816954daaff24fc669de Mon Sep 17 00:00:00 2001 From: RKrom Date: Sat, 7 Nov 2015 11:56:03 +0100 Subject: [PATCH] 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: