OAuth refactoring, making Photobucket work.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2073 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2012-09-20 11:37:47 +00:00
parent 55f59b34f7
commit 8b8024e20c
5 changed files with 185 additions and 140 deletions

View file

@ -137,23 +137,19 @@ namespace GreenshotImgurPlugin {
} }
} else { } else {
OAuthSession oAuth = new OAuthSession(); OAuthSession oAuth = new OAuthSession(ImgurCredentials.CONSUMER_KEY, ImgurCredentials.CONSUMER_SECRET);
oAuth.BrowserWidth = 650; oAuth.BrowserSize = new Size(650, 500);
oAuth.BrowserHeight = 500;
oAuth.CallbackUrl = "http://getgreenshot.org"; oAuth.CallbackUrl = "http://getgreenshot.org";
oAuth.AccessTokenUrl = "http://api.imgur.com/oauth/access_token"; oAuth.AccessTokenUrl = "http://api.imgur.com/oauth/access_token";
oAuth.AuthorizeUrl = "http://api.imgur.com/oauth/authorize"; oAuth.AuthorizeUrl = "http://api.imgur.com/oauth/authorize";
oAuth.RequestTokenUrl = "http://api.imgur.com/oauth/request_token"; oAuth.RequestTokenUrl = "http://api.imgur.com/oauth/request_token";
oAuth.ConsumerKey = ImgurCredentials.CONSUMER_KEY;
oAuth.ConsumerSecret = ImgurCredentials.CONSUMER_SECRET;
oAuth.UserAgent = "Greenshot";
oAuth.LoginTitle = "Imgur authorization"; oAuth.LoginTitle = "Imgur authorization";
//oAuth.UseHTTPHeadersForAuthorization = false; //oAuth.UseHTTPHeadersForAuthorization = false;
oAuth.Token = config.ImgurToken; oAuth.Token = config.ImgurToken;
oAuth.TokenSecret = config.ImgurTokenSecret; oAuth.TokenSecret = config.ImgurTokenSecret;
try { try {
LOG.DebugFormat("Test: {0}", oAuth.oAuthWebRequest(HTTPMethod.GET, "http://api.imgur.com/2/account", null)); LOG.DebugFormat("Test: {0}", oAuth.MakeOAuthRequest(HTTPMethod.GET, "http://api.imgur.com/2/account", null));
responseString = oAuth.oAuthWebRequest(HTTPMethod.POST, "http://api.imgur.com/2/account/images.xml", uploadParameters); responseString = oAuth.MakeOAuthRequest(HTTPMethod.POST, "http://api.imgur.com/2/account/images.xml", uploadParameters);
} catch (Exception ex) { } catch (Exception ex) {
LOG.Error("Upload to imgur gave an exeption: ", ex); LOG.Error("Upload to imgur gave an exeption: ", ex);
throw ex; throw ex;

View file

@ -40,10 +40,12 @@ namespace GreenshotPhotobucketPlugin {
public bool UploadReduceColors; public bool UploadReduceColors;
[IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")] [IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
public bool UsePageLink; public bool UsePageLink;
[IniProperty("PhotobucketToken", Description = "The Photobucket token", Encrypted=true, ExcludeIfNull=true)] [IniProperty("Token", Description = "The Photobucket token", Encrypted=true, ExcludeIfNull=true)]
public string PhotobucketToken; public string Token;
[IniProperty("PhotobucketTokenSecret", Description = "The Photobucket token secret", Encrypted=true, ExcludeIfNull=true)] [IniProperty("TokenSecret", Description = "The Photobucket token secret", Encrypted=true, ExcludeIfNull=true)]
public string PhotobucketTokenSecret; public string TokenSecret;
[IniProperty("SubDomain", Description = "The Photobucket api subdomain", Encrypted = true, ExcludeIfNull = true)]
public string SubDomain;
public int Credits { public int Credits {
get; get;

View file

@ -50,48 +50,62 @@ namespace GreenshotPhotobucketPlugin {
public static PhotobucketInfo UploadToPhotobucket(byte[] imageData, int dataLength, string title, string filename) { public static PhotobucketInfo UploadToPhotobucket(byte[] imageData, int dataLength, string title, string filename) {
string responseString; string responseString;
OAuthSession oAuth = new OAuthSession(); OAuthSession oAuth = new OAuthSession("149833145", "ebd828180b11103c010c7e71c66f6bcb");
oAuth.CheckVerifier = false;
// This url is configured in the Photobucket API settings in the Photobucket site!! // This url is configured in the Photobucket API settings in the Photobucket site!!
oAuth.CallbackUrl = "http://getgreenshot.org"; oAuth.CallbackUrl = "http://getgreenshot.org";
oAuth.AccessTokenUrl = "http://api.photobucket.com/login/access"; oAuth.AccessTokenUrl = "http://api.photobucket.com/login/access";
oAuth.AuthorizeUrl = "http://photobucket.com/apilogin/login"; oAuth.AuthorizeUrl = "http://photobucket.com/apilogin/login";
oAuth.RequestTokenUrl = "http://api.photobucket.com/login/request"; oAuth.RequestTokenUrl = "http://api.photobucket.com/login/request";
oAuth.ConsumerKey = "149833145"; oAuth.BrowserSize = new Size(1010, 400);
oAuth.ConsumerSecret = "ebd828180b11103c010c7e71c66f6bcb";
oAuth.UserAgent = "Greenshot";
oAuth.BrowserWidth = 1010;
oAuth.BrowserHeight = 400;
oAuth.CheckVerifier = false;
oAuth.LoginTitle = "Photobucket authorization"; oAuth.LoginTitle = "Photobucket authorization";
oAuth.Token = config.PhotobucketToken; if (string.IsNullOrEmpty(config.SubDomain) || string.IsNullOrEmpty(config.Token)) {
oAuth.TokenSecret = config.PhotobucketTokenSecret; if (!oAuth.Authorize()) {
return null;
}
if (!string.IsNullOrEmpty(oAuth.Token)) {
config.Token = oAuth.Token;
}
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
config.TokenSecret = oAuth.TokenSecret;
}
if (oAuth.AccessTokenResponseParameters != null && oAuth.AccessTokenResponseParameters["subdomain"] != null) {
config.SubDomain = oAuth.AccessTokenResponseParameters["subdomain"];
}
IniConfig.Save();
}
oAuth.Token = config.Token;
oAuth.TokenSecret = config.TokenSecret;
Dictionary<string ,string> parameters = new Dictionary<string, string>(); Dictionary<string ,string> parameters = new Dictionary<string, string>();
// add album // add album
parameters.Add("id", "Apex75"); parameters.Add("id", "Apex75/greenshot");
// add type // add type
parameters.Add("type", "base64"); parameters.Add("type", "base64");
// Add image
parameters.Add("uploadfile", System.Convert.ToBase64String(imageData, 0, dataLength));
// add title // add title
if (title != null) { if (title != null) {
//parameters.Add("title", title); parameters.Add("title", title);
} }
// add filename // add filename
if (filename != null) { if (filename != null) {
parameters.Add("filename", filename); parameters.Add("filename", filename);
} }
try { try {
LOG.DebugFormat("Album info", oAuth.oAuthWebRequest(HTTPMethod.GET, "http://api.photobucket.com/album/Apex75", null, null, null)); string apiUrl = "http://api.photobucket.com/album/!/upload";
responseString = oAuth.oAuthWebRequest(HTTPMethod.POST, "http://api.photobucket.com/album/!/upload", parameters, null, null); oAuth.Sign(HTTPMethod.POST, apiUrl, parameters);
apiUrl = apiUrl.Replace("api.photobucket.com", config.SubDomain);
// Add image
parameters.Add("uploadfile", System.Convert.ToBase64String(imageData, 0, dataLength));
responseString = oAuth.MakeRequest(HTTPMethod.POST, apiUrl, parameters, null, null);
} catch (Exception ex) { } catch (Exception ex) {
LOG.Error("Error uploading to Photobucket.", ex); LOG.Error("Error uploading to Photobucket.", ex);
throw ex; throw ex;
} finally { } finally {
if (!string.IsNullOrEmpty(oAuth.Token)) { if (!string.IsNullOrEmpty(oAuth.Token)) {
config.PhotobucketToken = oAuth.Token; config.Token = oAuth.Token;
} }
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
config.PhotobucketTokenSecret = oAuth.TokenSecret; config.TokenSecret = oAuth.TokenSecret;
} }
} }
LOG.Info(responseString); LOG.Info(responseString);

View file

@ -34,7 +34,7 @@ namespace GreenshotPlugin.Controls {
/// </summary> /// </summary>
public partial class OAuthLoginForm : Form { public partial class OAuthLoginForm : Form {
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthLoginForm)); private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthLoginForm));
private OAuthSession _oauthSession; private string callbackUrl = null;
private String _token; private String _token;
private String _verifier; private String _verifier;
private String _tokenSecret; private String _tokenSecret;
@ -57,18 +57,16 @@ namespace GreenshotPlugin.Controls {
} }
} }
public OAuthLoginForm(OAuthSession o, string browserTitle, int width, int height) { public OAuthLoginForm(OAuthSession o, string browserTitle, Size size, string authorizationLink, string callbackUrl) {
_oauthSession = o; this.callbackUrl = callbackUrl;
_token = null; _token = null;
InitializeComponent(); InitializeComponent();
this.ClientSize = new System.Drawing.Size(width, height); this.ClientSize = size;
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon(); this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
this.Text = browserTitle; this.Text = browserTitle;
this.addressTextBox.Text = o.AuthorizationLink; this.addressTextBox.Text = authorizationLink;
_token = _oauthSession.Token;
_tokenSecret = _oauthSession.TokenSecret;
browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted); browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
browser.Navigate(new Uri(_oauthSession.AuthorizationLink)); browser.Navigate(new Uri(authorizationLink));
WindowDetails.ToForeground(this.Handle); WindowDetails.ToForeground(this.Handle);
} }
@ -88,7 +86,7 @@ namespace GreenshotPlugin.Controls {
} }
private void checkUrl() { private void checkUrl() {
if (browser.Url.ToString().StartsWith(_oauthSession.CallbackUrl)) { if (browser.Url.ToString().StartsWith(callbackUrl)) {
string queryParams = browser.Url.Query; string queryParams = browser.Url.Query;
if (queryParams.Length > 0) { if (queryParams.Length > 0) {
//Store the Token and Token Secret //Store the Token and Token Secret

View file

@ -27,6 +27,7 @@ using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
using System.Drawing;
namespace GreenshotPlugin.Core { namespace GreenshotPlugin.Core {
/// <summary> /// <summary>
@ -72,16 +73,33 @@ namespace GreenshotPlugin.Core {
private string _callbackUrl = "http://getgreenshot.org"; private string _callbackUrl = "http://getgreenshot.org";
private bool checkVerifier = true; private bool checkVerifier = true;
private bool useHTTPHeadersForAuthorization = true; private bool useHTTPHeadersForAuthorization = true;
private bool useAuthorization = true; private IDictionary<string, string> accessTokenResponseParameters = null;
private IDictionary<string, string> requestTokenResponseParameters = null;
/// <summary>
/// Parameters of the last called getAccessToken
/// </summary>
public IDictionary<string, string> AccessTokenResponseParameters {
get {
return accessTokenResponseParameters;
}
}
/// <summary>
/// Parameters of the last called getRequestToken
/// </summary>
public IDictionary<string, string> RequestTokenResponseParameters {
get {
return requestTokenResponseParameters;
}
}
private string consumerKey;
private string consumerSecret;
// default browser size // default browser size
private int _browserWidth = 864; private Size _browserSize = new Size(864, 587);
private int _browserHeight = 587;
private string loginTitle = "Authorize Greenshot access"; private string loginTitle = "Authorize Greenshot access";
#region PublicPropertiies #region PublicPropertiies
public string ConsumerKey { get; set; }
public string ConsumerSecret { get; set; }
public string UserAgent { get { return _userAgent; } set { _userAgent = value; } } public string UserAgent { get { return _userAgent; } set { _userAgent = value; } }
public string RequestTokenUrl { get; set; } public string RequestTokenUrl { get; set; }
public string AuthorizeUrl { get; set; } public string AuthorizeUrl { get; set; }
@ -96,27 +114,21 @@ namespace GreenshotPlugin.Core {
} }
} }
public int BrowserWidth { public Size BrowserSize {
get { get {
return _browserWidth; return _browserSize;
} }
set { set {
_browserWidth = value; _browserSize = value;
}
}
public int BrowserHeight {
get {
return _browserHeight;
}
set {
_browserHeight = value;
} }
} }
public string Token { public string Token {
get; get;
set; set;
} }
public string TokenSecret { get; set; } public string TokenSecret { get; set; }
public string LoginTitle { public string LoginTitle {
get { get {
return loginTitle; return loginTitle;
@ -137,17 +149,14 @@ namespace GreenshotPlugin.Core {
useHTTPHeadersForAuthorization = value; useHTTPHeadersForAuthorization = value;
} }
} }
public bool UseAuthorization {
get {
return useAuthorization;
}
set {
useAuthorization = value;
}
}
#endregion #endregion
public OAuthSession(string consumerKey, string consumerSecret) {
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
}
/// <summary> /// <summary>
/// Helper function to compute a hash value /// Helper function to compute a hash value
/// </summary> /// </summary>
@ -229,18 +238,22 @@ namespace GreenshotPlugin.Core {
// Just a simple implementation of a random number between 123400 and 9999999 // Just a simple implementation of a random number between 123400 and 9999999
return random.Next(123400, 9999999).ToString(); return random.Next(123400, 9999999).ToString();
} }
/// <summary> /// <summary>
/// Get the request token using the consumer key and secret. Also initializes tokensecret /// Get the request token using the consumer key and secret. Also initializes tokensecret
/// </summary> /// </summary>
/// <returns>The request token.</returns> /// <returns>The request token.</returns>
private String getRequestToken() { private String getRequestToken() {
string ret = null; string ret = null;
string response = oAuthWebRequestNoCheck(HTTPMethod.POST, RequestTokenUrl, null); IDictionary<string, string> parameters = new Dictionary<string, string>();
Sign(HTTPMethod.POST, RequestTokenUrl, parameters);
string response = MakeRequest(HTTPMethod.POST, RequestTokenUrl, parameters, null, null);
LOG.DebugFormat("Request token response: {0}", response);
if (response.Length > 0) { if (response.Length > 0) {
IDictionary<string, string> qs = NetworkHelper.ParseQueryString(response); requestTokenResponseParameters = NetworkHelper.ParseQueryString(response);
if (qs.ContainsKey(OAUTH_TOKEN_KEY)) { if (requestTokenResponseParameters.ContainsKey(OAUTH_TOKEN_KEY)) {
this.Token = qs[OAUTH_TOKEN_KEY]; this.Token = requestTokenResponseParameters[OAUTH_TOKEN_KEY];
this.TokenSecret = qs[OAUTH_TOKEN_SECRET_KEY]; this.TokenSecret = requestTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY];
ret = this.Token; ret = this.Token;
} }
} }
@ -251,17 +264,17 @@ namespace GreenshotPlugin.Core {
/// Authorize the token by showing the dialog /// Authorize the token by showing the dialog
/// </summary> /// </summary>
/// <returns>The request token.</returns> /// <returns>The request token.</returns>
private String authorizeToken() { private String getAuthorizeToken() {
if (string.IsNullOrEmpty(Token)) { if (string.IsNullOrEmpty(Token)) {
Exception e = new Exception("The request token is not set"); Exception e = new Exception("The request token is not set");
throw e; throw e;
} }
LOG.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink); LOG.DebugFormat("Opening AuthorizationLink: {0}", authorizationLink);
OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(this, LoginTitle, BrowserWidth, BrowserHeight); OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(this, LoginTitle, BrowserSize, authorizationLink, CallbackUrl);
oAuthLoginForm.ShowDialog(); oAuthLoginForm.ShowDialog();
Token = oAuthLoginForm.Token; Token = oAuthLoginForm.Token;
Verifier = oAuthLoginForm.Verifier;
if (CheckVerifier) { if (CheckVerifier) {
Verifier = oAuthLoginForm.Verifier;
if (!string.IsNullOrEmpty(Verifier)) { if (!string.IsNullOrEmpty(Verifier)) {
return Token; return Token;
} else { } else {
@ -282,15 +295,17 @@ namespace GreenshotPlugin.Core {
throw e; throw e;
} }
string response = oAuthWebRequestNoCheck(HTTPMethod.POST, AccessTokenUrl, null); IDictionary<string, string> parameters = new Dictionary<string, string>();
Sign(HTTPMethod.POST, AccessTokenUrl, parameters);
string response = MakeRequest(HTTPMethod.POST, AccessTokenUrl, parameters, null, null);
LOG.DebugFormat("Access token response: {0}", response);
if (response.Length > 0) { if (response.Length > 0) {
IDictionary<string, string> qs = NetworkHelper.ParseQueryString(response); accessTokenResponseParameters = NetworkHelper.ParseQueryString(response);
if (qs.ContainsKey(OAUTH_TOKEN_KEY) && qs[OAUTH_TOKEN_KEY] != null) { if (accessTokenResponseParameters.ContainsKey(OAUTH_TOKEN_KEY) && accessTokenResponseParameters[OAUTH_TOKEN_KEY] != null) {
this.Token = qs[OAUTH_TOKEN_KEY]; this.Token = accessTokenResponseParameters[OAUTH_TOKEN_KEY];
} }
if (qs.ContainsKey(OAUTH_TOKEN_SECRET_KEY) && qs[OAUTH_TOKEN_SECRET_KEY] != null) { if (accessTokenResponseParameters.ContainsKey(OAUTH_TOKEN_SECRET_KEY) && accessTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY] != null) {
this.TokenSecret = qs[OAUTH_TOKEN_SECRET_KEY]; this.TokenSecret = accessTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY];
} }
} }
@ -301,7 +316,10 @@ namespace GreenshotPlugin.Core {
/// This method goes through the whole authorize process, including a Authorization window. /// This method goes through the whole authorize process, including a Authorization window.
/// </summary> /// </summary>
/// <returns>true if the process is completed</returns> /// <returns>true if the process is completed</returns>
private bool authorize() { public bool Authorize() {
this.Token = null;
this.TokenSecret = null;
this.Verifier = null;
LOG.Debug("Creating Token"); LOG.Debug("Creating Token");
try { try {
getRequestToken(); getRequestToken();
@ -309,7 +327,7 @@ namespace GreenshotPlugin.Core {
LOG.Error(ex); LOG.Error(ex);
throw new NotSupportedException("Service is not available: " + ex.Message); throw new NotSupportedException("Service is not available: " + ex.Message);
} }
if (UseAuthorization && string.IsNullOrEmpty(authorizeToken())) { if (string.IsNullOrEmpty(getAuthorizeToken())) {
LOG.Debug("User didn't authenticate!"); LOG.Debug("User didn't authenticate!");
return false; return false;
} }
@ -320,7 +338,7 @@ namespace GreenshotPlugin.Core {
/// Get the link to the authorization page for this application. /// Get the link to the authorization page for this application.
/// </summary> /// </summary>
/// <returns>The url with a valid request token, or a null string.</returns> /// <returns>The url with a valid request token, or a null string.</returns>
public string AuthorizationLink { private string authorizationLink {
get { get {
return AuthorizeUrl + "?" + OAUTH_TOKEN_KEY + "=" + this.Token + "&" + OAUTH_CALLBACK_KEY + "=" + UrlEncode3986(CallbackUrl); return AuthorizeUrl + "?" + OAUTH_TOKEN_KEY + "=" + this.Token + "&" + OAUTH_CALLBACK_KEY + "=" + UrlEncode3986(CallbackUrl);
} }
@ -333,9 +351,10 @@ namespace GreenshotPlugin.Core {
/// <param name="requestURL"></param> /// <param name="requestURL"></param>
/// <param name="parameters"></param> /// <param name="parameters"></param>
/// <returns></returns> /// <returns></returns>
public string oAuthWebRequest(HTTPMethod method, string requestURL, IDictionary<string, string> parameters) { public string MakeOAuthRequest(HTTPMethod method, string requestURL, IDictionary<string, string> parameters) {
return oAuthWebRequest(method, requestURL, parameters, null, null); return MakeOAuthRequest(method, requestURL, parameters, null, null);
} }
/// <summary> /// <summary>
/// Submit a web request using oAuth. /// Submit a web request using oAuth.
/// </summary> /// </summary>
@ -345,21 +364,61 @@ namespace GreenshotPlugin.Core {
/// <param name="contentType">contenttype for the postdata</param> /// <param name="contentType">contenttype for the postdata</param>
/// <param name="postData">Data to post (MemoryStream)</param> /// <param name="postData">Data to post (MemoryStream)</param>
/// <returns>The web server response.</returns> /// <returns>The web server response.</returns>
public string oAuthWebRequest(HTTPMethod method, string requestURL, IDictionary<string, string> parameters, string contentType, MemoryStream postData) { public string MakeOAuthRequest(HTTPMethod method, string requestURL, IDictionary<string, string> parameters, string contentType, MemoryStream postData) {
// If we are not trying to get a Authorization or Accestoken, and we don't have a token, create one if (parameters == null) {
if (string.IsNullOrEmpty(Token)) { parameters = new Dictionary<string, string>();
if (!authorize()) { }
throw new Exception("Not authorized"); int retries = 2;
Exception lastException = null;
while (retries-- > 0) {
// If we are not trying to get a Authorization or Accestoken, and we don't have a token, create one
if (string.IsNullOrEmpty(Token)) {
if (!Authorize()) {
throw new Exception("Not authorized");
}
}
try {
Sign(method, requestURL, parameters);
return MakeRequest(method, requestURL, parameters, contentType, 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
IDictionary<string, string> newParameters = new Dictionary<string, string>();
foreach (string parameterKey in parameters.Keys) {
if (!parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) {
newParameters.Add(parameterKey, parameters[parameterKey]);
}
}
parameters = newParameters;
continue;
}
}
throw wEx;
} }
} }
return oAuthWebRequestNoCheck(method, requestURL, parameters, contentType, postData); if (lastException != null) {
throw lastException;
}
throw new Exception("Not authorized");
} }
public string oAuthWebRequestNoCheck(HTTPMethod method, string requestURL, IDictionary<string, string> parameters) { /// <summary>
return oAuthWebRequestNoCheck(method, requestURL, parameters, null, null); /// OAuth sign the parameters, meaning all oauth parameters are added to the supplied dictionary.
} /// And additionally a signature is added.
/// </summary>
private string oAuthWebRequestNoCheck(HTTPMethod method, string requestURL, IDictionary<string, string> parameters, string contentType, MemoryStream postData) { /// <param name="method">Method (POST,PUT,GET)</param>
/// <param name="requestURL">Url to call</param>
/// <param name="parameters">IDictionary<string, string></param>
public void Sign(HTTPMethod method, string requestURL, IDictionary<string, string> parameters) {
if (parameters == null) {
throw new ArgumentNullException("parameters");
}
// Build the signature base // Build the signature base
StringBuilder signatureBase = new StringBuilder(); StringBuilder signatureBase = new StringBuilder();
@ -376,42 +435,52 @@ namespace GreenshotPlugin.Core {
signatureBase.Append(UrlEncode3986(normalizedUrl)).Append("&"); signatureBase.Append(UrlEncode3986(normalizedUrl)).Append("&");
// Add normalized parameters // Add normalized parameters
if (parameters == null) {
parameters = new Dictionary<string, string>();
}
parameters.Add(OAUTH_VERSION_KEY, OAUTH_VERSION); parameters.Add(OAUTH_VERSION_KEY, OAUTH_VERSION);
parameters.Add(OAUTH_NONCE_KEY, GenerateNonce()); parameters.Add(OAUTH_NONCE_KEY, GenerateNonce());
parameters.Add(OAUTH_TIMESTAMP_KEY, GenerateTimeStamp()); parameters.Add(OAUTH_TIMESTAMP_KEY, GenerateTimeStamp());
parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, HMACSHA1SignatureType); parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, HMACSHA1SignatureType);
parameters.Add(OAUTH_CONSUMER_KEY_KEY, ConsumerKey); parameters.Add(OAUTH_CONSUMER_KEY_KEY, consumerKey);
if (CallbackUrl != null && RequestTokenUrl != null && requestURL.ToString().StartsWith(RequestTokenUrl)) { if (CallbackUrl != null && RequestTokenUrl != null && requestURL.ToString().StartsWith(RequestTokenUrl)) {
parameters.Add(OAUTH_CALLBACK_KEY, CallbackUrl); parameters.Add(OAUTH_CALLBACK_KEY, CallbackUrl);
} }
if (!string.IsNullOrEmpty(Verifier)) {
parameters.Add(OAUTH_VERIFIER_KEY, Verifier);
}
if (!string.IsNullOrEmpty(Token)) { if (!string.IsNullOrEmpty(Token)) {
parameters.Add(OAUTH_TOKEN_KEY, Token); parameters.Add(OAUTH_TOKEN_KEY, Token);
} }
signatureBase.Append(UrlEncode3986(GenerateNormalizedParametersString(parameters))); signatureBase.Append(UrlEncode3986(GenerateNormalizedParametersString(parameters)));
LOG.DebugFormat("Signature base: {0}", signatureBase);
// Generate Signature and add it to the parameters // Generate Signature and add it to the parameters
HMACSHA1 hmacsha1 = new HMACSHA1(); HMACSHA1 hmacsha1 = new HMACSHA1();
hmacsha1.Key = Encoding.UTF8.GetBytes(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}&{1}", UrlEncode3986(ConsumerSecret), string.IsNullOrEmpty(TokenSecret) ? string.Empty : UrlEncode3986(TokenSecret))); hmacsha1.Key = Encoding.UTF8.GetBytes(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}&{1}", UrlEncode3986(consumerSecret), string.IsNullOrEmpty(TokenSecret) ? string.Empty : UrlEncode3986(TokenSecret)));
string signature = ComputeHash(hmacsha1, signatureBase.ToString()); string signature = ComputeHash(hmacsha1, signatureBase.ToString());
parameters.Add(OAUTH_SIGNATURE_KEY, signature); parameters.Add(OAUTH_SIGNATURE_KEY, signature);
LOG.DebugFormat("Signature: {0}", signature); }
/// <summary>
/// Make the actual OAuth request, all oauth parameters are passed as header (default) and the others are placed in the url or post data.
/// Any additional parameters added after the Sign call are not in the signature, this could be by design!
/// </summary>
/// <param name="method"></param>
/// <param name="requestURL"></param>
/// <param name="parameters"></param>
/// <param name="contentType"></param>
/// <param name="postData"></param>
/// <returns>Response from server</returns>
public string MakeRequest(HTTPMethod method, string requestURL, IDictionary<string, string> parameters, string contentType, MemoryStream postData) {
if (parameters == null) {
throw new ArgumentNullException("parameters");
}
IDictionary<string, string> requestParameters = null; IDictionary<string, string> requestParameters = null;
// Add oAuth values as HTTP headers, if this is allowed // Add oAuth values as HTTP headers, if this is allowed
StringBuilder authHeader = null; StringBuilder authHeader = null;
if ((HTTPMethod.POST == method || HTTPMethod.PUT == method) && UseHTTPHeadersForAuthorization) { if (HTTPMethod.POST == method && UseHTTPHeadersForAuthorization) {
authHeader = new StringBuilder(); authHeader = new StringBuilder();
requestParameters = new Dictionary<string, string>(); requestParameters = new Dictionary<string, string>();
foreach (string parameterKey in parameters.Keys) { foreach (string parameterKey in parameters.Keys) {
if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) { if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) {
authHeader.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}=\"{1}\", ", parameterKey, UrlEncode3986(parameters[parameterKey])); authHeader.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}=\"{1}\", ", parameterKey, UrlEncode3986(parameters[parameterKey]));
} else if (!requestParameters.ContainsKey(parameterKey)) { } else if (!requestParameters.ContainsKey(parameterKey)) {
LOG.DebugFormat("Request parameter: {0}={1}", parameterKey, parameters[parameterKey]);
requestParameters.Add(parameterKey, parameters[parameterKey]); requestParameters.Add(parameterKey, parameters[parameterKey]);
} }
} }
@ -427,7 +496,6 @@ namespace GreenshotPlugin.Core {
} else { } else {
requestParameters = parameters; requestParameters = parameters;
} }
// Create webrequest // Create webrequest
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(requestURL); HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(requestURL);
webRequest.Method = method.ToString(); webRequest.Method = method.ToString();
@ -440,7 +508,7 @@ namespace GreenshotPlugin.Core {
webRequest.Headers.Add("Authorization: OAuth " + authHeader.ToString()); webRequest.Headers.Add("Authorization: OAuth " + authHeader.ToString());
} }
if ( (HTTPMethod.POST == method || HTTPMethod.PUT == method) && postData == null && requestParameters != null && requestParameters.Count > 0) { if (HTTPMethod.POST == method && postData == null && requestParameters != null && requestParameters.Count > 0) {
StringBuilder form = new StringBuilder(); StringBuilder form = new StringBuilder();
foreach (string parameterKey in requestParameters.Keys) { foreach (string parameterKey in requestParameters.Keys) {
form.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}={1}&", UrlEncode3986(parameterKey), UrlEncode3986(parameters[parameterKey])); form.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}={1}&", UrlEncode3986(parameterKey), UrlEncode3986(parameters[parameterKey]));
@ -449,7 +517,6 @@ namespace GreenshotPlugin.Core {
if (form.Length > 0) { if (form.Length > 0) {
form.Remove(form.Length - 1, 1); form.Remove(form.Length - 1, 1);
} }
LOG.DebugFormat("Form data: {0}", form.ToString());
webRequest.ContentType = "application/x-www-form-urlencoded"; webRequest.ContentType = "application/x-www-form-urlencoded";
byte[] data = Encoding.UTF8.GetBytes(form.ToString()); byte[] data = Encoding.UTF8.GetBytes(form.ToString());
using (var requestStream = webRequest.GetRequestStream()) { using (var requestStream = webRequest.GetRequestStream()) {
@ -472,38 +539,6 @@ namespace GreenshotPlugin.Core {
return responseData; return responseData;
} }
/// <summary>
/// Web Request Wrapper
/// </summary>
/// <param name="method">Http Method</param>
/// <param name="url">Full url to the web resource</param>
/// <param name="postData">Data to post </param>
/// <returns>The web server response.</returns>
protected string WebRequest(HTTPMethod method, string url, string contentType, MemoryStream postData) {
HttpWebRequest webRequest = null;
string responseData = "";
webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
webRequest.Method = method.ToString();
webRequest.ServicePoint.Expect100Continue = false;
webRequest.UserAgent = _userAgent;
webRequest.Timeout = 20000;
webRequest.ContentLength = postData.Length;
if (method == HTTPMethod.POST) {
webRequest.ContentType = contentType;
}
using (var requestStream = webRequest.GetRequestStream()) {
requestStream.Write(postData.GetBuffer(), 0, (int)postData.Length);
}
responseData = WebResponseGet(webRequest);
webRequest = null;
return responseData;
}
/// <summary> /// <summary>
/// Process the web response. /// Process the web response.
/// </summary> /// </summary>