mirror of
https://github.com/greenshot/greenshot
synced 2025-07-16 10:03:44 -07:00
Made the OAuth implementation work as specified, Imgur is working but the others need to be checked.
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2050 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
45e018d197
commit
ade8e365b6
5 changed files with 371 additions and 525 deletions
|
@ -100,39 +100,34 @@ namespace GreenshotImgurPlugin {
|
|||
/// <param name="imageData">byte[] with image data</param>
|
||||
/// <returns>ImgurResponse</returns>
|
||||
public static ImgurInfo UploadToImgur(byte[] imageData, int dataLength, string title, string filename) {
|
||||
StringBuilder uploadRequest = new StringBuilder();
|
||||
IDictionary<string, string> uploadParameters = new Dictionary<string, string>();
|
||||
// Add image
|
||||
uploadRequest.Append("image=");
|
||||
uploadRequest.Append(OAuthHelper.UrlEncode3986(System.Convert.ToBase64String(imageData, 0, dataLength)));
|
||||
uploadParameters.Add("image", System.Convert.ToBase64String(imageData, 0, dataLength));
|
||||
// add type
|
||||
uploadRequest.Append("&type=base64");
|
||||
uploadParameters.Add("type", "base64");
|
||||
|
||||
// add title
|
||||
if (title != null) {
|
||||
uploadRequest.Append("&title=");
|
||||
uploadRequest.Append(OAuthHelper.UrlEncode3986(title));
|
||||
uploadParameters.Add("title", title);
|
||||
}
|
||||
// add filename
|
||||
if (filename != null) {
|
||||
uploadRequest.Append("&name=");
|
||||
uploadRequest.Append(OAuthHelper.UrlEncode3986(filename));
|
||||
uploadParameters.Add("name", filename);
|
||||
}
|
||||
string url;
|
||||
string responseString;
|
||||
|
||||
string responseString = null;
|
||||
if (config.AnonymousAccess) {
|
||||
// add key
|
||||
uploadRequest.Append("&key=");
|
||||
uploadRequest.Append(IMGUR_ANONYMOUS_API_KEY);
|
||||
url = config.ImgurApiUrl + "/upload";
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
uploadParameters.Add("key", IMGUR_ANONYMOUS_API_KEY);
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(config.ImgurApiUrl + "/upload");
|
||||
|
||||
webRequest.Method = "POST";
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
|
||||
using(StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream())) {
|
||||
streamWriter.Write(uploadRequest.ToString());
|
||||
string urloadText = NetworkHelper.GenerateQueryParameters(uploadParameters);
|
||||
streamWriter.Write(urloadText);
|
||||
}
|
||||
using (WebResponse response = webRequest.GetResponse()) {
|
||||
LogCredits(response);
|
||||
|
@ -142,37 +137,38 @@ namespace GreenshotImgurPlugin {
|
|||
}
|
||||
|
||||
} else {
|
||||
url = config.ImgurApiUrl + "/account/images";
|
||||
OAuthHelper oAuth = new OAuthHelper();
|
||||
OAuthSession oAuth = new OAuthSession();
|
||||
oAuth.BrowserWidth = 650;
|
||||
oAuth.BrowserHeight = 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.ConsumerKey = ImgurCredentials.CONSUMER_KEY;
|
||||
oAuth.ConsumerSecret = ImgurCredentials.CONSUMER_SECRET;
|
||||
oAuth.ConsumerKey = "907d4455b8c38144d68c4f72190af4c40504a0ac7";
|
||||
oAuth.ConsumerSecret = "d33902ef409fea163ab755454c15b3d0";
|
||||
oAuth.UserAgent = "Greenshot";
|
||||
if (string.IsNullOrEmpty(config.ImgurToken)) {
|
||||
LOG.Debug("Creating Imgur Token");
|
||||
oAuth.getRequestToken();
|
||||
if (string.IsNullOrEmpty(oAuth.authorizeToken("Imgur authorization"))) {
|
||||
LOG.Debug("User didn't authenticate!");
|
||||
return null;
|
||||
}
|
||||
string accessToken = oAuth.getAccessToken();
|
||||
config.ImgurToken = oAuth.Token;
|
||||
config.ImgurTokenSecret = oAuth.TokenSecret;
|
||||
} else {
|
||||
LOG.Debug("Using stored Imgur Token");
|
||||
oAuth.LoginTitle = "Imgur authorization";
|
||||
//oAuth.UseHTTPHeadersForAuthorization = false;
|
||||
oAuth.Token = config.ImgurToken;
|
||||
oAuth.TokenSecret = config.ImgurTokenSecret;
|
||||
try {
|
||||
LOG.DebugFormat("Test: {0}", oAuth.oAuthWebRequest(HTTPMethod.GET, "http://api.imgur.com/2/account", null));
|
||||
responseString = oAuth.oAuthWebRequest(HTTPMethod.POST, "http://api.imgur.com/2/account/images.xml", uploadParameters);
|
||||
} catch (Exception ex) {
|
||||
LOG.Error("Upload to imgur gave an exeption: ", ex);
|
||||
throw ex;
|
||||
} finally {
|
||||
if (oAuth.Token != null) {
|
||||
config.ImgurToken = oAuth.Token;
|
||||
}
|
||||
if (oAuth.TokenSecret != null) {
|
||||
config.ImgurTokenSecret = oAuth.TokenSecret;
|
||||
}
|
||||
IniConfig.Save();
|
||||
}
|
||||
responseString = oAuth.oAuthWebRequest(OAuthHelper.Method.POST, url, uploadRequest.ToString());
|
||||
}
|
||||
LOG.Info(responseString);
|
||||
ImgurInfo imgurInfo = ImgurInfo.ParseResponse(responseString);
|
||||
LOG.Debug("Upload to imgur was finished");
|
||||
return imgurInfo;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,59 +48,39 @@ namespace GreenshotPhotobucketPlugin {
|
|||
/// <param name="imageData">byte[] with image data</param>
|
||||
/// <returns>PhotobucketResponse</returns>
|
||||
public static PhotobucketInfo UploadToPhotobucket(byte[] imageData, int dataLength, string title, string filename) {
|
||||
StringBuilder uploadRequest = new StringBuilder();
|
||||
uploadRequest.Append("identifier=greenshot");
|
||||
// add type
|
||||
uploadRequest.Append("&type=base64");
|
||||
// Add image
|
||||
uploadRequest.Append("&uploadfile=");
|
||||
uploadRequest.Append(OAuthHelper.UrlEncode3986(System.Convert.ToBase64String(imageData, 0, dataLength)));
|
||||
// add title
|
||||
if (title != null) {
|
||||
uploadRequest.Append("&title=");
|
||||
uploadRequest.Append(OAuthHelper.UrlEncode3986(title));
|
||||
}
|
||||
// add filename
|
||||
if (filename != null) {
|
||||
uploadRequest.Append("&filename=");
|
||||
uploadRequest.Append(OAuthHelper.UrlEncode3986(filename));
|
||||
}
|
||||
string url = "http://api.photobucket.com/album/greenshot/upload";
|
||||
string responseString;
|
||||
|
||||
OAuthHelper oAuth = new OAuthHelper();
|
||||
OAuthSession oAuth = new OAuthSession();
|
||||
// This url is configured in the Photobucket API settings in the Photobucket site!!
|
||||
oAuth.CallbackUrl = "http://getgreenshot.org";
|
||||
oAuth.AccessTokenUrl = "http://api.photobucket.com/login/access";
|
||||
oAuth.AuthorizeUrl = "http://photobucket.com/apilogin/login";
|
||||
oAuth.RequestTokenUrl = "http://api.photobucket.com/login/request";
|
||||
oAuth.ConsumerKey = ;
|
||||
oAuth.ConsumerSecret = ;
|
||||
oAuth.ConsumerKey = "149833145";
|
||||
oAuth.ConsumerSecret = "ebd828180b11103c010c7e71c66f6bcb";
|
||||
oAuth.UserAgent = "Greenshot";
|
||||
oAuth.BrowserWidth = 1010;
|
||||
oAuth.BrowserHeight = 400;
|
||||
oAuth.CheckVerifier = false;
|
||||
if (string.IsNullOrEmpty(config.PhotobucketToken)) {
|
||||
LOG.Debug("Creating Photobucket Token");
|
||||
try {
|
||||
oAuth.getRequestToken();
|
||||
} catch (Exception ex) {
|
||||
LOG.Error(ex);
|
||||
throw new NotSupportedException("Photobucket is not available: " + ex.Message);
|
||||
oAuth.LoginTitle = "Photobucket authorization";
|
||||
Dictionary<string ,string> parameters = new Dictionary<string, string>();
|
||||
// add album
|
||||
parameters.Add("identifier", "greenshot");
|
||||
// add type
|
||||
parameters.Add("type", "base64");
|
||||
// Add image
|
||||
parameters.Add("uploadfile", System.Convert.ToBase64String(imageData, 0, dataLength));
|
||||
// add title
|
||||
if (title != null) {
|
||||
parameters.Add("title", title);
|
||||
}
|
||||
LOG.Debug("Authorizing Photobucket");
|
||||
if (string.IsNullOrEmpty(oAuth.authorizeToken("Photobucket authorization"))) {
|
||||
return null;
|
||||
// add filename
|
||||
if (filename != null) {
|
||||
parameters.Add("filename", filename);
|
||||
}
|
||||
string accessToken = oAuth.getAccessToken();
|
||||
config.PhotobucketToken = oAuth.Token;
|
||||
config.PhotobucketTokenSecret = oAuth.TokenSecret;
|
||||
} else {
|
||||
LOG.Debug("Using stored Photobucket Token");
|
||||
responseString = oAuth.oAuthWebRequest(HTTPMethod.POST, "http://api.photobucket.com/album/greenshot/upload", parameters, null, null);
|
||||
oAuth.Token = config.PhotobucketToken;
|
||||
oAuth.TokenSecret = config.PhotobucketTokenSecret;
|
||||
}
|
||||
responseString = oAuth.oAuthWebRequest(OAuthHelper.Method.POST, url, uploadRequest.ToString());
|
||||
LOG.Info(responseString);
|
||||
PhotobucketInfo PhotobucketInfo = PhotobucketInfo.ParseResponse(responseString);
|
||||
LOG.Debug("Upload to Photobucket was finished");
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace GreenshotPlugin.Controls {
|
|||
/// </summary>
|
||||
public partial class OAuthLoginForm : Form {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthLoginForm));
|
||||
private OAuthHelper _oauth;
|
||||
private OAuthSession _oauthSession;
|
||||
private String _token;
|
||||
private String _verifier;
|
||||
private String _tokenSecret;
|
||||
|
@ -57,18 +57,18 @@ namespace GreenshotPlugin.Controls {
|
|||
}
|
||||
}
|
||||
|
||||
public OAuthLoginForm(OAuthHelper o, string browserTitle, int width, int height) {
|
||||
_oauth = o;
|
||||
public OAuthLoginForm(OAuthSession o, string browserTitle, int width, int height) {
|
||||
_oauthSession = o;
|
||||
_token = null;
|
||||
InitializeComponent();
|
||||
this.ClientSize = new System.Drawing.Size(width, height);
|
||||
this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
|
||||
this.Text = browserTitle;
|
||||
this.addressTextBox.Text = o.AuthorizationLink;
|
||||
_token = _oauth.Token;
|
||||
_tokenSecret = _oauth.TokenSecret;
|
||||
_token = _oauthSession.Token;
|
||||
_tokenSecret = _oauthSession.TokenSecret;
|
||||
browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
|
||||
browser.Navigate(new Uri(_oauth.AuthorizationLink));
|
||||
browser.Navigate(new Uri(_oauthSession.AuthorizationLink));
|
||||
|
||||
WindowDetails.ToForeground(this.Handle);
|
||||
}
|
||||
|
@ -88,15 +88,15 @@ namespace GreenshotPlugin.Controls {
|
|||
}
|
||||
|
||||
private void checkUrl() {
|
||||
if (browser.Url.ToString().StartsWith(_oauth.CallbackUrl)) {
|
||||
if (browser.Url.ToString().StartsWith(_oauthSession.CallbackUrl)) {
|
||||
string queryParams = browser.Url.Query;
|
||||
if (queryParams.Length > 0) {
|
||||
//Store the Token and Token Secret
|
||||
NameValueCollection qs = NetworkHelper.ParseQueryString(queryParams);
|
||||
if (qs["oauth_token"] != null) {
|
||||
IDictionary<string, string> qs = NetworkHelper.ParseQueryString(queryParams);
|
||||
if (qs.ContainsKey("oauth_token") && qs["oauth_token"] != null) {
|
||||
_token = qs["oauth_token"];
|
||||
}
|
||||
if (qs["oauth_verifier"] != null) {
|
||||
if (qs.ContainsKey("oauth_verifier") && qs["oauth_verifier"] != null) {
|
||||
_verifier = qs["oauth_verifier"];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,11 +23,13 @@ using System.Drawing;
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text.RegularExpressions;
|
||||
using Greenshot.IniFile;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Net.Security;
|
||||
using System.Web;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
/// <summary>
|
||||
|
@ -158,6 +160,26 @@ namespace GreenshotPlugin.Core {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper around the EscapeDataString, as the limit is 32766 characters
|
||||
/// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns>escaped data string</returns>
|
||||
public static string EscapeDataString(string text) {
|
||||
if (!string.IsNullOrEmpty(text)) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
int currentLocation = 0;
|
||||
while (currentLocation < text.Length) {
|
||||
string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation));
|
||||
result.Append(Uri.EscapeDataString(process));
|
||||
currentLocation = currentLocation + 16384;
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UrlDecodes a string without requiring System.Web
|
||||
/// </summary>
|
||||
|
@ -174,23 +196,50 @@ namespace GreenshotPlugin.Core {
|
|||
/// ParseQueryString without the requirement for System.Web
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static NameValueCollection ParseQueryString(string s) {
|
||||
NameValueCollection nvc = new NameValueCollection();
|
||||
/// <returns>Dictionary<string, string></returns>
|
||||
public static IDictionary<string, string> ParseQueryString(string s) {
|
||||
IDictionary<string, string> parameters = new SortedDictionary<string, string>();
|
||||
// remove anything other than query string from url
|
||||
if (s.Contains("?")) {
|
||||
s = s.Substring(s.IndexOf('?') + 1);
|
||||
}
|
||||
foreach (string vp in Regex.Split(s, "&")) {
|
||||
if (string.IsNullOrEmpty(vp)) {
|
||||
continue;
|
||||
}
|
||||
string[] singlePair = Regex.Split(vp, "=");
|
||||
if (parameters.ContainsKey(singlePair[0])) {
|
||||
parameters.Remove(singlePair[0]);
|
||||
}
|
||||
if (singlePair.Length == 2) {
|
||||
nvc.Add(singlePair[0], singlePair[1]);
|
||||
parameters.Add(singlePair[0], singlePair[1]);
|
||||
} else {
|
||||
// only one key with no value specified in query string
|
||||
nvc.Add(singlePair[0], string.Empty);
|
||||
parameters.Add(singlePair[0], string.Empty);
|
||||
}
|
||||
}
|
||||
return nvc;
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the query paramters
|
||||
/// </summary>
|
||||
/// <param name="queryParameters">the list of query parameters</param>
|
||||
/// <returns>a string with the query parameters</returns>
|
||||
public static string GenerateQueryParameters(IDictionary<string, string> queryParameters) {
|
||||
if (queryParameters == null || queryParameters.Count == 0) {
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
queryParameters = new SortedDictionary<string, string>(queryParameters);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach(string key in queryParameters.Keys) {
|
||||
sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode(queryParameters[key]));
|
||||
}
|
||||
sb.Remove(sb.Length-1,1);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,87 +29,55 @@ using System.Text.RegularExpressions;
|
|||
using GreenshotPlugin.Controls;
|
||||
|
||||
namespace GreenshotPlugin.Core {
|
||||
public class OAuthHelper {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthHelper));
|
||||
/// <summary>
|
||||
/// Provides a predefined set of algorithms that are supported officially by the protocol
|
||||
/// </summary>
|
||||
protected enum SignatureTypes {
|
||||
public enum OAuthSignatureTypes {
|
||||
HMACSHA1,
|
||||
PLAINTEXT,
|
||||
RSASHA1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides an internal structure to sort the query parameter
|
||||
/// </summary>
|
||||
protected class QueryParameter {
|
||||
private string name = null;
|
||||
private string value = null;
|
||||
public enum HTTPMethod { GET, POST, PUT, DELETE };
|
||||
|
||||
public QueryParameter(string name, string value)
|
||||
{
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public string Value
|
||||
{
|
||||
get { return value; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Comparer class used to perform the sorting of the query parameters
|
||||
/// </summary>
|
||||
protected class QueryParameterComparer : IComparer<QueryParameter> {
|
||||
|
||||
#region IComparer<QueryParameter> Members
|
||||
|
||||
public int Compare(QueryParameter x, QueryParameter y) {
|
||||
if (x.Name == y.Name) {
|
||||
return string.Compare(x.Value, y.Value);
|
||||
} else {
|
||||
return string.Compare(x.Name, y.Name);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
protected const string OAuthVersion = "1.0";
|
||||
protected const string OAuthParameterPrefix = "oauth_";
|
||||
public class OAuthSession {
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OAuthSession));
|
||||
protected const string OAUTH_VERSION = "1.0";
|
||||
protected const string OAUTH_PARAMETER_PREFIX = "oauth_";
|
||||
|
||||
//
|
||||
// List of know and used oauth parameters' names
|
||||
//
|
||||
protected const string OAuthConsumerKeyKey = "oauth_consumer_key";
|
||||
protected const string OAuthCallbackKey = "oauth_callback";
|
||||
protected const string OAuthVersionKey = "oauth_version";
|
||||
protected const string OAuthSignatureMethodKey = "oauth_signature_method";
|
||||
protected const string OAuthSignatureKey = "oauth_signature";
|
||||
protected const string OAuthTimestampKey = "oauth_timestamp";
|
||||
protected const string OAuthNonceKey = "oauth_nonce";
|
||||
protected const string OAuthTokenKey = "oauth_token";
|
||||
protected const string oAauthVerifierKey = "oauth_verifier";
|
||||
protected const string OAuthTokenSecretKey = "oauth_token_secret";
|
||||
protected const string OAUTH_CONSUMER_KEY_KEY = "oauth_consumer_key";
|
||||
protected const string OAUTH_CALLBACK_KEY = "oauth_callback";
|
||||
protected const string OAUTH_VERSION_KEY = "oauth_version";
|
||||
protected const string OAUTH_SIGNATURE_METHOD_KEY = "oauth_signature_method";
|
||||
protected const string OAUTH_TIMESTAMP_KEY = "oauth_timestamp";
|
||||
protected const string OAUTH_NONCE_KEY = "oauth_nonce";
|
||||
protected const string OAUTH_TOKEN_KEY = "oauth_token";
|
||||
protected const string OAUTH_VERIFIER_KEY = "oauth_verifier";
|
||||
protected const string OAUTH_TOKEN_SECRET_KEY = "oauth_token_secret";
|
||||
protected const string OAUTH_SIGNATURE_KEY = "oauth_signature";
|
||||
|
||||
protected const string HMACSHA1SignatureType = "HMAC-SHA1";
|
||||
protected const string PlainTextSignatureType = "PLAINTEXT";
|
||||
protected const string RSASHA1SignatureType = "RSA-SHA1";
|
||||
|
||||
public enum Method { GET, POST, PUT, DELETE };
|
||||
|
||||
protected static Random random = new Random();
|
||||
|
||||
protected const string UNRESERVED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
|
||||
|
||||
private string _userAgent = "Greenshot";
|
||||
private string _callbackUrl = "http://getgreenshot.org";
|
||||
private bool checkVerifier = true;
|
||||
private bool useHTTPHeadersForAuthorization = true;
|
||||
private bool useAuthorization = true;
|
||||
|
||||
// default browser size
|
||||
private int _browserWidth = 864;
|
||||
private int _browserHeight = 587;
|
||||
private string loginTitle = "Authorize Greenshot access";
|
||||
|
||||
#region PublicPropertiies
|
||||
public string ConsumerKey { get; set; }
|
||||
|
@ -149,23 +117,44 @@ namespace GreenshotPlugin.Core {
|
|||
set;
|
||||
}
|
||||
public string TokenSecret { get; set; }
|
||||
public string LoginTitle {
|
||||
get {
|
||||
return loginTitle;
|
||||
}
|
||||
set {
|
||||
loginTitle = value;
|
||||
}
|
||||
}
|
||||
public string Verifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool UseHTTPHeadersForAuthorization {
|
||||
get {
|
||||
return useHTTPHeadersForAuthorization;
|
||||
}
|
||||
set {
|
||||
useHTTPHeadersForAuthorization = value;
|
||||
}
|
||||
}
|
||||
public bool UseAuthorization {
|
||||
get {
|
||||
return useAuthorization;
|
||||
}
|
||||
set {
|
||||
useAuthorization = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected Random random = new Random();
|
||||
|
||||
private string oauth_verifier;
|
||||
public string Verifier { get { return oauth_verifier; } set { oauth_verifier = value; } }
|
||||
|
||||
|
||||
protected const string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to compute a hash value
|
||||
/// </summary>
|
||||
/// <param name="hashAlgorithm">The hashing algorithm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function</param>
|
||||
/// <param name="data">The data to hash</param>
|
||||
/// <returns>a Base64 string of the hash value</returns>
|
||||
private string ComputeHash(HashAlgorithm hashAlgorithm, string data) {
|
||||
private static string ComputeHash(HashAlgorithm hashAlgorithm, string data) {
|
||||
if (hashAlgorithm == null) {
|
||||
throw new ArgumentNullException("hashAlgorithm");
|
||||
}
|
||||
|
@ -174,56 +163,31 @@ namespace GreenshotPlugin.Core {
|
|||
throw new ArgumentNullException("data");
|
||||
}
|
||||
|
||||
byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(data);
|
||||
byte[] dataBuffer = System.Text.Encoding.UTF8.GetBytes(data);
|
||||
byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
|
||||
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal function to cut out all non oauth query string parameters (all parameters not begining with "oauth_")
|
||||
/// Generate the normalized paramter string
|
||||
/// </summary>
|
||||
/// <param name="parameters">The query string part of the Url</param>
|
||||
/// <returns>A list of QueryParameter each containing the parameter name and value</returns>
|
||||
private List<QueryParameter> GetQueryParameters(string parameters) {
|
||||
if (parameters.StartsWith("?")) {
|
||||
parameters = parameters.Remove(0, 1);
|
||||
/// <param name="queryParameters">the list of query parameters</param>
|
||||
/// <returns>a string with the normalized query parameters</returns>
|
||||
private static string GenerateNormalizedParametersString(IDictionary<string, string> queryParameters) {
|
||||
if (queryParameters == null || queryParameters.Count == 0) {
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
List<QueryParameter> result = new List<QueryParameter>();
|
||||
queryParameters = new SortedDictionary<string, string>(queryParameters);
|
||||
|
||||
if (!string.IsNullOrEmpty(parameters)) {
|
||||
string[] p = parameters.Split('&');
|
||||
foreach (string s in p) {
|
||||
if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix)) {
|
||||
if (s.IndexOf('=') > -1) {
|
||||
string[] temp = s.Split('=');
|
||||
result.Add(new QueryParameter(temp[0], temp[1]));
|
||||
} else {
|
||||
result.Add(new QueryParameter(s, string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (string key in queryParameters.Keys) {
|
||||
sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode3986(queryParameters[key]));
|
||||
}
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper around the EscapeDataString, as the limit is 32766 characters
|
||||
/// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx
|
||||
/// </summary>
|
||||
/// <param name="dataString"></param>
|
||||
/// <returns>escaped data string</returns>
|
||||
private static StringBuilder EscapeDataStringToStringBuilder(string dataString) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
int currentLocation = 0;
|
||||
while (currentLocation < dataString.Length) {
|
||||
string process = dataString.Substring(currentLocation, Math.Min(16384, dataString.Length - currentLocation));
|
||||
result.Append(Uri.EscapeDataString(process));
|
||||
currentLocation = currentLocation + 16384;
|
||||
}
|
||||
return result;
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -232,170 +196,26 @@ namespace GreenshotPlugin.Core {
|
|||
/// </summary>
|
||||
/// <param name="value">The value to Url encode</param>
|
||||
/// <returns>Returns a Url encoded string</returns>
|
||||
public static string UrlEncode3986(string text) {
|
||||
string[] UriRfc3986CharsToEscape = new[] { "!", "*", "'", "(", ")" };
|
||||
LOG.DebugFormat("Text size {0}", text.Length);
|
||||
StringBuilder escaped = EscapeDataStringToStringBuilder(text);
|
||||
/// <remarks>This will cause an ignorable CA1055 warning in code analysis.</remarks>
|
||||
private static string UrlEncode3986(string value) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++) {
|
||||
escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0]));
|
||||
}
|
||||
return escaped.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// Normalizes the request parameters according to the spec
|
||||
/// </summary>
|
||||
/// <param name="parameters">The list of parameters already sorted</param>
|
||||
/// <returns>a string representing the normalized parameters</returns>
|
||||
protected string NormalizeRequestParameters(IList<QueryParameter> parameters) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
QueryParameter p = null;
|
||||
for (int i = 0; i < parameters.Count; i++) {
|
||||
p = parameters[i];
|
||||
sb.AppendFormat("{0}={1}", p.Name, p.Value);
|
||||
|
||||
if (i < parameters.Count - 1) {
|
||||
sb.Append("&");
|
||||
foreach (char symbol in value) {
|
||||
if (UNRESERVED_CHARS.IndexOf(symbol) != -1) {
|
||||
result.Append(symbol);
|
||||
} else {
|
||||
result.Append('%' + String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:X2}", (int)symbol));
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the signature base that is used to produce the signature
|
||||
/// </summary>
|
||||
/// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
|
||||
/// <param name="consumerKey">The consumer key</param>
|
||||
/// <param name="token">The token, if available. If not available pass null or an empty string</param>
|
||||
/// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
|
||||
/// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
|
||||
/// <param name="signatureType">The signature type. To use the default values use <see cref="OAuthBase.SignatureTypes">OAuthBase.SignatureTypes</see>.</param>
|
||||
/// <returns>The signature base</returns>
|
||||
protected string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string callback, string signatureType, out string normalizedUrl, out string normalizedRequestParameters) {
|
||||
if (token == null) {
|
||||
token = string.Empty;
|
||||
}
|
||||
|
||||
if (tokenSecret == null) {
|
||||
tokenSecret = string.Empty;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(consumerKey)) {
|
||||
throw new ArgumentNullException("consumerKey");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(httpMethod)) {
|
||||
throw new ArgumentNullException("httpMethod");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(signatureType)) {
|
||||
throw new ArgumentNullException("signatureType");
|
||||
}
|
||||
|
||||
normalizedUrl = null;
|
||||
normalizedRequestParameters = null;
|
||||
|
||||
List<QueryParameter> parameters = GetQueryParameters(url.Query);
|
||||
parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
|
||||
parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
|
||||
parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
|
||||
parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
|
||||
parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
|
||||
|
||||
//TODO: Make this less of a hack
|
||||
if (!string.IsNullOrEmpty(callback)) {
|
||||
parameters.Add(new QueryParameter(OAuthCallbackKey, UrlEncode3986(callback)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(token)) {
|
||||
parameters.Add(new QueryParameter(OAuthTokenKey, token));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(oauth_verifier)) {
|
||||
parameters.Add(new QueryParameter(oAauthVerifierKey, oauth_verifier));
|
||||
}
|
||||
|
||||
|
||||
parameters.Sort(new QueryParameterComparer());
|
||||
|
||||
|
||||
normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
|
||||
if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) {
|
||||
normalizedUrl += ":" + url.Port;
|
||||
}
|
||||
normalizedUrl += url.AbsolutePath;
|
||||
normalizedRequestParameters = NormalizeRequestParameters(parameters);
|
||||
|
||||
StringBuilder signatureBase = new StringBuilder();
|
||||
signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
|
||||
signatureBase.AppendFormat("{0}&", UrlEncode3986(normalizedUrl));
|
||||
signatureBase.AppendFormat("{0}", UrlEncode3986(normalizedRequestParameters));
|
||||
|
||||
return signatureBase.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the signature value based on the given signature base and hash algorithm
|
||||
/// </summary>
|
||||
/// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param>
|
||||
/// <param name="hash">The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method</param>
|
||||
/// <returns>A base64 string of the hash value</returns>
|
||||
protected string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash) {
|
||||
return ComputeHash(hash, signatureBase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a signature using the HMAC-SHA1 algorithm
|
||||
/// </summary>
|
||||
/// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
|
||||
/// <param name="consumerKey">The consumer key</param>
|
||||
/// <param name="consumerSecret">The consumer seceret</param>
|
||||
/// <param name="token">The token, if available. If not available pass null or an empty string</param>
|
||||
/// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
|
||||
/// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
|
||||
/// <returns>A base64 string of the hash value</returns>
|
||||
protected string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string callback, out string normalizedUrl, out string normalizedRequestParameters) {
|
||||
return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, callback, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a signature using the specified signatureType
|
||||
/// </summary>
|
||||
/// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
|
||||
/// <param name="consumerKey">The consumer key</param>
|
||||
/// <param name="consumerSecret">The consumer seceret</param>
|
||||
/// <param name="token">The token, if available. If not available pass null or an empty string</param>
|
||||
/// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
|
||||
/// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
|
||||
/// <param name="signatureType">The type of signature to use</param>
|
||||
/// <returns>A base64 string of the hash value</returns>
|
||||
protected string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string callback, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters) {
|
||||
normalizedUrl = null;
|
||||
normalizedRequestParameters = null;
|
||||
|
||||
switch (signatureType) {
|
||||
case SignatureTypes.PLAINTEXT:
|
||||
return NetworkHelper.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
|
||||
case SignatureTypes.HMACSHA1:
|
||||
string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, callback, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
|
||||
HMACSHA1 hmacsha1 = new HMACSHA1();
|
||||
hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode3986(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode3986(tokenSecret)));
|
||||
|
||||
return GenerateSignatureUsingHash(signatureBase, hmacsha1);
|
||||
case SignatureTypes.RSASHA1:
|
||||
throw new NotImplementedException();
|
||||
default:
|
||||
throw new ArgumentException("Unknown signature type", "signatureType");
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the timestamp for the signature
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
protected virtual string GenerateTimeStamp() {
|
||||
public static string GenerateTimeStamp() {
|
||||
// Default implementation of UNIX time of the current UTC time
|
||||
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
return Convert.ToInt64(ts.TotalSeconds).ToString();
|
||||
|
@ -405,23 +225,22 @@ namespace GreenshotPlugin.Core {
|
|||
/// Generate a nonce
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual string GenerateNonce() {
|
||||
public static string GenerateNonce() {
|
||||
// Just a simple implementation of a random number between 123400 and 9999999
|
||||
return random.Next(123400, 9999999).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the request token using the consumer key and secret. Also initializes tokensecret
|
||||
/// </summary>
|
||||
/// <returns>The request token.</returns>
|
||||
public String getRequestToken() {
|
||||
private String getRequestToken() {
|
||||
string ret = null;
|
||||
string response = oAuthWebRequest(Method.POST, RequestTokenUrl, String.Empty);
|
||||
string response = oAuthWebRequestNoCheck(HTTPMethod.POST, RequestTokenUrl, null);
|
||||
if (response.Length > 0) {
|
||||
NameValueCollection qs = NetworkHelper.ParseQueryString(response);
|
||||
if (qs[OAuthTokenKey] != null) {
|
||||
this.Token = qs[OAuthTokenKey];
|
||||
this.TokenSecret = qs[OAuthTokenSecretKey];
|
||||
IDictionary<string, string> qs = NetworkHelper.ParseQueryString(response);
|
||||
if (qs.ContainsKey(OAUTH_TOKEN_KEY)) {
|
||||
this.Token = qs[OAUTH_TOKEN_KEY];
|
||||
this.TokenSecret = qs[OAUTH_TOKEN_SECRET_KEY];
|
||||
ret = this.Token;
|
||||
}
|
||||
}
|
||||
|
@ -432,13 +251,13 @@ namespace GreenshotPlugin.Core {
|
|||
/// Authorize the token by showing the dialog
|
||||
/// </summary>
|
||||
/// <returns>The request token.</returns>
|
||||
public String authorizeToken(string browserTitle) {
|
||||
private String authorizeToken() {
|
||||
if (string.IsNullOrEmpty(Token)) {
|
||||
Exception e = new Exception("The request token is not set");
|
||||
throw e;
|
||||
}
|
||||
LOG.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink);
|
||||
OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(this, browserTitle, BrowserWidth, BrowserHeight);
|
||||
OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(this, LoginTitle, BrowserWidth, BrowserHeight);
|
||||
oAuthLoginForm.ShowDialog();
|
||||
Token = oAuthLoginForm.Token;
|
||||
if (CheckVerifier) {
|
||||
|
@ -457,163 +276,200 @@ namespace GreenshotPlugin.Core {
|
|||
/// Get the access token
|
||||
/// </summary>
|
||||
/// <returns>The access token.</returns>
|
||||
public 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;
|
||||
}
|
||||
|
||||
string response = oAuthWebRequest(Method.POST, AccessTokenUrl, string.Empty);
|
||||
string response = oAuthWebRequestNoCheck(HTTPMethod.POST, AccessTokenUrl, null);
|
||||
|
||||
if (response.Length > 0) {
|
||||
NameValueCollection qs = NetworkHelper.ParseQueryString(response);
|
||||
if (qs[OAuthTokenKey] != null) {
|
||||
this.Token = qs[OAuthTokenKey];
|
||||
IDictionary<string, string> qs = NetworkHelper.ParseQueryString(response);
|
||||
if (qs.ContainsKey(OAUTH_TOKEN_KEY) && qs[OAUTH_TOKEN_KEY] != null) {
|
||||
this.Token = qs[OAUTH_TOKEN_KEY];
|
||||
}
|
||||
if (qs[OAuthTokenSecretKey] != null) {
|
||||
this.TokenSecret = qs[OAuthTokenSecretKey];
|
||||
if (qs.ContainsKey(OAUTH_TOKEN_SECRET_KEY) && qs[OAUTH_TOKEN_SECRET_KEY] != null) {
|
||||
this.TokenSecret = qs[OAUTH_TOKEN_SECRET_KEY];
|
||||
}
|
||||
}
|
||||
|
||||
return Token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method goes through the whole authorize process, including a Authorization window.
|
||||
/// </summary>
|
||||
/// <returns>true if the process is completed</returns>
|
||||
private bool authorize() {
|
||||
LOG.Debug("Creating Token");
|
||||
try {
|
||||
getRequestToken();
|
||||
} catch (Exception ex) {
|
||||
LOG.Error(ex);
|
||||
throw new NotSupportedException("Service is not available: " + ex.Message);
|
||||
}
|
||||
if (UseAuthorization && string.IsNullOrEmpty(authorizeToken())) {
|
||||
LOG.Debug("User didn't authenticate!");
|
||||
return false;
|
||||
}
|
||||
return getAccessToken() != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the link to the authorization page for this application.
|
||||
/// </summary>
|
||||
/// <returns>The url with a valid request token, or a null string.</returns>
|
||||
public string AuthorizationLink {
|
||||
get {
|
||||
return AuthorizeUrl + "?" + OAuthTokenKey + "=" + this.Token + "&" + OAuthCallbackKey + "=" + UrlEncode3986(CallbackUrl);
|
||||
return AuthorizeUrl + "?" + OAUTH_TOKEN_KEY + "=" + this.Token + "&" + OAUTH_CALLBACK_KEY + "=" + UrlEncode3986(CallbackUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper
|
||||
/// </summary>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="requestURL"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public string oAuthWebRequest(HTTPMethod method, string requestURL, IDictionary<string, string> parameters) {
|
||||
return oAuthWebRequest(method, requestURL, parameters, null, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// Submit a web request using oAuth.
|
||||
/// </summary>
|
||||
/// <param name="method">GET or POST</param>
|
||||
/// <param name="url">The full url, including the querystring.</param>
|
||||
/// <param name="requestURL">The full url, including the querystring.</param>
|
||||
/// <param name="parameters">Parameters for the request</param>
|
||||
/// <param name="contentType">contenttype for the postdata</param>
|
||||
/// <param name="postData">Data to post (MemoryStream)</param>
|
||||
/// <returns>The web server response.</returns>
|
||||
public string oAuthWebRequest(Method method, string url, MemoryStream postData) {
|
||||
string outUrl = "";
|
||||
string querystring = "";
|
||||
|
||||
Uri uri = new Uri(url);
|
||||
|
||||
string nonce = this.GenerateNonce();
|
||||
string timeStamp = this.GenerateTimeStamp();
|
||||
|
||||
string callback = "";
|
||||
if (url.ToString().Contains(RequestTokenUrl)) {
|
||||
callback = CallbackUrl;
|
||||
public string oAuthWebRequest(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 (string.IsNullOrEmpty(Token)) {
|
||||
if (!authorize()) {
|
||||
throw new Exception("Not authorized");
|
||||
}
|
||||
}
|
||||
return oAuthWebRequestNoCheck(method, requestURL, parameters, contentType, postData);
|
||||
}
|
||||
|
||||
//Generate Signature
|
||||
string sig = this.GenerateSignature(uri,
|
||||
this.ConsumerKey,
|
||||
this.ConsumerSecret,
|
||||
this.Token,
|
||||
this.TokenSecret,
|
||||
method.ToString(),
|
||||
timeStamp,
|
||||
nonce,
|
||||
callback,
|
||||
out outUrl,
|
||||
out querystring);
|
||||
|
||||
if (querystring.Length > 0) {
|
||||
querystring += "&";
|
||||
}
|
||||
querystring += OAuthSignatureKey + "=" + NetworkHelper.UrlEncode(sig);
|
||||
|
||||
if (querystring.Length > 0) {
|
||||
outUrl += "?";
|
||||
public string oAuthWebRequestNoCheck(HTTPMethod method, string requestURL, IDictionary<string, string> parameters) {
|
||||
return oAuthWebRequestNoCheck(method, requestURL, parameters, null, null);
|
||||
}
|
||||
|
||||
return WebRequest(method, outUrl + querystring, postData);
|
||||
private string oAuthWebRequestNoCheck(HTTPMethod method, string requestURL, IDictionary<string, string> parameters, string contentType, MemoryStream postData) {
|
||||
// Build the signature base
|
||||
StringBuilder signatureBase = new StringBuilder();
|
||||
|
||||
// Add Method to signature base
|
||||
signatureBase.Append(method.ToString()).Append("&");
|
||||
|
||||
// Add normalized URL
|
||||
Uri url = new Uri(requestURL);
|
||||
string normalizedUrl = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}://{1}", url.Scheme, url.Host);
|
||||
if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) {
|
||||
normalizedUrl += ":" + url.Port;
|
||||
}
|
||||
normalizedUrl += url.AbsolutePath;
|
||||
signatureBase.Append(UrlEncode3986(normalizedUrl)).Append("&");
|
||||
|
||||
// Add normalized parameters
|
||||
if (parameters == null) {
|
||||
parameters = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submit a web request using oAuth.
|
||||
/// </summary>
|
||||
/// <param name="method">GET or POST</param>
|
||||
/// <param name="url">The full url, including the querystring.</param>
|
||||
/// <param name="postData">Data to post (querystring format)</param>
|
||||
/// <returns>The web server response.</returns>
|
||||
public string oAuthWebRequest(Method method, string url, string postData) {
|
||||
string outUrl = "";
|
||||
string querystring = "";
|
||||
string ret = "";
|
||||
|
||||
//Setup postData for signing.
|
||||
//Add the postData to the querystring.
|
||||
if (method == Method.POST) {
|
||||
if (postData.Length > 0) {
|
||||
//Decode the parameters and re-encode using the oAuth UrlEncode method.
|
||||
NameValueCollection qs = NetworkHelper.ParseQueryString(postData);
|
||||
postData = "";
|
||||
foreach (string key in qs.AllKeys) {
|
||||
if (postData.Length > 0) {
|
||||
postData += "&";
|
||||
parameters.Add(OAUTH_VERSION_KEY, OAUTH_VERSION);
|
||||
parameters.Add(OAUTH_NONCE_KEY, GenerateNonce());
|
||||
parameters.Add(OAUTH_TIMESTAMP_KEY, GenerateTimeStamp());
|
||||
parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, HMACSHA1SignatureType);
|
||||
parameters.Add(OAUTH_CONSUMER_KEY_KEY, ConsumerKey);
|
||||
if (CallbackUrl != null && RequestTokenUrl != null && requestURL.ToString().StartsWith(RequestTokenUrl)) {
|
||||
parameters.Add(OAUTH_CALLBACK_KEY, CallbackUrl);
|
||||
}
|
||||
qs[key] = NetworkHelper.UrlDecode(qs[key]);
|
||||
qs[key] = UrlEncode3986(qs[key]);
|
||||
postData += key + "=" + qs[key];
|
||||
|
||||
if (!string.IsNullOrEmpty(Token)) {
|
||||
parameters.Add(OAUTH_TOKEN_KEY, Token);
|
||||
}
|
||||
signatureBase.Append(UrlEncode3986(GenerateNormalizedParametersString(parameters)));
|
||||
LOG.DebugFormat("Signature base: {0}", signatureBase);
|
||||
// Generate Signature and add it to the parameters
|
||||
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)));
|
||||
string signature = ComputeHash(hmacsha1, signatureBase.ToString());
|
||||
parameters.Add(OAUTH_SIGNATURE_KEY, signature);
|
||||
LOG.DebugFormat("Signature: {0}", signature);
|
||||
|
||||
IDictionary<string, string> requestParameters = null;
|
||||
// Add oAuth values as HTTP headers, if this is allowed
|
||||
StringBuilder authHeader = null;
|
||||
if (HTTPMethod.POST == method && UseHTTPHeadersForAuthorization) {
|
||||
authHeader = new StringBuilder();
|
||||
requestParameters = new Dictionary<string, string>();
|
||||
foreach (string parameterKey in parameters.Keys) {
|
||||
if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) {
|
||||
authHeader.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}=\"{1}\", ", parameterKey, UrlEncode3986(parameters[parameterKey]));
|
||||
} else if (!requestParameters.ContainsKey(parameterKey)) {
|
||||
LOG.DebugFormat("Request parameter: {0}={1}", parameterKey, parameters[parameterKey]);
|
||||
requestParameters.Add(parameterKey, parameters[parameterKey]);
|
||||
}
|
||||
}
|
||||
// Remove trailing comma and space and add it to the headers
|
||||
if (authHeader.Length > 0) {
|
||||
authHeader.Remove(authHeader.Length - 2, 2);
|
||||
}
|
||||
} else if (HTTPMethod.GET == method) {
|
||||
if (parameters.Count > 0) {
|
||||
// Add the parameters to the request
|
||||
requestURL += "?" + NetworkHelper.GenerateQueryParameters(parameters);
|
||||
}
|
||||
if (url.IndexOf("?") > 0) {
|
||||
url += "&";
|
||||
} else {
|
||||
url += "?";
|
||||
requestParameters = parameters;
|
||||
}
|
||||
|
||||
// Create webrequest
|
||||
HttpWebRequest webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(requestURL);
|
||||
webRequest.Method = method.ToString();
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
webRequest.UserAgent = _userAgent;
|
||||
webRequest.Timeout = 20000;
|
||||
|
||||
if (UseHTTPHeadersForAuthorization && authHeader != null) {
|
||||
LOG.DebugFormat("Authorization: OAuth {0}", authHeader.ToString());
|
||||
webRequest.Headers.Add("Authorization: OAuth " + authHeader.ToString());
|
||||
}
|
||||
|
||||
if (HTTPMethod.POST == method && postData == null && requestParameters != null && requestParameters.Count > 0) {
|
||||
StringBuilder form = new StringBuilder();
|
||||
foreach (string parameterKey in requestParameters.Keys) {
|
||||
form.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}={1}&", UrlEncode3986(parameterKey), UrlEncode3986(parameters[parameterKey]));
|
||||
}
|
||||
// Remove trailing &
|
||||
if (form.Length > 0) {
|
||||
form.Remove(form.Length - 1, 1);
|
||||
}
|
||||
LOG.DebugFormat("Form data: {0}", form.ToString());
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
byte[] data = Encoding.UTF8.GetBytes(form.ToString());
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
}
|
||||
} else {
|
||||
webRequest.ContentType = contentType;
|
||||
if (postData != null) {
|
||||
using (var requestStream = webRequest.GetRequestStream()) {
|
||||
requestStream.Write(postData.GetBuffer(), 0, (int)postData.Length);
|
||||
}
|
||||
url += postData;
|
||||
}
|
||||
}
|
||||
|
||||
Uri uri = new Uri(url);
|
||||
string responseData = WebResponseGet(webRequest);
|
||||
LOG.DebugFormat("Response: {0}", responseData);
|
||||
|
||||
string nonce = this.GenerateNonce();
|
||||
string timeStamp = this.GenerateTimeStamp();
|
||||
webRequest = null;
|
||||
|
||||
string callback = "";
|
||||
if (url.ToString().Contains(RequestTokenUrl)) {
|
||||
callback = CallbackUrl;
|
||||
}
|
||||
|
||||
//Generate Signature
|
||||
string sig = this.GenerateSignature(uri,
|
||||
this.ConsumerKey,
|
||||
this.ConsumerSecret,
|
||||
this.Token,
|
||||
this.TokenSecret,
|
||||
method.ToString(),
|
||||
timeStamp,
|
||||
nonce,
|
||||
callback,
|
||||
out outUrl,
|
||||
out querystring);
|
||||
|
||||
if (querystring.Length > 0) {
|
||||
querystring += "&";
|
||||
}
|
||||
querystring += OAuthSignatureKey + "=" + NetworkHelper.UrlEncode(sig);
|
||||
|
||||
//Convert the querystring to postData
|
||||
if (method == Method.POST) {
|
||||
postData = querystring;
|
||||
querystring = "";
|
||||
}
|
||||
|
||||
if (querystring.Length > 0) {
|
||||
outUrl += "?";
|
||||
}
|
||||
|
||||
if (method == Method.POST || method == Method.GET) {
|
||||
ret = WebRequest(method, outUrl + querystring, postData);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return responseData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -623,7 +479,7 @@ namespace GreenshotPlugin.Core {
|
|||
/// <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(Method method, string url, MemoryStream postData) {
|
||||
protected string WebRequest(HTTPMethod method, string url, string contentType, MemoryStream postData) {
|
||||
HttpWebRequest webRequest = null;
|
||||
string responseData = "";
|
||||
|
||||
|
@ -633,6 +489,10 @@ namespace GreenshotPlugin.Core {
|
|||
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);
|
||||
}
|
||||
|
@ -644,46 +504,6 @@ namespace GreenshotPlugin.Core {
|
|||
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 in querystring format</param>
|
||||
/// <returns>The web server response.</returns>
|
||||
protected string WebRequest(Method method, string url, string postData) {
|
||||
HttpWebRequest webRequest = null;
|
||||
StreamWriter requestWriter = null;
|
||||
string responseData = "";
|
||||
|
||||
webRequest = (HttpWebRequest)NetworkHelper.CreateWebRequest(url);
|
||||
webRequest.Method = method.ToString();
|
||||
webRequest.ServicePoint.Expect100Continue = false;
|
||||
webRequest.UserAgent = _userAgent;
|
||||
webRequest.Timeout = 20000;
|
||||
|
||||
if (method == Method.POST) {
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
|
||||
requestWriter = new StreamWriter(webRequest.GetRequestStream());
|
||||
try {
|
||||
requestWriter.Write(postData);
|
||||
} catch {
|
||||
throw;
|
||||
} finally {
|
||||
requestWriter.Close();
|
||||
requestWriter = null;
|
||||
}
|
||||
}
|
||||
|
||||
responseData = WebResponseGet(webRequest);
|
||||
|
||||
webRequest = null;
|
||||
|
||||
return responseData;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the web response.
|
||||
/// </summary>
|
||||
|
@ -707,4 +527,5 @@ namespace GreenshotPlugin.Core {
|
|||
return responseData;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue