Copy.com File Uploader

See #57
This commit is contained in:
Kamil Zmich 2014-06-05 19:19:45 +01:00
parent 3185442111
commit 2218ec3306
13 changed files with 4261 additions and 3439 deletions

View file

@ -815,6 +815,14 @@ public UploadResult UploadFile(Stream stream, string fileName)
ShareURLType = Program.UploadersConfig.DropboxURLType
};
break;
case FileDestination.Copy:
parser = new NameParser(NameParserType.URL);
uploadPath = parser.Parse(Copy.TidyUploadPath(Program.UploadersConfig.CopyUploadPath));
fileUploader = new Copy(Program.UploadersConfig.CopyOAuthInfo, Program.UploadersConfig.CopyAccountInfo)
{
UploadPath = uploadPath
};
break;
case FileDestination.GoogleDrive:
fileUploader = new GoogleDrive(Program.UploadersConfig.GoogleDriveOAuth2Info)
{

View file

@ -25,10 +25,6 @@ You should have received a copy of the GNU General Public License
namespace UploadersLib
{
/////////////////////////////////////////////////////////////////////////////
// Note: For be able to compile project create empty APIKeysLocal.cs file. //
/////////////////////////////////////////////////////////////////////////////
public static partial class APIKeys
{
// Image Uploaders
@ -47,6 +43,8 @@ public static partial class APIKeys
// File Uploaders
public static string DropboxConsumerKey = "";
public static string DropboxConsumerSecret = "";
public static string CopyConsumerKey = "";
public static string CopyConsumerSecret = "";
public static string MinusConsumerKey = "";
public static string MinusConsumerSecret = "";
public static string BoxClientID = "";

View file

@ -84,6 +84,8 @@ public enum FileDestination
{
[Description("dropbox.com")]
Dropbox,
[Description("copy.com")]
Copy,
[Description("FTP Server")]
FTP,
[Description("gfycat.com")]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,460 @@
#region License Information (GPL v3)
/*
ShareX - A program that allows you to take screenshots and share any file type
Copyright (C) 2007-2014 ShareX Developers
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
*/
#endregion License Information (GPL v3)
using HelpersLib;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text.RegularExpressions;
using UploadersLib.HelperClasses;
namespace UploadersLib.FileUploaders
{
public sealed class Copy : FileUploader, IOAuth
{
public OAuthInfo AuthInfo { get; set; }
public CopyAccountInfo AccountInfo { get; set; }
public string UploadPath { get; set; }
private const string APIVersion = "1";
private const string URLAPI = "https://api.copy.com/rest";
private const string URLAccountInfo = URLAPI + "/user";
private const string URLFiles = URLAPI + "/files";
private const string URLMetaData = URLAPI + "/meta/";
private const string URLLinks = URLAPI + "/links";
//private const string URLShares = URLAPI + "/shares/" + Root;
//private const string URLCopy = URLAPI + "/fileops/copy";
//private const string URLCreateFolder = URLAPI + "/fileops/create_folder";
//private const string URLDelete = URLAPI + "/fileops/delete";
//private const string URLMove = URLAPI + "/fileops/move";
private const string URLPublicDirect = "http://copy.com";
private const string URLRequestToken = "https://api.copy.com/oauth/request";
private const string URLAuthorize = "https://www.copy.com/applications/authorize";
private const string URLAccessToken = "https://api.copy.com/oauth/access";
private readonly NameValueCollection APIHeaders = new NameValueCollection {
{ "X-Api-Version", APIVersion }
};
public Copy(OAuthInfo oauth)
{
AuthInfo = oauth;
}
public Copy(OAuthInfo oauth, CopyAccountInfo accountInfo)
: this(oauth)
{
AccountInfo = accountInfo;
}
// https://developers.copy.com/documentation#authentication/oauth-handshake
// https://developers.copy.com/console
public string GetAuthorizationURL()
{
return GetAuthorizationURL(URLRequestToken, URLAuthorize, AuthInfo
, new Dictionary<string, string> { { "oauth_callback", Links.URL_CALLBACK } });
}
public bool GetAccessToken(string verificationCode = null)
{
AuthInfo.AuthVerifier = verificationCode;
return GetAccessToken(URLAccessToken, AuthInfo);
}
#region Copy accounts
// https://developers.copy.com/documentation#api-calls/profile
public CopyAccountInfo GetAccountInfo()
{
CopyAccountInfo account = null;
if (OAuthInfo.CheckOAuth(AuthInfo))
{
string query = OAuthManager.GenerateQuery(URLAccountInfo, null, HttpMethod.GET, AuthInfo);
string response = SendRequest(HttpMethod.GET, query, null, ResponseType.Text, APIHeaders);
if (!string.IsNullOrEmpty(response))
{
account = JsonConvert.DeserializeObject<CopyAccountInfo>(response);
if (account != null)
{
AccountInfo = account;
}
}
}
return account;
}
#endregion Copy accounts
#region Files and metadata
/*// https://www.dropbox.com/developers/core/api#files-GET
public bool DownloadFile(string path, Stream downloadStream)
{
if (!string.IsNullOrEmpty(path) && OAuthInfo.CheckOAuth(AuthInfo))
{
string url = Helpers.CombineURL(URLFiles, Helpers.URLPathEncode(path));
string query = OAuthManager.GenerateQuery(url, null, HttpMethod.GET, AuthInfo);
return SendRequest(HttpMethod.GET, downloadStream, query);
}
return false;
}*/
// https://developers.copy.com/documentation#api-calls/filesystem - Create File or Directory
// POST https://api.copy.com/rest/files/PATH/TO/FILE?overwrite=true
public UploadResult UploadFile(Stream stream, string path, string fileName)
{
if (!OAuthInfo.CheckOAuth(AuthInfo))
{
Errors.Add("Copy login is required.");
return null;
}
string url = Helpers.CombineURL(URLFiles, Helpers.URLPathEncode(path));
Dictionary<string, string> args = new Dictionary<string, string>();
args.Add("overwrite", "true");
string query = OAuthManager.GenerateQuery(url, args, HttpMethod.POST, AuthInfo);
// There's a 1GB and 5 hour(max time for a single upload) limit to all uploads through the API.
UploadResult result = UploadData(stream, query, fileName, "file", null, null, APIHeaders);
if (result.IsSuccess)
{
CopyUploadInfo content = JsonConvert.DeserializeObject<CopyUploadInfo>(result.Response);
if (content != null)
{
result.URL = CreatePublicURL(content.objects[0].path);
}
}
return result;
}
// https://developers.copy.com/documentation#api-calls/filesystem
public CopyContentInfo GetMetadata(string path)
{
CopyContentInfo contentInfo = null;
if (OAuthInfo.CheckOAuth(AuthInfo))
{
string url = Helpers.CombineURL(URLMetaData, Helpers.URLPathEncode(path));
string query = OAuthManager.GenerateQuery(url, null, HttpMethod.GET, AuthInfo);
string response = SendRequest(HttpMethod.GET, query);
if (!string.IsNullOrEmpty(response))
{
contentInfo = JsonConvert.DeserializeObject<CopyContentInfo>(response);
}
}
return contentInfo;
}
/*public bool IsExists(string path)
{
DropboxContentInfo contentInfo = GetMetadata(path, false);
return contentInfo != null && !contentInfo.Is_deleted;
}
// https://www.dropbox.com/developers/core/api#shares
public string CreateShareableLink(string path, DropboxURLType urlType)
{
if (!string.IsNullOrEmpty(path) && OAuthInfo.CheckOAuth(AuthInfo))
{
string url = Helpers.CombineURL(URLShares, Helpers.URLPathEncode(path));
Dictionary<string, string> args = new Dictionary<string, string>();
args.Add("short_url", urlType == DropboxURLType.Shortened ? "true" : "false");
string query = OAuthManager.GenerateQuery(url, args, HttpMethod.POST, AuthInfo);
string response = SendRequest(HttpMethod.POST, query);
if (!string.IsNullOrEmpty(response))
{
DropboxShares shares = JsonConvert.DeserializeObject<DropboxShares>(response);
if (urlType == DropboxURLType.Direct)
{
Match match = Regex.Match(shares.URL, @"https?://(?:www\.)?dropbox.com/s/(?<path>\w+/.+)");
if (match.Success)
{
string urlPath = match.Groups["path"].Value;
if (!string.IsNullOrEmpty(urlPath))
{
return Helpers.CombineURL(URLShareDirect, urlPath);
}
}
}
else
{
return shares.URL;
}
}
}
return null;
}*/
#endregion Files and metadata
#region File operations
/*// https://www.dropbox.com/developers/core/api#fileops-copy
public DropboxContentInfo Copy(string from_path, string to_path)
{
DropboxContentInfo contentInfo = null;
if (!string.IsNullOrEmpty(from_path) && !string.IsNullOrEmpty(to_path) && OAuthInfo.CheckOAuth(AuthInfo))
{
Dictionary<string, string> args = new Dictionary<string, string>();
args.Add("root", Root);
args.Add("from_path", from_path);
args.Add("to_path", to_path);
string query = OAuthManager.GenerateQuery(URLCopy, args, HttpMethod.POST, AuthInfo);
string response = SendRequest(HttpMethod.POST, query);
if (!string.IsNullOrEmpty(response))
{
contentInfo = JsonConvert.DeserializeObject<DropboxContentInfo>(response);
}
}
return contentInfo;
}
// https://www.dropbox.com/developers/core/api#fileops-create-folder
public DropboxContentInfo CreateFolder(string path)
{
DropboxContentInfo contentInfo = null;
if (!string.IsNullOrEmpty(path) && OAuthInfo.CheckOAuth(AuthInfo))
{
Dictionary<string, string> args = new Dictionary<string, string>();
args.Add("root", Root);
args.Add("path", path);
string query = OAuthManager.GenerateQuery(URLCreateFolder, args, HttpMethod.POST, AuthInfo);
string response = SendRequest(HttpMethod.POST, query);
if (!string.IsNullOrEmpty(response))
{
contentInfo = JsonConvert.DeserializeObject<DropboxContentInfo>(response);
}
}
return contentInfo;
}
// https://www.dropbox.com/developers/core/api#fileops-delete
public DropboxContentInfo Delete(string path)
{
DropboxContentInfo contentInfo = null;
if (!string.IsNullOrEmpty(path) && OAuthInfo.CheckOAuth(AuthInfo))
{
Dictionary<string, string> args = new Dictionary<string, string>();
args.Add("root", Root);
args.Add("path", path);
string query = OAuthManager.GenerateQuery(URLDelete, args, HttpMethod.POST, AuthInfo);
string response = SendRequest(HttpMethod.POST, query);
if (!string.IsNullOrEmpty(response))
{
contentInfo = JsonConvert.DeserializeObject<DropboxContentInfo>(response);
}
}
return contentInfo;
}
// https://www.dropbox.com/developers/core/api#fileops-move
public DropboxContentInfo Move(string from_path, string to_path)
{
DropboxContentInfo contentInfo = null;
if (!string.IsNullOrEmpty(from_path) && !string.IsNullOrEmpty(to_path) && OAuthInfo.CheckOAuth(AuthInfo))
{
Dictionary<string, string> args = new Dictionary<string, string>();
args.Add("root", Root);
args.Add("from_path", from_path);
args.Add("to_path", to_path);
string query = OAuthManager.GenerateQuery(URLMove, args, HttpMethod.POST, AuthInfo);
string response = SendRequest(HttpMethod.POST, query);
if (!string.IsNullOrEmpty(response))
{
contentInfo = JsonConvert.DeserializeObject<DropboxContentInfo>(response);
}
}
return contentInfo;
}*/
#endregion File operations
public override UploadResult Upload(Stream stream, string fileName)
{
return UploadFile(stream, UploadPath, fileName);
}
/* Link types:
* Shortened: http://copy.com/BWr9OswktCLl
* Extended: http://www.copy.com/s/BWr9OswktCLl/2014-06-05_17-00-01.mp4
* Direct: http://copy.com/BWr9OswktCLl/2014-06-05_17-00-01.mp4
*/
public string CreatePublicURL(string path)
{
path = path.Trim('/');
string url = Helpers.CombineURL(URLLinks, Helpers.URLPathEncode(path));
string query = OAuthManager.GenerateQuery(url, null, HttpMethod.POST, AuthInfo);
CopyLinkRequest publicLink = new CopyLinkRequest();
publicLink.@public = true;
publicLink.name = "ShareX";
publicLink.paths = new string[] { path };
string content = JsonConvert.SerializeObject(publicLink);
string response = SendRequest(HttpMethod.POST, query, content, null, ResponseType.Text, APIHeaders);
if (!string.IsNullOrEmpty(response))
{
return JsonConvert.DeserializeObject<CopyLinksInfo>(response).url_short;
}
return "";
}
public string GetPublicURL(string path)
{
path = path.Trim('/');
CopyContentInfo fileInfo = GetMetadata(path);
foreach(CopyLinksInfo link in fileInfo.links)
{
if(!link.expired)
{
return link.url_short;
}
}
return "";
}
public static string TidyUploadPath(string uploadPath)
{
if (!string.IsNullOrEmpty(uploadPath))
{
return uploadPath.Trim().Replace('\\', '/').Trim('/') + "/";
}
return string.Empty;
}
}
public class CopyAccountInfo
{
public long id { get; set; } // The user's unique Copy ID.
public string first_name { get; set; } // The user's first name.
public string last_name { get; set; } // The user's last name.
public CopyStorageInfo storage { get; set; }
public string email { get; set; }
}
public class CopyStorageInfo
{
public long used { get; set; } // The user's used quota outside of shared folders (bytes).
public long quota { get; set; } // The user's total quota allocation (bytes).
public long saved { get; set; } // The user's saved quota through shared folders (bytes).
}
public class CopyLinkRequest
{
public bool @public { get; set; }
public string name { get; set; }
public string[] paths { get; set; }
}
public class CopyLinksInfo
{
public string id { get; set; }
public string name { get; set; }
public bool @public { get; set; }
public bool expires { get; set; }
public bool expired { get; set; }
public string url { get; set; }
public string url_short { get; set; }
public string creator_id { get; set; }
public string company_id { get; set; }
public bool confirmation_required { get; set; }
public string status { get; set; }
public string permissions { get; set; }
}
public class CopyContentInfo //https://api.copy.com/rest/meta //also works on rest/meta/copy
{
public string id { get; set; } // Internal copy name
public string path { get; set; } // hmm?
public string name { get; set; } // Human readable (Filesystem) folder name
public string type { get; set; } // "inbox", "root", "copy", "dir", "file"?
public bool stub { get; set; } // 'The stub attribute you see on all of the nodes represents if the specified node is incomplete, that is, if the children have not all been delivered to you. Basically, they will always be a stub, unless you are looking at that item directly.'
public long size { get; set; } // size of the folder/file
public long date_last_synced { get; set; }
public bool @public { get; set; } // is available to public; isnt everything private but shared in copy???
public string url { get; set; } // web access url (private)
public long revision_id { get; set; } // Revision of content
public CopyLinksInfo[] links { get; set; } // links array
public CopyContentInfo[] children { get; set; } // Children
}
public class CopyUploadInfo
{
public CopyContentInfo[] objects { get; set; }
}
}

File diff suppressed because it is too large Load diff

View file

@ -83,6 +83,7 @@ private void FormSettings()
uploadersImageList.Images.Add("TwitSnaps", Resources.TwitSnaps);
uploadersImageList.Images.Add("YFrog", Resources.YFrog);
uploadersImageList.Images.Add("Dropbox", Resources.Dropbox);
uploadersImageList.Images.Add("Copy", Resources.Copy);
uploadersImageList.Images.Add("GoogleDrive", Resources.GoogleDrive);
uploadersImageList.Images.Add("Box", Resources.Box);
uploadersImageList.Images.Add("Minus", Resources.Minus);
@ -116,6 +117,7 @@ private void FormSettings()
tpTwitSnaps.ImageKey = "TwitSnaps";
tpYFrog.ImageKey = "YFrog";
tpDropbox.ImageKey = "Dropbox";
tpCopy.ImageKey = "Copy";
tpGoogleDrive.ImageKey = "GoogleDrive";
tpBox.ImageKey = "Box";
tpMinus.ImageKey = "Minus";
@ -293,6 +295,16 @@ public void LoadSettings(UploadersConfig uploadersConfig)
cbDropboxURLType.SelectedIndex = (int)Config.DropboxURLType;
UpdateDropboxStatus();
// Copy
txtCopyPath.Text = Config.CopyUploadPath;
if (OAuthInfo.CheckOAuth(Config.CopyOAuthInfo))
{
oAuthCopy.Status = "Login successful.";
oAuthCopy.LoginStatus = true;
}
// Google Drive
if (OAuth2Info.CheckOAuth(Config.GoogleDriveOAuth2Info))
@ -952,6 +964,36 @@ private void cbDropboxURLType_SelectedIndexChanged(object sender, EventArgs e)
#endregion Dropbox
#region Copy
private void pbCopyLogo_Click(object sender, EventArgs e)
{
Helpers.OpenURL("https://copy.com");
}
private void btnCopyRegister_Click(object sender, EventArgs e)
{
Helpers.OpenURL("https://copy.com?r=hC3DMW");
}
private void txtCopyPath_TextChanged(object sender, EventArgs e)
{
Config.CopyUploadPath = txtCopyPath.Text;
UpdateCopyStatus();
}
private void oAuthCopy_OpenButtonClicked()
{
CopyAuthOpen();
}
private void oAuthCopy_CompleteButtonClicked(string code)
{
CopyAuthComplete(code);
}
#endregion Copy
#region Google Drive
private void oauth2GoogleDrive_OpenButtonClicked()

View file

@ -117,6 +117,19 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="ttHelpTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="cbAmazonS3UseRRS.ToolTip" xml:space="preserve">
<value>Use a lower-redundancy storage class for stored objects.
With this option, objects are cheaper to store, but have 99.99% durability, instead of 99.999999999%.
This means that they may be lost from Amazon S3 at some point.</value>
</data>
<data name="cbAmazonS3CustomCNAME.ToolTip" xml:space="preserve">
<value>Use this option if you have a bucket set up with a custom domain.
If text field is empty then bucket name will be used for URL.
For example, if your bucket is called bucket.example.com then URL will be http://bucket.example.com/...</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="pbDropboxLogo.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
@ -234,18 +247,92 @@
cEDOIz9clMt26LAWUUxcLUy92z9hAUk7h0+HDimqY/4fT5V6IeBXOg8AAAAASUVORK5CYII=
</value>
</data>
<metadata name="ttHelpTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="cbAmazonS3CustomCNAME.ToolTip" xml:space="preserve">
<value>Use this option if you have a bucket set up with a custom domain.
If text field is empty then bucket name will be used for URL.
For example, if your bucket is called bucket.example.com then URL will be http://bucket.example.com/...</value>
</data>
<data name="cbAmazonS3UseRRS.ToolTip" xml:space="preserve">
<value>Use a lower-redundancy storage class for stored objects.
With this option, objects are cheaper to store, but have 99.99% durability, instead of 99.999999999%.
This means that they may be lost from Amazon S3 at some point.</value>
<data name="pbCopyLogo.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcI
CQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwM
DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABAAMkDASIAAhEBAxEB/8QA
HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh
MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW
V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG
x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQF
BgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq
8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAopGcKeTS5oAKKKKACiisP4j/ABB0n4WeBdV8
Ra5dLZ6Vo1u11cyt/CqjoB3YnAA6kkDqaqMXKSjFXbM61aFKDq1GlGKbbeiSWrbfZHO/EX40x+FPir4N
8G2Kx3eueKp5pmjPSzsYIy807Y6ZbZGgPVnPUK2O8QkrzXxb/wAE2vFmqftQ/tEfEz4va1C0Ue2HRNIh
JDJZwsTKYR/tRxrb5YY3NNIeM4r7Ur084wKwVdYV/FFLm/xPVr5JpeqZ8vwbns86wUs1WlKpOXsls/Zx
fKm/OTjKXkpJdAoooryj6wKKKKACiiigAooooAKKKKACiiigAooooAKKKKACoby+h0+1kmuJo4YYVLyS
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
</value>
</data>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>72</value>

View file

@ -546,6 +546,103 @@ private string GetDropboxUploadPath()
#endregion Dropbox
#region Copy
public void CopyAuthOpen()
{
try
{
OAuthInfo oauth = new OAuthInfo(APIKeys.CopyConsumerKey, APIKeys.CopyConsumerSecret);
string url = new Copy(oauth).GetAuthorizationURL();
if (!string.IsNullOrEmpty(url))
{
Config.CopyOAuthInfo = oauth;
Helpers.OpenURL(url);
DebugHelper.WriteLine("CopyAuthOpen - Authorization URL is opened: " + url);
}
else
{
DebugHelper.WriteLine("CopyAuthOpen - Authorization URL is empty.");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public void CopyAuthComplete(string code)
{
try
{
if (Config.CopyOAuthInfo != null && !string.IsNullOrEmpty(Config.CopyOAuthInfo.AuthToken)
&& !string.IsNullOrEmpty(Config.CopyOAuthInfo.AuthSecret) && !string.IsNullOrEmpty(code))
{
Copy copy = new Copy(Config.CopyOAuthInfo);
bool result = copy.GetAccessToken(code);
if (result)
{
CopyAccountInfo account = copy.GetAccountInfo();
if (account != null)
{
Config.CopyAccountInfo = account;
Config.CopyUploadPath = txtCopyPath.Text;
UpdateCopyStatus();
MessageBox.Show("Login successful.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
MessageBox.Show("GetAccountInfo failed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show("Login failed.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("You must gain access from the Authorize page and copy the verification code into the box first.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Config.CopyOAuthInfo = null;
UpdateCopyStatus();
}
catch (Exception ex)
{
DebugHelper.WriteException(ex);
MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpdateCopyStatus()
{
if (OAuthInfo.CheckOAuth(Config.CopyOAuthInfo) && Config.CopyAccountInfo != null)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Login status: Successful");
sb.AppendLine("Email: " + Config.CopyAccountInfo.email);
sb.AppendLine("Name: " + Config.CopyAccountInfo.first_name + " " + Config.CopyAccountInfo.last_name);
sb.AppendLine("User ID: " + Config.CopyAccountInfo.id.ToString());
sb.AppendLine("Upload path: " + GetCopyUploadPath());
lblCopyStatus.Text = sb.ToString();
}
else
{
lblCopyStatus.Text = "Login status: Authorize required";
}
}
private string GetCopyUploadPath()
{
return new NameParser(NameParserType.URL).Parse(Copy.TidyUploadPath(Config.CopyUploadPath));
}
#endregion Copy
#region Amazon S3
private void UpdateAmazonS3Status()

View file

@ -90,6 +90,16 @@ internal static System.Drawing.Icon Box {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
internal static System.Drawing.Icon Copy {
get {
object obj = ResourceManager.GetObject("Copy", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>

View file

@ -121,6 +121,9 @@
<data name="Dropbox" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Favicons\Dropbox.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Copy" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Favicons\Copy.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Flickr" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Favicons\Flickr.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>

View file

@ -122,6 +122,12 @@ public class UploadersConfig : SettingsBase<UploadersConfig>
public bool DropboxAutoCreateShareableLink = false;
public DropboxURLType DropboxURLType = DropboxURLType.Default;
// Copy
public OAuthInfo CopyOAuthInfo = null;
public CopyAccountInfo CopyAccountInfo = null;
public string CopyUploadPath = "ShareX/%y/%mo";
// Google Drive
public OAuth2Info GoogleDriveOAuth2Info = null;
@ -326,6 +332,8 @@ public bool IsActive(FileDestination destination)
{
case FileDestination.Dropbox:
return OAuthInfo.CheckOAuth(DropboxOAuthInfo);
case FileDestination.Copy:
return OAuthInfo.CheckOAuth(CopyOAuthInfo);
case FileDestination.GoogleDrive:
return OAuth2Info.CheckOAuth(GoogleDriveOAuth2Info);
case FileDestination.RapidShare:

View file

@ -101,6 +101,7 @@
<Compile Include="APIKeys\APIKeys.cs" />
<Compile Include="APIKeys\APIKeysLocal.cs" />
<Compile Include="FileUploaders\Box.cs" />
<Compile Include="FileUploaders\Copy.cs" />
<Compile Include="FileUploaders\Email.cs" />
<Compile Include="FileUploaders\Ge_tt.cs" />
<Compile Include="FileUploaders\AmazonS3.cs" />