PageRenderTime 62ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/ShareX.UploadersLib/FileUploaders/Copy.cs

https://gitlab.com/billyprice1/ShareX
C# | 329 lines | 233 code | 65 blank | 31 comment | 20 complexity | eae33e22fdc125a9c674855daa80c2f4 MD5 | raw file
  1. #region License Information (GPL v3)
  2. /*
  3. ShareX - A program that allows you to take screenshots and share any file type
  4. Copyright (c) 2007-2016 ShareX Team
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. Optionally you can also view the license at <http://www.gnu.org/licenses/>.
  17. */
  18. #endregion License Information (GPL v3)
  19. // Credits: https://github.com/KamilKZ
  20. using Newtonsoft.Json;
  21. using ShareX.HelpersLib;
  22. using System.Collections.Generic;
  23. using System.Collections.Specialized;
  24. using System.IO;
  25. namespace ShareX.UploadersLib.FileUploaders
  26. {
  27. public sealed class Copy : FileUploader, IOAuth
  28. {
  29. public OAuthInfo AuthInfo { get; set; }
  30. public CopyAccountInfo AccountInfo { get; set; }
  31. public string UploadPath { get; set; }
  32. public CopyURLType URLType { get; set; }
  33. private const string APIVersion = "1";
  34. private const string URLAPI = "https://api.copy.com/rest";
  35. private const string URLAccountInfo = URLAPI + "/user";
  36. private const string URLFiles = URLAPI + "/files";
  37. private const string URLMetaData = URLAPI + "/meta/";
  38. private const string URLLinks = URLAPI + "/links";
  39. private const string URLRequestToken = "https://api.copy.com/oauth/request";
  40. private const string URLAuthorize = "https://www.copy.com/applications/authorize";
  41. private const string URLAccessToken = "https://api.copy.com/oauth/access";
  42. private readonly NameValueCollection APIHeaders = new NameValueCollection { { "X-Api-Version", APIVersion } };
  43. public Copy(OAuthInfo oauth)
  44. {
  45. AuthInfo = oauth;
  46. }
  47. public Copy(OAuthInfo oauth, CopyAccountInfo accountInfo) : this(oauth)
  48. {
  49. AccountInfo = accountInfo;
  50. }
  51. // https://developers.copy.com/documentation#authentication/oauth-handshake
  52. // https://developers.copy.com/console
  53. public string GetAuthorizationURL()
  54. {
  55. Dictionary<string, string> args = new Dictionary<string, string>();
  56. args.Add("oauth_callback", Links.URL_CALLBACK);
  57. return GetAuthorizationURL(URLRequestToken, URLAuthorize, AuthInfo, args);
  58. }
  59. public bool GetAccessToken(string verificationCode = null)
  60. {
  61. AuthInfo.AuthVerifier = verificationCode;
  62. return GetAccessToken(URLAccessToken, AuthInfo);
  63. }
  64. #region Copy accounts
  65. // https://developers.copy.com/documentation#api-calls/profile
  66. public CopyAccountInfo GetAccountInfo()
  67. {
  68. CopyAccountInfo account = null;
  69. if (OAuthInfo.CheckOAuth(AuthInfo))
  70. {
  71. string query = OAuthManager.GenerateQuery(URLAccountInfo, null, HttpMethod.GET, AuthInfo);
  72. string response = SendRequest(HttpMethod.GET, query, null, APIHeaders);
  73. if (!string.IsNullOrEmpty(response))
  74. {
  75. account = JsonConvert.DeserializeObject<CopyAccountInfo>(response);
  76. if (account != null)
  77. {
  78. AccountInfo = account;
  79. }
  80. }
  81. }
  82. return account;
  83. }
  84. #endregion Copy accounts
  85. #region Files and metadata
  86. // https://developers.copy.com/documentation#api-calls/filesystem - Download Raw File Conents
  87. // GET https://api.copy.com/rest/files/PATH/TO/FILE
  88. public bool DownloadFile(string path, Stream downloadStream)
  89. {
  90. if (!string.IsNullOrEmpty(path) && OAuthInfo.CheckOAuth(AuthInfo))
  91. {
  92. string url = URLHelpers.CombineURL(URLFiles, URLHelpers.URLPathEncode(path));
  93. string query = OAuthManager.GenerateQuery(url, null, HttpMethod.GET, AuthInfo);
  94. return SendRequest(HttpMethod.GET, downloadStream, query);
  95. }
  96. return false;
  97. }
  98. // https://developers.copy.com/documentation#api-calls/filesystem - Create File or Directory
  99. // POST https://api.copy.com/rest/files/PATH/TO/FILE?overwrite=true
  100. public UploadResult UploadFile(Stream stream, string path, string fileName)
  101. {
  102. if (!OAuthInfo.CheckOAuth(AuthInfo))
  103. {
  104. Errors.Add("Copy login is required.");
  105. return null;
  106. }
  107. string url = URLHelpers.CombineURL(URLFiles, URLHelpers.URLPathEncode(path));
  108. Dictionary<string, string> args = new Dictionary<string, string>();
  109. args.Add("overwrite", "true");
  110. string query = OAuthManager.GenerateQuery(url, args, HttpMethod.POST, AuthInfo);
  111. // There's a 1GB and 5 hour(max time for a single upload) limit to all uploads through the API.
  112. UploadResult result = UploadData(stream, query, fileName, "file", headers: APIHeaders);
  113. if (result.IsSuccess)
  114. {
  115. CopyUploadInfo content = JsonConvert.DeserializeObject<CopyUploadInfo>(result.Response);
  116. if (content != null && content.objects != null && content.objects.Length > 0)
  117. {
  118. AllowReportProgress = false;
  119. result.URL = CreatePublicURL(content.objects[0].path, URLType);
  120. }
  121. }
  122. return result;
  123. }
  124. // https://developers.copy.com/documentation#api-calls/filesystem - Read Root Directory
  125. // GET https://api.copy.com/rest/meta/copy
  126. public CopyContentInfo GetMetadata(string path)
  127. {
  128. CopyContentInfo contentInfo = null;
  129. if (OAuthInfo.CheckOAuth(AuthInfo))
  130. {
  131. string url = URLHelpers.CombineURL(URLMetaData, URLHelpers.URLPathEncode(path));
  132. string query = OAuthManager.GenerateQuery(url, null, HttpMethod.GET, AuthInfo);
  133. string response = SendRequest(HttpMethod.GET, query);
  134. if (!string.IsNullOrEmpty(response))
  135. {
  136. contentInfo = JsonConvert.DeserializeObject<CopyContentInfo>(response);
  137. }
  138. }
  139. return contentInfo;
  140. }
  141. #endregion Files and metadata
  142. public override UploadResult Upload(Stream stream, string fileName)
  143. {
  144. return UploadFile(stream, UploadPath, fileName);
  145. }
  146. public string GetLinkURL(CopyLinksInfo link, string path, CopyURLType urlType = CopyURLType.Default)
  147. {
  148. string filename = URLHelpers.URLEncode(URLHelpers.GetFileName(path));
  149. switch (urlType)
  150. {
  151. default:
  152. case CopyURLType.Default:
  153. return string.Format("https://www.copy.com/s/{0}/{1}", link.id, filename);
  154. case CopyURLType.Shortened:
  155. return string.Format("https://copy.com/{0}", link.id);
  156. case CopyURLType.Direct:
  157. return string.Format("https://copy.com/{0}/{1}", link.id, filename);
  158. }
  159. }
  160. public string CreatePublicURL(string path, CopyURLType urlType = CopyURLType.Default)
  161. {
  162. path = path.Trim('/');
  163. string url = URLHelpers.CombineURL(URLLinks, URLHelpers.URLPathEncode(path));
  164. string query = OAuthManager.GenerateQuery(url, null, HttpMethod.POST, AuthInfo);
  165. CopyLinkRequest publicLink = new CopyLinkRequest();
  166. publicLink.@public = true;
  167. publicLink.name = "ShareX";
  168. publicLink.paths = new string[] { path };
  169. string content = JsonConvert.SerializeObject(publicLink);
  170. string response = SendRequest(HttpMethod.POST, query, content, headers: APIHeaders);
  171. if (!string.IsNullOrEmpty(response))
  172. {
  173. CopyLinksInfo link = JsonConvert.DeserializeObject<CopyLinksInfo>(response);
  174. return GetLinkURL(link, path, urlType);
  175. }
  176. return "";
  177. }
  178. public string GetPublicURL(string path, CopyURLType urlType = CopyURLType.Default)
  179. {
  180. path = path.Trim('/');
  181. CopyContentInfo fileInfo = GetMetadata(path);
  182. foreach (CopyLinksInfo link in fileInfo.links)
  183. {
  184. if (!link.expired && link.@public)
  185. {
  186. return GetLinkURL(link, path, urlType);
  187. }
  188. }
  189. return "";
  190. }
  191. public static string TidyUploadPath(string uploadPath)
  192. {
  193. if (!string.IsNullOrEmpty(uploadPath))
  194. {
  195. return uploadPath.Trim().Replace('\\', '/').Trim('/') + "/";
  196. }
  197. return "";
  198. }
  199. }
  200. public enum CopyURLType
  201. {
  202. Default,
  203. Shortened,
  204. Direct
  205. }
  206. public class CopyAccountInfo
  207. {
  208. public long id { get; set; } // The user's unique Copy ID.
  209. public string first_name { get; set; } // The user's first name.
  210. public string last_name { get; set; } // The user's last name.
  211. public CopyStorageInfo storage { get; set; }
  212. public string email { get; set; }
  213. }
  214. public class CopyStorageInfo
  215. {
  216. public long used { get; set; } // The user's used quota outside of shared folders (bytes).
  217. public long quota { get; set; } // The user's total quota allocation (bytes).
  218. public long saved { get; set; } // The user's saved quota through shared folders (bytes).
  219. }
  220. public class CopyLinkRequest
  221. {
  222. public bool @public { get; set; }
  223. public string name { get; set; }
  224. public string[] paths { get; set; }
  225. }
  226. public class CopyLinksInfo
  227. {
  228. public string id { get; set; }
  229. public string name { get; set; }
  230. public bool @public { get; set; }
  231. public bool expires { get; set; }
  232. public bool expired { get; set; }
  233. public string url { get; set; }
  234. public string url_short { get; set; }
  235. public string creator_id { get; set; }
  236. public string company_id { get; set; }
  237. public bool confirmation_required { get; set; }
  238. public string status { get; set; }
  239. public string permissions { get; set; }
  240. }
  241. public class CopyContentInfo // https://api.copy.com/rest/meta also works on 'rest/files'
  242. {
  243. public string id { get; set; } // Internal copy name
  244. public string path { get; set; } // file path
  245. public string name { get; set; } // Human readable (Filesystem) folder name
  246. public string type { get; set; } // "inbox", "root", "copy", "dir", "file"?
  247. 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.'
  248. public long? size { get; set; } // Filesizes (size attributes) are measured in bytes. If an item displayed in the filesystem is a directory or an otherwise special location which doesn't represent a file, the size attribute will be null.
  249. public long date_last_synced { get; set; }
  250. public bool @public { get; set; } // is available to public; isnt everything private but shared in copy???
  251. public string url { get; set; } // web access url (private)
  252. public long revision_id { get; set; } // Revision of content
  253. public CopyLinksInfo[] links { get; set; } // links array
  254. public CopyContentInfo[] children { get; set; } // Children
  255. }
  256. public class CopyUploadInfo
  257. {
  258. public CopyContentInfo[] objects { get; set; }
  259. }
  260. }