mirror of
https://github.com/greenshot/greenshot
synced 2025-08-22 06:23:24 -07:00
Continuing work on the OAuth simplification, and going via our website.
This commit is contained in:
parent
51ea5fdc94
commit
3d61b8e28c
6 changed files with 137 additions and 51 deletions
|
@ -21,7 +21,6 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using GreenshotPlugin.Controls;
|
||||
using GreenshotPlugin.Core;
|
||||
|
@ -102,20 +101,16 @@ namespace GreenshotDropboxPlugin {
|
|||
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) {
|
||||
uploadUrl = null;
|
||||
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
|
||||
try {
|
||||
string dropboxUrl = null;
|
||||
try
|
||||
{
|
||||
bool result = false;
|
||||
new PleaseWaitForm().ShowAndWait("Dropbox", Language.GetString("dropbox", LangKey.communication_wait),
|
||||
delegate
|
||||
{
|
||||
string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
|
||||
dropboxUrl = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, filename);
|
||||
result = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, captureDetails);
|
||||
}
|
||||
);
|
||||
if (dropboxUrl == null) {
|
||||
return false;
|
||||
}
|
||||
uploadUrl = dropboxUrl;
|
||||
return true;
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.Error(e);
|
||||
MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message);
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using GreenshotPlugin.Core;
|
||||
using GreenshotPlugin.Core.OAuth;
|
||||
using GreenshotPlugin.IniFile;
|
||||
using GreenshotPlugin.Interfaces;
|
||||
using GreenshotPlugin.Interfaces.Plugin;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GreenshotDropboxPlugin {
|
||||
/// <summary>
|
||||
|
@ -37,11 +39,11 @@ namespace GreenshotDropboxPlugin {
|
|||
private DropboxUtils() {
|
||||
}
|
||||
|
||||
public static string UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string filename) {
|
||||
|
||||
public static bool UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, ICaptureDetails captureDetails)
|
||||
{
|
||||
var oauth2Settings = new OAuth2Settings
|
||||
{
|
||||
AuthUrlPattern = "https://api.dropbox.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}&redirect_uri={RedirectUrl}&token_access_type=offline",
|
||||
AuthUrlPattern = "https://api.dropbox.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}&redirect_uri={RedirectUrl}",
|
||||
TokenUrl = "https://api.dropbox.com/oauth2/token",
|
||||
RedirectUrl = "https://getgreenshot.org/authorize/dropbox",
|
||||
CloudServiceName = "Dropbox",
|
||||
|
@ -55,20 +57,28 @@ namespace GreenshotDropboxPlugin {
|
|||
|
||||
try
|
||||
{
|
||||
string filename = Path.GetFileName(FilenameHelper.GetFilename(DropboxConfig.UploadFormat, captureDetails));
|
||||
SurfaceContainer image = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
|
||||
|
||||
IDictionary<string, object> parameters = new Dictionary<string, object>
|
||||
IDictionary<string, object> arguments = new Dictionary<string, object>
|
||||
{
|
||||
{ "file", image },
|
||||
{ "autorename", true },
|
||||
{ "mute", true },
|
||||
{ "path", filename}
|
||||
{ "path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')}
|
||||
};
|
||||
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, "https://api.dropbox.com//2/files/upload", oauth2Settings);
|
||||
NetworkHelper.WriteMultipartFormData(webRequest, parameters);
|
||||
var response = NetworkHelper.GetResponseAsString(webRequest);
|
||||
Log.DebugFormat("Upload response: {0}", response);
|
||||
} catch (Exception ex) {
|
||||
IDictionary<string, object> headers = new Dictionary<string, object>
|
||||
{
|
||||
{ "Dropbox-API-Arg", JsonConvert.SerializeObject(arguments)}
|
||||
};
|
||||
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, "https://content.dropboxapi.com/2/files/upload", oauth2Settings);
|
||||
|
||||
NetworkHelper.Post(webRequest, headers, image);
|
||||
var responseString = NetworkHelper.GetResponseAsString(webRequest);
|
||||
Log.DebugFormat("Upload response: {0}", responseString);
|
||||
var response = JsonConvert.DeserializeObject<IDictionary<string, string>>(responseString);
|
||||
return response.ContainsKey("id");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Log.Error("Upload error: ", ex);
|
||||
throw;
|
||||
} finally {
|
||||
|
@ -78,7 +88,6 @@ namespace GreenshotDropboxPlugin {
|
|||
DropboxConfig.IsDirty = true;
|
||||
IniConfig.Save();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,6 +358,84 @@ namespace GreenshotPlugin.Core {
|
|||
WriteMultipartFormData(formDataStream, boundary, postParameters);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Post content HttpWebRequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
|
||||
/// <param name="headers">IDictionary with the headers</param>
|
||||
/// <param name="binaryContainer">IBinaryContainer</param>
|
||||
public static void Post(HttpWebRequest webRequest, IDictionary<string, object> headers, IBinaryContainer binaryContainer = null)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
switch (header.Key)
|
||||
{
|
||||
case "Content-Type":
|
||||
webRequest.ContentType = header.Value as string;
|
||||
break;
|
||||
case "Accept":
|
||||
webRequest.Accept = header.Value as string;
|
||||
break;
|
||||
default:
|
||||
webRequest.Headers.Add(header.Key, Convert.ToString(header.Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!headers.ContainsKey("Content-Type"))
|
||||
{
|
||||
webRequest.ContentType = "application/octet-stream";
|
||||
}
|
||||
|
||||
if (binaryContainer != null)
|
||||
{
|
||||
using var requestStream = webRequest.GetRequestStream();
|
||||
binaryContainer.WriteToStream(requestStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post content HttpWebRequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
|
||||
/// <param name="headers">IDictionary with the headers</param>
|
||||
/// <param name="jsonString">string</param>
|
||||
public static void Post(HttpWebRequest webRequest, IDictionary<string, object> headers, string jsonString)
|
||||
{
|
||||
if (headers != null)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
switch (header.Key)
|
||||
{
|
||||
case "Content-Type":
|
||||
webRequest.ContentType = header.Value as string;
|
||||
break;
|
||||
case "Accept":
|
||||
webRequest.Accept = header.Value as string;
|
||||
break;
|
||||
default:
|
||||
webRequest.Headers.Add(header.Key, Convert.ToString(header.Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!headers.ContainsKey("Content-Type"))
|
||||
{
|
||||
webRequest.ContentType = "application/json";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
webRequest.ContentType = "application/json";
|
||||
}
|
||||
|
||||
if (jsonString != null)
|
||||
{
|
||||
using var requestStream = webRequest.GetRequestStream();
|
||||
using var streamWriter = new StreamWriter(requestStream);
|
||||
streamWriter.Write(jsonString);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data to the HttpListenerResponse
|
||||
/// </summary>
|
||||
|
|
|
@ -51,7 +51,6 @@ namespace GreenshotPlugin.Core.OAuth {
|
|||
// Use the returned code to get a refresh code
|
||||
{ Code, settings.Code },
|
||||
{ ClientId, settings.ClientId },
|
||||
{ RedirectUri, settings.RedirectUrl },
|
||||
{ ClientSecret, settings.ClientSecret },
|
||||
{ GrantType, AuthorizationCode }
|
||||
};
|
||||
|
@ -194,29 +193,29 @@ namespace GreenshotPlugin.Core.OAuth {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate by using the mode specified in the settings
|
||||
/// Authorize by using the mode specified in the settings
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings</param>
|
||||
/// <returns>false if it was canceled, true if it worked, exception if not</returns>
|
||||
public static bool Authenticate(OAuth2Settings settings) {
|
||||
public static bool Authorize(OAuth2Settings settings) {
|
||||
var completed = settings.AuthorizeMode switch
|
||||
{
|
||||
OAuth2AuthorizeMode.LocalServer => AuthenticateViaLocalServer(settings),
|
||||
OAuth2AuthorizeMode.EmbeddedBrowser => AuthenticateViaEmbeddedBrowser(settings),
|
||||
OAuth2AuthorizeMode.JsonReceiver => AuthenticateViaDefaultBrowser(settings),
|
||||
OAuth2AuthorizeMode.LocalServer => AuthorizeViaLocalServer(settings),
|
||||
OAuth2AuthorizeMode.EmbeddedBrowser => AuthorizeViaEmbeddedBrowser(settings),
|
||||
OAuth2AuthorizeMode.JsonReceiver => AuthorizeViaDefaultBrowser(settings),
|
||||
_ => throw new NotImplementedException($"Authorize mode '{settings.AuthorizeMode}' is not 'yet' implemented."),
|
||||
};
|
||||
return completed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate via the default browser, via the Greenshot website.
|
||||
/// Authorize via the default browser, via the Greenshot website.
|
||||
/// It will wait for a Json post.
|
||||
/// If this works, return the code
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings with the Auth / Token url etc</param>
|
||||
/// <returns>true if completed, false if canceled</returns>
|
||||
private static bool AuthenticateViaDefaultBrowser(OAuth2Settings settings)
|
||||
private static bool AuthorizeViaDefaultBrowser(OAuth2Settings settings)
|
||||
{
|
||||
var codeReceiver = new LocalJsonReceiver();
|
||||
IDictionary<string, string> result = codeReceiver.ReceiveCode(settings);
|
||||
|
@ -260,18 +259,19 @@ namespace GreenshotPlugin.Core.OAuth {
|
|||
{
|
||||
settings.Code = code;
|
||||
GenerateRefreshToken(settings);
|
||||
return !string.IsNullOrEmpty(settings.AccessToken);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate via an embedded browser
|
||||
/// Authorize via an embedded browser
|
||||
/// If this works, return the code
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings with the Auth / Token url etc</param>
|
||||
/// <returns>true if completed, false if canceled</returns>
|
||||
private static bool AuthenticateViaEmbeddedBrowser(OAuth2Settings settings) {
|
||||
private static bool AuthorizeViaEmbeddedBrowser(OAuth2Settings settings) {
|
||||
if (string.IsNullOrEmpty(settings.CloudServiceName)) {
|
||||
throw new ArgumentNullException(nameof(settings.CloudServiceName));
|
||||
}
|
||||
|
@ -290,12 +290,12 @@ namespace GreenshotPlugin.Core.OAuth {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate via a local server by using the LocalServerCodeReceiver
|
||||
/// Authorize via a local server by using the LocalServerCodeReceiver
|
||||
/// If this works, return the code
|
||||
/// </summary>
|
||||
/// <param name="settings">OAuth2Settings with the Auth / Token url etc</param>
|
||||
/// <returns>true if completed</returns>
|
||||
private static bool AuthenticateViaLocalServer(OAuth2Settings settings) {
|
||||
private static bool AuthorizeViaLocalServer(OAuth2Settings settings) {
|
||||
var codeReceiver = new LocalServerCodeReceiver();
|
||||
IDictionary<string, string> result = codeReceiver.ReceiveCode(settings);
|
||||
|
||||
|
@ -335,7 +335,7 @@ namespace GreenshotPlugin.Core.OAuth {
|
|||
public static void CheckAndAuthenticateOrRefresh(OAuth2Settings settings) {
|
||||
// Get Refresh / Access token
|
||||
if (string.IsNullOrEmpty(settings.RefreshToken)) {
|
||||
if (!Authenticate(settings)) {
|
||||
if (!Authorize(settings)) {
|
||||
throw new Exception("Authentication cancelled");
|
||||
}
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ namespace GreenshotPlugin.Core.OAuth {
|
|||
GenerateAccessToken(settings);
|
||||
// Get Refresh / Access token
|
||||
if (string.IsNullOrEmpty(settings.RefreshToken)) {
|
||||
if (!Authenticate(settings)) {
|
||||
if (!Authorize(settings)) {
|
||||
throw new Exception("Authentication cancelled");
|
||||
}
|
||||
GenerateAccessToken(settings);
|
||||
|
|
|
@ -137,6 +137,10 @@ namespace GreenshotPlugin.Core.OAuth
|
|||
/// </summary>
|
||||
public bool IsAccessTokenExpired {
|
||||
get {
|
||||
if (AccessTokenExpires == default)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool expired = true;
|
||||
if (!string.IsNullOrEmpty(AccessToken)) {
|
||||
expired = DateTimeOffset.Now.AddSeconds(60) > AccessTokenExpires;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue