├── test ├── Test.res ├── Test.dpr ├── DropboxManager.Tests.pas └── Test.dproj ├── .gitattributes ├── README.md ├── .gitignore ├── src ├── DropboxApi.pas ├── DropboxApi.Routes.pas ├── DropboxApi.Persister.pas ├── DropboxManager.pas ├── DropboxApi.Requests.pas └── DropboxApi.Data.pas └── LICENSE /test/Test.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverComponents/DropBox-Delphi-API/HEAD/test/Test.res -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Denote all files that are truly binary and should not be modified. 5 | *.dat binary 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dropbox API for Delphi 2 | 3 | 4 | 5 | The Dropbox API library for Delphi allows working with Dropbox directory using official Dropbox API v2. 6 | 7 | The library includes a powerful OAuth 2.0 support with a consistent interface. You can use the Dropbox API for Delphi to download and upload files, manage files and folders on Dropbox directory. 8 | 9 | This article describes how connect to Dropbox account in Delphi, download and upload files programmatically, create remote folders and save an URL into a file in user's Dropbox. 10 | 11 | [Read the article](https://www.clevercomponents.com/articles/article041/) 12 | -------------------------------------------------------------------------------- /test/Test.dpr: -------------------------------------------------------------------------------- 1 | program Test; 2 | 3 | uses 4 | Vcl.Forms, 5 | TestFrameWork, 6 | GUITestRunner, 7 | DropboxManager.Tests in 'DropboxManager.Tests.pas', 8 | clJsonSerializer in '..\..\JsonSerializer\json\clJsonSerializer.pas', 9 | clJsonSerializerBase in '..\..\JsonSerializer\json\clJsonSerializerBase.pas', 10 | DropboxManager in '..\src\DropboxManager.pas', 11 | DropboxApi.Data in '..\src\DropboxApi.Data.pas', 12 | DropboxApi in '..\src\DropboxApi.pas', 13 | DropboxApi.Persister in '..\src\DropboxApi.Persister.pas', 14 | DropboxApi.Routes in '..\src\DropboxApi.Routes.pas', 15 | DropboxApi.Requests in '..\src\DropboxApi.Requests.pas', 16 | clJsonParser in '..\..\JsonSerializer\json\clJsonParser.pas'; 17 | 18 | {$R *.res} 19 | 20 | begin 21 | Application.Initialize; 22 | GUITestRunner.RunRegisteredTests; 23 | end. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | -------------------------------------------------------------------------------- /src/DropboxApi.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxApi; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, System.SysUtils, clJsonSerializerBase, DropboxApi.Data; 38 | 39 | type 40 | EDropboxException = class(Exception) 41 | strict private 42 | FError: TError; 43 | 44 | procedure SetError(const Value: TError); 45 | function GetErrorSummary: string; 46 | procedure SetErrorSummary(const Value: string); 47 | public 48 | constructor Create; overload; 49 | constructor Create(AError: TError); overload; 50 | destructor Destroy; override; 51 | 52 | [TclJsonString('error_summary')] 53 | property ErrorSummary: string read GetErrorSummary write SetErrorSummary; 54 | 55 | [TclJsonProperty('error')] 56 | property Error: TError read FError write SetError; 57 | end; 58 | 59 | TCredential = class abstract 60 | public 61 | function GetAuthorization: string; virtual; abstract; 62 | function RefreshAuthorization: string; virtual; abstract; 63 | procedure RevokeAuthorization; virtual; abstract; 64 | procedure Abort; virtual; abstract; 65 | end; 66 | 67 | TJsonSerializer = class abstract 68 | public 69 | function JsonToException(const AJson: string): EDropboxException; virtual; abstract; 70 | function ExceptionToJson(E: EDropboxException): string; virtual; abstract; 71 | 72 | function JsonToObject(AType: TClass; const AJson: string): TObject; virtual; abstract; 73 | function ObjectToJson(AObject: TObject): string; virtual; abstract; 74 | end; 75 | 76 | TServiceInitializer = class; 77 | 78 | THttpClient = class abstract 79 | strict private 80 | FInitializer: TServiceInitializer; 81 | strict protected 82 | function GetStatusCode: Integer; virtual; abstract; 83 | public 84 | constructor Create(AInitializer: TServiceInitializer); 85 | 86 | function RpcEndPointRequest(const AUri: string; const ARequest: string): string; virtual; abstract; 87 | function ContentUploadEndPointRequest(const AUri: string; const ARequestHeader: string; ABody: TStream): string; virtual; abstract; 88 | function ContentDownloadEndPointRequest(const AUri: string; const ARequestHeader: string; ABody: TStream): string; virtual; abstract; 89 | procedure Abort; virtual; abstract; 90 | 91 | property Initializer: TServiceInitializer read FInitializer; 92 | property StatusCode: Integer read GetStatusCode; 93 | end; 94 | 95 | TServiceInitializer = class abstract 96 | strict private 97 | FApplicationName: string; 98 | FCredential: TCredential; 99 | strict protected 100 | function GetHttpClient: THttpClient; virtual; abstract; 101 | function GetJsonSerializer: TJsonSerializer; virtual; abstract; 102 | public 103 | constructor Create(ACredential: TCredential; const ApplicationName: string); 104 | destructor Destroy; override; 105 | 106 | property HttpClient: THttpClient read GetHttpClient; 107 | property JsonSerializer: TJsonSerializer read GetJsonSerializer; 108 | property Credential: TCredential read FCredential; 109 | property ApplicationName: string read FApplicationName; 110 | end; 111 | 112 | TService = class 113 | strict private 114 | FInitializer: TServiceInitializer; 115 | public 116 | constructor Create(AInitializer: TServiceInitializer); 117 | destructor Destroy; override; 118 | 119 | procedure Abort; 120 | 121 | property Initializer: TServiceInitializer read FInitializer; 122 | end; 123 | 124 | TServiceRequest = class abstract 125 | strict private 126 | FService: TService; 127 | public 128 | constructor Create(AService: TService); 129 | 130 | function Execute: TResponse; virtual; abstract; 131 | 132 | property Service: TService read FService; 133 | end; 134 | 135 | resourcestring 136 | cUnspecifiedError = 'Unspecified error'; 137 | 138 | implementation 139 | 140 | { EDropboxException } 141 | 142 | constructor EDropboxException.Create; 143 | begin 144 | inherited Create(cUnspecifiedError); 145 | end; 146 | 147 | constructor EDropboxException.Create(AError: TError); 148 | begin 149 | inherited Create(cUnspecifiedError); 150 | SetError(AError); 151 | end; 152 | 153 | destructor EDropboxException.Destroy; 154 | begin 155 | SetError(nil); 156 | inherited Destroy(); 157 | end; 158 | 159 | function EDropboxException.GetErrorSummary: string; 160 | begin 161 | Result := Message; 162 | end; 163 | 164 | procedure EDropboxException.SetError(const Value: TError); 165 | begin 166 | FError.Free(); 167 | FError := Value; 168 | end; 169 | 170 | procedure EDropboxException.SetErrorSummary(const Value: string); 171 | begin 172 | Message := Value; 173 | end; 174 | 175 | { THttpClient } 176 | 177 | constructor THttpClient.Create(AInitializer: TServiceInitializer); 178 | begin 179 | inherited Create(); 180 | FInitializer := AInitializer; 181 | end; 182 | 183 | { TServiceInitializer } 184 | 185 | constructor TServiceInitializer.Create(ACredential: TCredential; const ApplicationName: string); 186 | begin 187 | inherited Create(); 188 | 189 | FCredential := ACredential; 190 | FApplicationName := ApplicationName; 191 | 192 | Assert(FCredential <> nil); 193 | end; 194 | 195 | destructor TServiceInitializer.Destroy; 196 | begin 197 | FCredential.Free(); 198 | inherited Destroy(); 199 | end; 200 | 201 | { TService } 202 | 203 | procedure TService.Abort; 204 | begin 205 | FInitializer.Credential.Abort(); 206 | FInitializer.HttpClient.Abort(); 207 | end; 208 | 209 | constructor TService.Create(AInitializer: TServiceInitializer); 210 | begin 211 | inherited Create(); 212 | FInitializer := AInitializer; 213 | Assert(FInitializer <> nil); 214 | end; 215 | 216 | destructor TService.Destroy; 217 | begin 218 | FInitializer.Free(); 219 | inherited Destroy(); 220 | end; 221 | 222 | { TServiceRequest } 223 | 224 | constructor TServiceRequest.Create(AService: TService); 225 | begin 226 | inherited Create(); 227 | FService := AService; 228 | end; 229 | 230 | end. 231 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /test/DropboxManager.Tests.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxManager.Tests; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, System.SysUtils, TestFramework, DropboxManager, DropboxApi, DropboxApi.Persister, DropboxApi.Data; 38 | 39 | type 40 | TDropboxManagerTests = class(TTestCase) 41 | strict private 42 | procedure AssignCredentials(ADropbox: TDropboxManager); 43 | published 44 | procedure TestSerialization; 45 | procedure TestFolderRoutine; 46 | procedure TestFileRoutine; 47 | procedure TestCopyMove; 48 | procedure TestSaveUrl; 49 | end; 50 | 51 | implementation 52 | 53 | { TDropboxManagerTests } 54 | 55 | procedure TDropboxManagerTests.AssignCredentials(ADropbox: TDropboxManager); 56 | begin 57 | ADropbox.ClientID := 'x0hh3lne06oc1cg'; 58 | ADropbox.ClientSecret := 'xrkh8yumfunrrnl'; 59 | ADropbox.RedirectURL := 'http://localhost:55896'; 60 | end; 61 | 62 | procedure TDropboxManagerTests.TestCopyMove; 63 | var 64 | dropbox: TDropboxManager; 65 | list: TStrings; 66 | begin 67 | dropbox := nil; 68 | list := nil; 69 | try 70 | dropbox := TDropboxManager.Create(); 71 | list := TStringList.Create(); 72 | 73 | AssignCredentials(dropbox); 74 | 75 | try 76 | dropbox.Delete('/TestFolder'); 77 | except 78 | on EDropboxException do; 79 | end; 80 | 81 | try 82 | dropbox.Delete('/TestFolderCopy'); 83 | except 84 | on EDropboxException do; 85 | end; 86 | 87 | try 88 | dropbox.Delete('/TestFolderMove'); 89 | except 90 | on EDropboxException do; 91 | end; 92 | 93 | dropbox.CreateFolder('/TestFolder'); 94 | 95 | dropbox.Copy('/TestFolder', '/TestFolderCopy'); 96 | 97 | dropbox.Move('/TestFolderCopy', '/TestFolderMove'); 98 | 99 | dropbox.Search('', 'TestFolderCopy', False, list); 100 | Assert(0 = list.Count); 101 | 102 | dropbox.Delete('/TestFolder'); 103 | dropbox.Delete('/TestFolderMove'); 104 | finally 105 | list.Free(); 106 | dropbox.Free(); 107 | end; 108 | end; 109 | 110 | procedure TDropboxManagerTests.TestFileRoutine; 111 | var 112 | dropbox: TDropboxManager; 113 | list: TStrings; 114 | stream: TStringStream; 115 | begin 116 | dropbox := nil; 117 | list := nil; 118 | stream := nil; 119 | try 120 | dropbox := TDropboxManager.Create(); 121 | list := TStringList.Create(); 122 | 123 | AssignCredentials(dropbox); 124 | 125 | stream := TStringStream.Create('test content', TEncoding.UTF8); 126 | 127 | try 128 | dropbox.Delete('/testfile.txt'); 129 | except 130 | on EDropboxException do; 131 | end; 132 | 133 | dropbox.Upload(stream, '/testfile.txt'); 134 | 135 | stream.Size := 0; 136 | 137 | dropbox.Download('/testfile.txt', stream); 138 | 139 | Assert('test content' = stream.DataString); 140 | 141 | dropbox.Search('', 'testfile', False, list); 142 | 143 | Assert(1 = list.Count); 144 | Assert('/testfile.txt' = list[0]); 145 | 146 | dropbox.Delete('/testfile.txt'); 147 | 148 | Sleep(2000); 149 | 150 | dropbox.Search('', 'testfile', False, list); 151 | Assert(0 = list.Count); 152 | 153 | dropbox.Search('', 'testfile', True, list); 154 | Assert(1 = list.Count); 155 | Assert(' /testfile.txt' = list[0]); 156 | finally 157 | stream.Free(); 158 | list.Free(); 159 | dropbox.Free(); 160 | end; 161 | end; 162 | 163 | procedure TDropboxManagerTests.TestFolderRoutine; 164 | var 165 | dropbox: TDropboxManager; 166 | list: TStrings; 167 | cnt: Integer; 168 | begin 169 | dropbox := nil; 170 | list := nil; 171 | try 172 | dropbox := TDropboxManager.Create(); 173 | list := TStringList.Create(); 174 | 175 | AssignCredentials(dropbox); 176 | 177 | try 178 | dropbox.Delete('/TestFolder'); 179 | except 180 | on EDropboxException do; 181 | end; 182 | 183 | dropbox.ListFolder('', list); 184 | cnt := list.Count; 185 | 186 | dropbox.CreateFolder('/TestFolder'); 187 | 188 | dropbox.ListFolder('', list); 189 | Assert(cnt + 1 = list.Count); 190 | 191 | dropbox.Delete('/TestFolder'); 192 | finally 193 | list.Free(); 194 | dropbox.Free(); 195 | end; 196 | end; 197 | 198 | procedure TDropboxManagerTests.TestSaveUrl; 199 | var 200 | dropbox: TDropboxManager; 201 | list: TStrings; 202 | cnt: Integer; 203 | id: string; 204 | status: TSaveUrlStatus; 205 | begin 206 | dropbox := nil; 207 | list := nil; 208 | try 209 | dropbox := TDropboxManager.Create(); 210 | list := TStringList.Create(); 211 | 212 | AssignCredentials(dropbox); 213 | 214 | try 215 | dropbox.Delete('/testfile.txt'); 216 | except 217 | on EDropboxException do; 218 | end; 219 | 220 | dropbox.ListFolder('', list); 221 | cnt := list.Count; 222 | 223 | id := dropbox.SaveUrl('/testfile.txt', 'http://www.clevercomponents.com/robots.txt'); 224 | 225 | Assert('' <> id); 226 | 227 | repeat 228 | status := dropbox.SaveUrlCheckStatus(id); 229 | until (status <> usInProgress); 230 | 231 | Assert(usComplete = status); 232 | 233 | dropbox.ListFolder('', list); 234 | Assert(cnt + 1 = list.Count); 235 | 236 | dropbox.Delete('/testfile.txt'); 237 | finally 238 | list.Free(); 239 | dropbox.Free(); 240 | end; 241 | end; 242 | 243 | procedure TDropboxManagerTests.TestSerialization; 244 | const 245 | source = '{"entries": [' 246 | + '{".tag": "file", "name": "Get Started with Dropbox.pdf", "path_lower": "/get started with dropbox.pdf",' 247 | + ' "path_display": "/Get Started with Dropbox.pdf", "id": "id:99W9FmuZVTAAAAAAAAAAAg", "client_modified": "2016-12-20T21:27:34Z",' 248 | + ' "server_modified": "2016-12-20T21:28:34Z", "rev": "1521e41da", "size": 905827}],' 249 | + ' "cursor": "AAHiavvxdBrJsoC9q5E4girQd5LvgbyGhnTR1lYC5mo7OU_Ni0h_thdoLdQocqOK03ZyRPyshA2ifDnjIeyWV_FZ6UwMsh6unZMhoVpDPkCrXp8jYtnGUJ-g9u8LKjhatGA3e9ZAULV4IeFaUOMpLcjD", "has_more": false}'; 250 | 251 | var 252 | json: TDropboxJsonSerializer; 253 | obj: TListFolderResult; 254 | fileEntry: TFileMetadata; 255 | begin 256 | json := nil; 257 | obj := nil; 258 | try 259 | json := TDropboxJsonSerializer.Create(); 260 | obj := json.JsonToObject(TListFolderResult, source) as TListFolderResult; 261 | 262 | Assert(1 = Length(obj.Entries)); 263 | Assert('AAHiavvxdBrJsoC9q5E4girQd5LvgbyGhnTR1lYC5mo7OU_Ni0h_thdoLdQocqOK03ZyRPyshA2ifDnjIeyWV_FZ6UwMsh6unZMhoVpDPkCrXp8jYtnGUJ-g9u8LKjhatGA3e9ZAULV4IeFaUOMpLcjD' = obj.Cursor); 264 | Assert(not obj.HasMore); 265 | 266 | fileEntry := obj.Entries[0] as TFileMetadata; 267 | 268 | Assert('Get Started with Dropbox.pdf' = fileEntry.Name); 269 | Assert('/get started with dropbox.pdf' = fileEntry.PathLower); 270 | Assert('/Get Started with Dropbox.pdf' = fileEntry.PathDisplay); 271 | Assert('id:99W9FmuZVTAAAAAAAAAAAg' = fileEntry.Id); 272 | Assert('2016-12-20T21:27:34Z' = fileEntry.ClientModified); 273 | Assert('2016-12-20T21:28:34Z' = fileEntry.ServerModified); 274 | Assert('1521e41da' = fileEntry.Rev); 275 | Assert(905827 = fileEntry.Size); 276 | finally 277 | obj.Free(); 278 | json.Free(); 279 | end; 280 | end; 281 | 282 | initialization 283 | TestFramework.RegisterTest(TDropboxManagerTests.Suite); 284 | 285 | end. 286 | -------------------------------------------------------------------------------- /src/DropboxApi.Routes.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxApi.Routes; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, System.SysUtils, DropboxApi, DropboxApi.Data, DropboxApi.Requests; 38 | 39 | type 40 | TDropboxRoutes = class 41 | strict private 42 | FService: TService; 43 | public 44 | constructor Create(AService: TService); 45 | 46 | property Service: TService read FService; 47 | end; 48 | 49 | TAuthUserRoutes = class(TDropboxRoutes) 50 | public 51 | procedure TokenRevoke; 52 | end; 53 | 54 | TFilesUserRoutes = class(TDropboxRoutes) 55 | function Copy(ARelocationArg: TRelocationArg): TMetadata; 56 | //copy_batch 57 | //copy_batch/check 58 | //copy_reference/get 59 | //copy_reference/save 60 | function CreateFolder(ACreateFolderArg: TCreateFolderArg): TFolderMetadata; 61 | function Delete(ADeleteArg: TDeleteArg): TMetadata; 62 | //delete_batch 63 | //delete_batch/check 64 | function Download(ADownloadArg: TDownloadArg; ABody: TStream): TFileMetadata; 65 | //get_metadata 66 | //get_preview 67 | //get_temporary_link 68 | //get_thumbnail 69 | function ListFolder(AListFolderArg: TListFolderArg): TListFolderResult; 70 | function ListFolderContinue(AListFolderContinueArg: TListFolderContinueArg): TListFolderResult; 71 | //list_folder/get_latest_cursor 72 | //list_folder/longpoll 73 | //list_revisions 74 | function Move(ARelocationArg: TRelocationArg): TMetadata; 75 | //move_batch 76 | //move_batch/check 77 | //permanently_delete 78 | //restore 79 | function SaveUrl(ASaveUrlArg: TSaveUrlArg): TSaveUrlResult; 80 | function SaveUrlCheckJobStatus(APollArg: TPollArg): TSaveUrlJobStatus; 81 | function Search(ASearchArg: TSearchArg): TSearchResult; 82 | function Upload(ACommitInfo: TCommitInfo; ABody: TStream): TFileMetadata; 83 | //upload_session/append_v2 84 | //upload_session/finish 85 | //upload_session/finish_batch 86 | //upload_session/finish_batch/check 87 | //upload_session/start 88 | end; 89 | 90 | TDropboxClient = class(TService) 91 | strict private 92 | FAuth: TAuthUserRoutes; 93 | FFiles: TFilesUserRoutes; 94 | 95 | function GetAuth: TAuthUserRoutes; 96 | function GetFiles: TFilesUserRoutes; 97 | strict protected 98 | function CreateAuth: TAuthUserRoutes; virtual; 99 | function CreateFiles: TFilesUserRoutes; virtual; 100 | public 101 | constructor Create(AInitializer: TServiceInitializer); 102 | destructor Destroy; override; 103 | 104 | property Auth: TAuthUserRoutes read GetAuth; 105 | property Files: TFilesUserRoutes read GetFiles; 106 | //PaperUserRoutes Paper 107 | //SharingUserRoutes Sharing 108 | //UsersUserRoutes Users 109 | end; 110 | 111 | implementation 112 | 113 | { TDropboxClient } 114 | 115 | constructor TDropboxClient.Create(AInitializer: TServiceInitializer); 116 | begin 117 | inherited Create(AInitializer); 118 | 119 | FAuth := nil; 120 | FFiles := nil; 121 | end; 122 | 123 | function TDropboxClient.CreateAuth: TAuthUserRoutes; 124 | begin 125 | Result := TAuthUserRoutes.Create(Self); 126 | end; 127 | 128 | function TDropboxClient.CreateFiles: TFilesUserRoutes; 129 | begin 130 | Result := TFilesUserRoutes.Create(Self); 131 | end; 132 | 133 | destructor TDropboxClient.Destroy; 134 | begin 135 | FreeAndNil(FAuth); 136 | FreeAndNil(FFiles); 137 | 138 | inherited Destroy(); 139 | end; 140 | 141 | function TDropboxClient.GetAuth: TAuthUserRoutes; 142 | begin 143 | if (FAuth = nil) then 144 | begin 145 | FAuth := CreateAuth(); 146 | end; 147 | Result := FAuth; 148 | end; 149 | 150 | function TDropboxClient.GetFiles: TFilesUserRoutes; 151 | begin 152 | if (FFiles = nil) then 153 | begin 154 | FFiles := CreateFiles(); 155 | end; 156 | Result := FFiles; 157 | end; 158 | 159 | { TDropboxRoutes } 160 | 161 | constructor TDropboxRoutes.Create(AService: TService); 162 | begin 163 | inherited Create(); 164 | FService := AService; 165 | end; 166 | 167 | { TAuthUserRoutes } 168 | 169 | procedure TAuthUserRoutes.TokenRevoke; 170 | begin 171 | Service.Initializer.Credential.RevokeAuthorization(); 172 | end; 173 | 174 | { TFilesUserRoutes } 175 | 176 | function TFilesUserRoutes.Copy(ARelocationArg: TRelocationArg): TMetadata; 177 | var 178 | request: TFilesCopyRequest; 179 | begin 180 | request := TFilesCopyRequest.Create(Service, ARelocationArg); 181 | try 182 | Result := request.Execute(); 183 | finally 184 | request.Free(); 185 | end; 186 | end; 187 | 188 | function TFilesUserRoutes.CreateFolder(ACreateFolderArg: TCreateFolderArg): TFolderMetadata; 189 | var 190 | request: TFilesCreateFolderRequest; 191 | begin 192 | request := TFilesCreateFolderRequest.Create(Service, ACreateFolderArg); 193 | try 194 | Result := request.Execute(); 195 | finally 196 | request.Free(); 197 | end; 198 | end; 199 | 200 | function TFilesUserRoutes.Delete(ADeleteArg: TDeleteArg): TMetadata; 201 | var 202 | request: TFilesDeleteRequest; 203 | begin 204 | request := TFilesDeleteRequest.Create(Service, ADeleteArg); 205 | try 206 | Result := request.Execute(); 207 | finally 208 | request.Free(); 209 | end; 210 | end; 211 | 212 | function TFilesUserRoutes.Download(ADownloadArg: TDownloadArg; ABody: TStream): TFileMetadata; 213 | var 214 | request: TFilesDownloadRequest; 215 | begin 216 | request := TFilesDownloadRequest.Create(Service, ADownloadArg, ABody); 217 | try 218 | Result := request.Execute(); 219 | finally 220 | request.Free(); 221 | end; 222 | end; 223 | 224 | function TFilesUserRoutes.ListFolder(AListFolderArg: TListFolderArg): TListFolderResult; 225 | var 226 | request: TFilesListFolderRequest; 227 | begin 228 | request := TFilesListFolderRequest.Create(Service, AListFolderArg); 229 | try 230 | Result := request.Execute(); 231 | finally 232 | request.Free(); 233 | end; 234 | end; 235 | 236 | function TFilesUserRoutes.ListFolderContinue(AListFolderContinueArg: TListFolderContinueArg): TListFolderResult; 237 | var 238 | request: TFilesListFolderContinueRequest; 239 | begin 240 | request := TFilesListFolderContinueRequest.Create(Service, AListFolderContinueArg); 241 | try 242 | Result := request.Execute(); 243 | finally 244 | request.Free(); 245 | end; 246 | end; 247 | 248 | function TFilesUserRoutes.Move(ARelocationArg: TRelocationArg): TMetadata; 249 | var 250 | request: TFilesMoveRequest; 251 | begin 252 | request := TFilesMoveRequest.Create(Service, ARelocationArg); 253 | try 254 | Result := request.Execute(); 255 | finally 256 | request.Free(); 257 | end; 258 | end; 259 | 260 | function TFilesUserRoutes.SaveUrl(ASaveUrlArg: TSaveUrlArg): TSaveUrlResult; 261 | var 262 | request: TFilesSaveUrlRequest; 263 | begin 264 | request := TFilesSaveUrlRequest.Create(Service, ASaveUrlArg); 265 | try 266 | Result := request.Execute(); 267 | finally 268 | request.Free(); 269 | end; 270 | end; 271 | 272 | function TFilesUserRoutes.SaveUrlCheckJobStatus(APollArg: TPollArg): TSaveUrlJobStatus; 273 | var 274 | request: TFilesSaveUrlCheckJobStatusRequest; 275 | begin 276 | request := TFilesSaveUrlCheckJobStatusRequest.Create(Service, APollArg); 277 | try 278 | Result := request.Execute(); 279 | finally 280 | request.Free(); 281 | end; 282 | end; 283 | 284 | function TFilesUserRoutes.Search(ASearchArg: TSearchArg): TSearchResult; 285 | var 286 | request: TFilesSearchRequest; 287 | begin 288 | request := TFilesSearchRequest.Create(Service, ASearchArg); 289 | try 290 | Result := request.Execute(); 291 | finally 292 | request.Free(); 293 | end; 294 | end; 295 | 296 | function TFilesUserRoutes.Upload(ACommitInfo: TCommitInfo; ABody: TStream): TFileMetadata; 297 | var 298 | request: TFilesUploadRequest; 299 | begin 300 | request := TFilesUploadRequest.Create(Service, ACommitInfo, ABody); 301 | try 302 | Result := request.Execute(); 303 | finally 304 | request.Free(); 305 | end; 306 | end; 307 | 308 | end. 309 | -------------------------------------------------------------------------------- /test/Test.dproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {77B61FFE-DE2E-4DBE-BE40-D39F6E982870} 4 | 14.4 5 | VCL 6 | Test.dpr 7 | True 8 | Debug 9 | Win32 10 | 3 11 | Application 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Base 40 | true 41 | 42 | 43 | $(BDS)\bin\delphi_PROJECTICON.ico 44 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) 45 | .\$(Platform)\$(Config) 46 | .\$(Platform)\$(Config) 47 | false 48 | false 49 | false 50 | false 51 | false 52 | 53 | 54 | 1033 55 | true 56 | bindcompfmx;DBXSqliteDriver;vcldbx;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;bindcomp;inetdb;vclib;inetdbbde;DBXInterBaseDriver;DataSnapCommon;xmlrtl;svnui;ibxpress;DbxCommonDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;vclie;vcltouch;websnap;CustomIPTransport;VclSmp;dsnap;IndyIPServer;fmxase;vcl;IndyCore;clinetsuitedXE3;IndyIPCommon;CloudService;dsnapcon;inet;fmxobj;vclx;clinetsuiteSSHdXE3;inetdbxpress;webdsnap;svn;fmxdae;bdertl;dbexpress;adortl;IndyIPClient;$(DCC_UsePackage) 57 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 58 | $(BDS)\bin\default_app.manifest 59 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 60 | 61 | 62 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 63 | $(BDS)\bin\default_app.manifest 64 | true 65 | 1033 66 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 67 | bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;bindcomp;inetdb;DBXInterBaseDriver;DataSnapCommon;xmlrtl;DbxCommonDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;vclie;vcltouch;websnap;CustomIPTransport;VclSmp;dsnap;IndyIPServer;fmxase;vcl;IndyCore;IndyIPCommon;dsnapcon;inet;fmxobj;vclx;inetdbxpress;webdsnap;fmxdae;dbexpress;IndyIPClient;$(DCC_UsePackage) 68 | 69 | 70 | DEBUG;$(DCC_Define) 71 | true 72 | false 73 | true 74 | true 75 | true 76 | 77 | 78 | 1033 79 | false 80 | true 81 | false 82 | 83 | 84 | false 85 | RELEASE;$(DCC_Define) 86 | 0 87 | false 88 | 89 | 90 | 91 | MainSource 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Cfg_2 105 | Base 106 | 107 | 108 | Base 109 | 110 | 111 | Cfg_1 112 | Base 113 | 114 | 115 | 116 | Delphi.Personality.12 117 | 118 | 119 | 120 | 121 | False 122 | False 123 | 1 124 | 0 125 | 0 126 | 0 127 | False 128 | False 129 | False 130 | False 131 | False 132 | 1049 133 | 1251 134 | 135 | 136 | 137 | 138 | 1.0.0.0 139 | 140 | 141 | 142 | 143 | 144 | 1.0.0.0 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | Test.dpr 157 | 158 | 159 | 160 | 161 | True 162 | True 163 | 164 | 165 | 12 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /src/DropboxApi.Persister.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxApi.Persister; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, System.SysUtils, DropboxApi, clOAuth, clUriUtils, clHttp, clHttpRequest, clHeaderFieldList, 38 | clJsonSerializer; 39 | 40 | type 41 | TDropboxOAuthCredential = class(TCredential) 42 | strict private 43 | FClientID: string; 44 | FClientSecret: string; 45 | FRedirectURL: string; 46 | FOAuth: TclOAuth; 47 | public 48 | constructor Create; 49 | destructor Destroy; override; 50 | 51 | function GetAuthorization: string; override; 52 | function RefreshAuthorization: string; override; 53 | procedure RevokeAuthorization; override; 54 | procedure Abort; override; 55 | 56 | property ClientID: string read FClientID write FClientID; 57 | property ClientSecret: string read FClientSecret write FClientSecret; 58 | property RedirectURL: string read FRedirectURL write FRedirectURL; 59 | end; 60 | 61 | TDropboxHttpClient = class(THttpClient) 62 | strict private 63 | FHttp: TclHttp; 64 | 65 | procedure CheckResponse(const AJsonResponse: string); 66 | protected 67 | function GetStatusCode: Integer; override; 68 | public 69 | constructor Create(AInitializer: TServiceInitializer); 70 | destructor Destroy; override; 71 | 72 | function RpcEndPointRequest(const AUri: string; const ARequest: string): string; override; 73 | function ContentUploadEndPointRequest(const AUri: string; const ARequestHeader: string; ABody: TStream): string; override; 74 | function ContentDownloadEndPointRequest(const AUri: string; const ARequestHeader: string; ABody: TStream): string; override; 75 | procedure Abort; override; 76 | end; 77 | 78 | TDropboxJsonSerializer = class(TJsonSerializer) 79 | strict private 80 | FSerializer: clJsonSerializer.TclJsonSerializer; 81 | public 82 | constructor Create; 83 | destructor Destroy; override; 84 | 85 | function JsonToException(const AJson: string): EDropboxException; override; 86 | function ExceptionToJson(E: EDropboxException): string; override; 87 | 88 | function JsonToObject(AType: TClass; const AJson: string): TObject; override; 89 | function ObjectToJson(AObject: TObject): string; override; 90 | end; 91 | 92 | TDropboxServiceInitializer = class(TServiceInitializer) 93 | strict private 94 | FHttpClient: THttpClient; 95 | FJsonSerializer: TJsonSerializer; 96 | strict protected 97 | function GetHttpClient: THttpClient; override; 98 | function GetJsonSerializer: TJsonSerializer; override; 99 | public 100 | constructor Create(ACredential: TCredential; const ApplicationName: string); 101 | destructor Destroy; override; 102 | end; 103 | 104 | implementation 105 | 106 | { TDropboxOAuthCredential } 107 | 108 | procedure TDropboxOAuthCredential.Abort; 109 | begin 110 | FOAuth.Close(); 111 | end; 112 | 113 | constructor TDropboxOAuthCredential.Create; 114 | begin 115 | inherited Create(); 116 | FOAuth := TclOAuth.Create(nil); 117 | end; 118 | 119 | destructor TDropboxOAuthCredential.Destroy; 120 | begin 121 | FOAuth.Free(); 122 | inherited Destroy(); 123 | end; 124 | 125 | function TDropboxOAuthCredential.GetAuthorization: string; 126 | var 127 | uri: TclUrlParser; 128 | begin 129 | FOAuth.AuthURL := 'https://www.dropbox.com/oauth2/authorize'; 130 | FOAuth.TokenURL := 'https://api.dropbox.com/oauth2/token'; 131 | 132 | FOAuth.ClientID := ClientID; 133 | FOAuth.ClientSecret := ClientSecret; 134 | FOAuth.RedirectURL := RedirectURL; 135 | 136 | uri := TclUrlParser.Create(); 137 | try 138 | uri.Parse(FOAuth.RedirectURL); 139 | FOAuth.LocalWebServerPort := uri.Port; 140 | finally 141 | uri.Free(); 142 | end; 143 | 144 | Result := FOAuth.GetAuthorization(); 145 | end; 146 | 147 | function TDropboxOAuthCredential.RefreshAuthorization: string; 148 | begin 149 | Result := FOAuth.RefreshAuthorization(); 150 | end; 151 | 152 | procedure TDropboxOAuthCredential.RevokeAuthorization; 153 | begin 154 | FOAuth.Close(); 155 | end; 156 | 157 | { TDropboxHttpClient } 158 | 159 | procedure TDropboxHttpClient.Abort; 160 | begin 161 | FHttp.Close(); 162 | end; 163 | 164 | procedure TDropboxHttpClient.CheckResponse(const AJsonResponse: string); 165 | begin 166 | if (FHttp.StatusCode >= 300) then 167 | begin 168 | if (FHttp.ResponseHeader.ContentType.ToLower().IndexOf('json') > -1) then 169 | begin 170 | raise Initializer.JsonSerializer.JsonToException(AJsonResponse); 171 | end else 172 | begin 173 | raise EclHttpError.Create(FHttp.StatusText, FHttp.StatusCode, AJsonResponse); 174 | end; 175 | end; 176 | end; 177 | 178 | constructor TDropboxHttpClient.Create(AInitializer: TServiceInitializer); 179 | begin 180 | inherited Create(AInitializer); 181 | 182 | FHttp := TclHttp.Create(nil); 183 | FHttp.UserAgent := Initializer.ApplicationName; 184 | FHttp.SilentHTTP := True; 185 | end; 186 | 187 | destructor TDropboxHttpClient.Destroy; 188 | begin 189 | FHttp.Free(); 190 | inherited Destroy(); 191 | end; 192 | 193 | function TDropboxHttpClient.GetStatusCode: Integer; 194 | begin 195 | Result := FHttp.StatusCode; 196 | end; 197 | 198 | function TDropboxHttpClient.RpcEndPointRequest(const AUri, ARequest: string): string; 199 | var 200 | req: TclHttpRequest; 201 | resp: TStringStream; 202 | begin 203 | req := nil; 204 | resp := nil; 205 | try 206 | req := TclHttpRequest.Create(nil); 207 | 208 | if (ARequest <> '') then 209 | begin 210 | req.BuildJSONRequest(ARequest); 211 | end; 212 | 213 | resp := TStringStream.Create('', TEncoding.UTF8); 214 | 215 | FHttp.Authorization := Initializer.Credential.GetAuthorization(); 216 | 217 | FHttp.Post(AUri, req, resp); 218 | 219 | CheckResponse(resp.DataString); 220 | 221 | Result := resp.DataString; 222 | finally 223 | resp.Free(); 224 | req.Free(); 225 | end; 226 | end; 227 | 228 | function TDropboxHttpClient.ContentDownloadEndPointRequest(const AUri, ARequestHeader: string; ABody: TStream): string; 229 | var 230 | req: TclHttpRequest; 231 | fieldList: TclHeaderFieldList; 232 | begin 233 | req := nil; 234 | fieldList := nil; 235 | try 236 | req := TclHttpRequest.Create(nil); 237 | 238 | req.Header.ExtraFields.Add('Dropbox-API-Arg: ' + ARequestHeader); 239 | 240 | FHttp.Authorization := Initializer.Credential.GetAuthorization(); 241 | 242 | FHttp.SendRequest('POST', AUri, req.HeaderSource, nil, nil, ABody); 243 | 244 | fieldList := TclHeaderFieldList.Create(); 245 | 246 | fieldList.Parse(0, FHttp.ResponseHeader.ExtraFields); 247 | 248 | Result := fieldList.GetFieldValue('Dropbox-API-Result'); 249 | 250 | CheckResponse(Result); 251 | finally 252 | fieldList.Free(); 253 | req.Free(); 254 | end; 255 | end; 256 | 257 | function TDropboxHttpClient.ContentUploadEndPointRequest(const AUri, ARequestHeader: string; ABody: TStream): string; 258 | var 259 | req: TclHttpRequest; 260 | resp: TStringStream; 261 | begin 262 | req := nil; 263 | resp := nil; 264 | try 265 | req := TclHttpRequest.Create(nil); 266 | 267 | req.Header.ContentType := 'application/octet-stream'; 268 | req.Header.ExtraFields.Add('Dropbox-API-Arg: ' + ARequestHeader); 269 | 270 | resp := TStringStream.Create('', TEncoding.UTF8); 271 | 272 | FHttp.Authorization := Initializer.Credential.GetAuthorization(); 273 | 274 | FHttp.SendRequest('POST', AUri, req.HeaderSource, ABody, nil, resp); 275 | 276 | CheckResponse(resp.DataString); 277 | 278 | Result := resp.DataString; 279 | finally 280 | resp.Free(); 281 | req.Free(); 282 | end; 283 | end; 284 | 285 | { TDropboxJsonSerializer } 286 | 287 | constructor TDropboxJsonSerializer.Create; 288 | begin 289 | inherited Create(); 290 | FSerializer := clJsonSerializer.TclJsonSerializer.Create(); 291 | end; 292 | 293 | destructor TDropboxJsonSerializer.Destroy; 294 | begin 295 | FSerializer.Free(); 296 | inherited Destroy(); 297 | end; 298 | 299 | function TDropboxJsonSerializer.ExceptionToJson(E: EDropboxException): string; 300 | begin 301 | Result := FSerializer.ObjectToJson(E); 302 | end; 303 | 304 | function TDropboxJsonSerializer.JsonToException(const AJson: string): EDropboxException; 305 | begin 306 | Result := EDropboxException.Create(); 307 | try 308 | Result := FSerializer.JsonToObject(Result, AJson) as EDropboxException; 309 | except 310 | Result.Free(); 311 | raise; 312 | end; 313 | end; 314 | 315 | function TDropboxJsonSerializer.JsonToObject(AType: TClass; const AJson: string): TObject; 316 | begin 317 | Result := FSerializer.JsonToObject(AType, AJson); 318 | end; 319 | 320 | function TDropboxJsonSerializer.ObjectToJson(AObject: TObject): string; 321 | begin 322 | Result := FSerializer.ObjectToJson(AObject); 323 | end; 324 | 325 | { TDropboxServiceInitializer } 326 | 327 | constructor TDropboxServiceInitializer.Create(ACredential: TCredential; const ApplicationName: string); 328 | begin 329 | inherited Create(ACredential, ApplicationName); 330 | 331 | FHttpClient := nil; 332 | FJsonSerializer := nil; 333 | end; 334 | 335 | destructor TDropboxServiceInitializer.Destroy; 336 | begin 337 | FHttpClient.Free(); 338 | FJsonSerializer.Free(); 339 | 340 | inherited Destroy(); 341 | end; 342 | 343 | function TDropboxServiceInitializer.GetHttpClient: THttpClient; 344 | begin 345 | if (FHttpClient = nil) then 346 | begin 347 | FHttpClient := TDropboxHttpClient.Create(Self); 348 | end; 349 | Result := FHttpClient; 350 | end; 351 | 352 | function TDropboxServiceInitializer.GetJsonSerializer: TJsonSerializer; 353 | begin 354 | if (FJsonSerializer = nil) then 355 | begin 356 | FJsonSerializer := TDropboxJsonSerializer.Create(); 357 | end; 358 | Result := FJsonSerializer; 359 | end; 360 | 361 | end. 362 | -------------------------------------------------------------------------------- /src/DropboxManager.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxManager; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, System.SysUtils, DropboxApi, DropboxApi.Data, DropboxApi.Routes, DropboxApi.Persister; 38 | 39 | type 40 | TSaveUrlStatus = (usInProgress, usComplete, usFailed); 41 | 42 | TDropboxManager = class 43 | strict private 44 | FClientID: string; 45 | FClientSecret: string; 46 | FRedirectURL: string; 47 | FClient: TDropboxClient; 48 | 49 | function GetClient: TDropboxClient; 50 | procedure CollectFolderList(AListFolderResult: TListFolderResult; AList: TStrings); 51 | procedure CollectSearchList(ASearchResult: TSearchResult; AList: TStrings); 52 | public 53 | constructor Create; 54 | destructor Destroy; override; 55 | 56 | procedure CreateFolder(const APath: string); 57 | procedure ListFolder(const APath: string; AList: TStrings); 58 | procedure Delete(const APath: string); 59 | procedure Search(const APath, AQuery: string; ASearchDeleted: Boolean; AList: TStrings); 60 | 61 | procedure Copy(const AFromPath, AToPath: string); 62 | procedure Move(const AFromPath, AToPath: string); 63 | 64 | procedure Download(const ASourceFile: string; ADestination: TStream); 65 | procedure Upload(ASource: TStream; const ADestinationFile: string); 66 | function SaveUrl(const APath, AUrl: string): string; 67 | function SaveUrlCheckStatus(const AsyncJobId: string): TSaveUrlStatus; 68 | 69 | procedure Close; 70 | 71 | property ClientID: string read FClientID write FClientID; 72 | property ClientSecret: string read FClientSecret write FClientSecret; 73 | property RedirectURL: string read FRedirectURL write FRedirectURL; 74 | end; 75 | 76 | implementation 77 | 78 | { TDropboxManager } 79 | 80 | function TDropboxManager.SaveUrlCheckStatus(const AsyncJobId: string): TSaveUrlStatus; 81 | var 82 | args: TPollArg; 83 | res: TSaveUrlJobStatus; 84 | begin 85 | args := nil; 86 | res := nil; 87 | try 88 | args := TPollArg.Create(); 89 | args.AsyncJobId := AsyncJobId; 90 | 91 | res := GetClient().Files.SaveUrlCheckJobStatus(args); 92 | 93 | if (res is TSaveUrlJobStatusInProgress) then 94 | begin 95 | Result := usInProgress; 96 | end else 97 | if (res is TSaveUrlJobStatusComplete) then 98 | begin 99 | Result := usComplete; 100 | end else 101 | begin 102 | Result := usFailed; 103 | end; 104 | finally 105 | res.Free(); 106 | args.Free(); 107 | end; 108 | end; 109 | 110 | procedure TDropboxManager.Close; 111 | begin 112 | if (FClient <> nil) then 113 | begin 114 | FClient.Abort(); 115 | end; 116 | end; 117 | 118 | constructor TDropboxManager.Create; 119 | begin 120 | inherited Create(); 121 | FClient := nil; 122 | end; 123 | 124 | procedure TDropboxManager.CreateFolder(const APath: string); 125 | var 126 | args: TCreateFolderArg; 127 | res: TFolderMetadata; 128 | begin 129 | args := nil; 130 | res := nil; 131 | try 132 | args := TCreateFolderArg.Create(); 133 | args.Path := APath; 134 | 135 | res := GetClient().Files.CreateFolder(args); 136 | 137 | finally 138 | res.Free(); 139 | args.Free(); 140 | end; 141 | end; 142 | 143 | procedure TDropboxManager.Delete(const APath: string); 144 | var 145 | args: TDeleteArg; 146 | res: TMetadata; 147 | begin 148 | args := nil; 149 | res := nil; 150 | try 151 | args := TDeleteArg.Create(); 152 | args.Path := APath; 153 | 154 | res := GetClient().Files.Delete(args); 155 | 156 | finally 157 | res.Free(); 158 | args.Free(); 159 | end; 160 | end; 161 | 162 | destructor TDropboxManager.Destroy; 163 | begin 164 | Close(); 165 | FClient.Free(); 166 | 167 | inherited Destroy(); 168 | end; 169 | 170 | procedure TDropboxManager.Download(const ASourceFile: string; ADestination: TStream); 171 | var 172 | args: TDownloadArg; 173 | res: TFileMetadata; 174 | begin 175 | args := nil; 176 | res := nil; 177 | try 178 | args := TDownloadArg.Create(); 179 | args.Path := ASourceFile; 180 | 181 | res := GetClient().Files.Download(args, ADestination); 182 | 183 | finally 184 | res.Free(); 185 | args.Free(); 186 | end; 187 | end; 188 | 189 | function TDropboxManager.GetClient: TDropboxClient; 190 | var 191 | credential: TDropboxOAuthCredential; 192 | initializer: TServiceInitializer; 193 | begin 194 | if (FClient = nil) then 195 | begin 196 | credential := TDropboxOAuthCredential.Create(); 197 | initializer := TDropboxServiceInitializer.Create(credential, 'Clever Disk Manager'); 198 | FClient := TDropboxClient.Create(initializer); 199 | 200 | credential.ClientID := ClientID; 201 | credential.ClientSecret := ClientSecret; 202 | credential.RedirectURL := RedirectURL; 203 | end; 204 | Result := FClient; 205 | end; 206 | 207 | procedure TDropboxManager.CollectFolderList(AListFolderResult: TListFolderResult; AList: TStrings); 208 | var 209 | entry: TMetaData; 210 | begin 211 | for entry in AListFolderResult.Entries do 212 | begin 213 | if (entry is TFileMetadata) then 214 | begin 215 | AList.Add((entry as TFileMetadata).PathDisplay); 216 | end else 217 | if (entry is TFolderMetadata) then 218 | begin 219 | AList.Add(' ' + (entry as TFolderMetadata).PathDisplay); 220 | end else 221 | if (entry is TDeletedMetadata) then 222 | begin 223 | AList.Add(' ' + (entry as TDeletedMetadata).PathDisplay); 224 | end else 225 | begin 226 | AList.Add(' ' + entry.Tag); 227 | end; 228 | end; 229 | end; 230 | 231 | procedure TDropboxManager.ListFolder(const APath: string; AList: TStrings); 232 | var 233 | args: TListFolderArg; 234 | continueArgs: TListFolderContinueArg; 235 | res: TListFolderResult; 236 | begin 237 | AList.BeginUpdate(); 238 | args := nil; 239 | continueArgs := nil; 240 | res := nil; 241 | try 242 | AList.Clear(); 243 | 244 | args := TListFolderArg.Create(); 245 | args.Path := APath; 246 | 247 | continueArgs := TListFolderContinueArg.Create(); 248 | 249 | res := GetClient().Files.ListFolder(args); 250 | CollectFolderList(res, AList); 251 | 252 | while (res.HasMore) do 253 | begin 254 | continueArgs.Cursor := res.Cursor; 255 | 256 | FreeAndNil(res); 257 | res := GetClient().Files.ListFolderContinue(continueArgs); 258 | CollectFolderList(res, AList); 259 | end; 260 | finally 261 | res.Free(); 262 | continueArgs.Free(); 263 | args.Free(); 264 | AList.EndUpdate(); 265 | end; 266 | end; 267 | 268 | procedure TDropboxManager.Move(const AFromPath, AToPath: string); 269 | var 270 | args: TRelocationArg; 271 | res: TMetadata; 272 | begin 273 | args := nil; 274 | res := nil; 275 | try 276 | args := TRelocationArg.Create(); 277 | args.FromPath := AFromPath; 278 | args.ToPath := AToPath; 279 | args.AllowSharedFolder := True; 280 | 281 | res := GetClient().Files.Move(args); 282 | 283 | finally 284 | res.Free(); 285 | args.Free(); 286 | end; 287 | end; 288 | 289 | procedure TDropboxManager.CollectSearchList(ASearchResult: TSearchResult; AList: TStrings); 290 | var 291 | match: TSearchMatch; 292 | begin 293 | for match in ASearchResult.Matches do 294 | begin 295 | if (match.Metadata is TFileMetadata) then 296 | begin 297 | AList.Add((match.Metadata as TFileMetadata).PathDisplay); 298 | end else 299 | if (match.Metadata is TFolderMetadata) then 300 | begin 301 | AList.Add(' ' + (match.Metadata as TFolderMetadata).PathDisplay); 302 | end else 303 | if (match.Metadata is TDeletedMetadata) then 304 | begin 305 | AList.Add(' ' + (match.Metadata as TDeletedMetadata).PathDisplay); 306 | end else 307 | begin 308 | AList.Add(' ' + match.Metadata.Tag); 309 | end; 310 | end; 311 | end; 312 | 313 | procedure TDropboxManager.Copy(const AFromPath, AToPath: string); 314 | var 315 | args: TRelocationArg; 316 | res: TMetadata; 317 | begin 318 | args := nil; 319 | res := nil; 320 | try 321 | args := TRelocationArg.Create(); 322 | args.FromPath := AFromPath; 323 | args.ToPath := AToPath; 324 | 325 | res := GetClient().Files.Copy(args); 326 | 327 | finally 328 | res.Free(); 329 | args.Free(); 330 | end; 331 | end; 332 | 333 | function TDropboxManager.SaveUrl(const APath, AUrl: string): string; 334 | var 335 | args: TSaveUrlArg; 336 | res: TSaveUrlResult; 337 | begin 338 | args := nil; 339 | res := nil; 340 | try 341 | args := TSaveUrlArg.Create(); 342 | args.Path := APath; 343 | args.Url := AUrl; 344 | 345 | res := GetClient().Files.SaveUrl(args); 346 | 347 | if (res is TSaveUrlResultAsyncJobId) then 348 | begin 349 | Result := (res as TSaveUrlResultAsyncJobId).AsyncJobId; 350 | end else 351 | begin 352 | Result := ''; 353 | end; 354 | finally 355 | res.Free(); 356 | args.Free(); 357 | end; 358 | end; 359 | 360 | procedure TDropboxManager.Search(const APath, AQuery: string; ASearchDeleted: Boolean; AList: TStrings); 361 | var 362 | args: TSearchArg; 363 | res: TSearchResult; 364 | begin 365 | AList.BeginUpdate(); 366 | args := nil; 367 | res := nil; 368 | try 369 | AList.Clear(); 370 | 371 | args := TSearchArg.Create(); 372 | args.Path := APath; 373 | args.Query := AQuery; 374 | 375 | if ASearchDeleted then 376 | begin 377 | args.Mode := TDeletedFilenameSearchMode.Create(); 378 | end; 379 | 380 | res := GetClient().Files.Search(args); 381 | CollectSearchList(res, AList); 382 | 383 | while (res.More) do 384 | begin 385 | args.Start := res.Start; 386 | 387 | FreeAndNil(res); 388 | res := GetClient().Files.Search(args); 389 | CollectSearchList(res, AList); 390 | end; 391 | 392 | finally 393 | res.Free(); 394 | args.Free(); 395 | AList.EndUpdate(); 396 | end; 397 | end; 398 | 399 | procedure TDropboxManager.Upload(ASource: TStream; const ADestinationFile: string); 400 | var 401 | args: TCommitInfo; 402 | res: TFileMetadata; 403 | begin 404 | args := nil; 405 | res := nil; 406 | try 407 | args := TCommitInfo.Create(); 408 | args.Path := ADestinationFile; 409 | 410 | res := GetClient().Files.Upload(args, ASource); 411 | 412 | finally 413 | res.Free(); 414 | args.Free(); 415 | end; 416 | end; 417 | 418 | end. 419 | -------------------------------------------------------------------------------- /src/DropboxApi.Requests.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxApi.Requests; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, DropboxApi, DropboxApi.Data; 38 | 39 | type 40 | TFilesCreateFolderRequest = class(TServiceRequest) 41 | strict private 42 | FCreateFolderArg: TCreateFolderArg; 43 | public 44 | constructor Create(AService: TService; ACreateFolderArg: TCreateFolderArg); 45 | 46 | function Execute: TFolderMetadata; override; 47 | end; 48 | 49 | TFilesDeleteRequest = class(TServiceRequest) 50 | strict private 51 | FDeleteArg: TDeleteArg; 52 | public 53 | constructor Create(AService: TService; ADeleteArg: TDeleteArg); 54 | 55 | function Execute: TMetadata; override; 56 | end; 57 | 58 | TFilesListFolderRequest = class(TServiceRequest) 59 | strict private 60 | FListFolderArg: TListFolderArg; 61 | public 62 | constructor Create(AService: TService; AListFolderArg: TListFolderArg); 63 | 64 | function Execute: TListFolderResult; override; 65 | end; 66 | 67 | TFilesListFolderContinueRequest = class(TServiceRequest) 68 | strict private 69 | FListFolderContinueArg: TListFolderContinueArg; 70 | public 71 | constructor Create(AService: TService; AListFolderContinueArg: TListFolderContinueArg); 72 | 73 | function Execute: TListFolderResult; override; 74 | end; 75 | 76 | TFilesUploadRequest = class(TServiceRequest) 77 | strict private 78 | FCommitInfo: TCommitInfo; 79 | FBody: TStream; 80 | public 81 | constructor Create(AService: TService; ACommitInfo: TCommitInfo; ABody: TStream); 82 | 83 | function Execute: TFileMetadata; override; 84 | end; 85 | 86 | TFilesDownloadRequest = class(TServiceRequest) 87 | strict private 88 | FDownloadArg: TDownloadArg; 89 | FBody: TStream; 90 | public 91 | constructor Create(AService: TService; ADownloadArg: TDownloadArg; ABody: TStream); 92 | 93 | function Execute: TFileMetadata; override; 94 | end; 95 | 96 | TFilesSearchRequest = class(TServiceRequest) 97 | strict private 98 | FSearchArg: TSearchArg; 99 | public 100 | constructor Create(AService: TService; ASearchArg: TSearchArg); 101 | 102 | function Execute: TSearchResult; override; 103 | end; 104 | 105 | TFilesCopyRequest = class(TServiceRequest) 106 | strict private 107 | FRelocationArg: TRelocationArg; 108 | public 109 | constructor Create(AService: TService; ARelocationArg: TRelocationArg); 110 | 111 | function Execute: TMetadata; override; 112 | end; 113 | 114 | TFilesMoveRequest = class(TServiceRequest) 115 | strict private 116 | FRelocationArg: TRelocationArg; 117 | public 118 | constructor Create(AService: TService; ARelocationArg: TRelocationArg); 119 | 120 | function Execute: TMetadata; override; 121 | end; 122 | 123 | TFilesSaveUrlRequest = class(TServiceRequest) 124 | strict private 125 | FSaveUrlArg: TSaveUrlArg; 126 | public 127 | constructor Create(AService: TService; ASaveUrlArg: TSaveUrlArg); 128 | 129 | function Execute: TSaveUrlResult; override; 130 | end; 131 | 132 | TFilesSaveUrlCheckJobStatusRequest = class(TServiceRequest) 133 | strict private 134 | FPollArg: TPollArg; 135 | public 136 | constructor Create(AService: TService; APollArg: TPollArg); 137 | 138 | function Execute: TSaveUrlJobStatus; override; 139 | end; 140 | 141 | implementation 142 | 143 | { TFilesListFolderRequest } 144 | 145 | constructor TFilesListFolderRequest.Create(AService: TService; AListFolderArg: TListFolderArg); 146 | begin 147 | inherited Create(AService); 148 | FListFolderArg := AListFolderArg; 149 | end; 150 | 151 | function TFilesListFolderRequest.Execute: TListFolderResult; 152 | var 153 | request, response: string; 154 | begin 155 | request := Service.Initializer.JsonSerializer.ObjectToJson(FListFolderArg); 156 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/list_folder', request); 157 | Result := Service.Initializer.JsonSerializer.JsonToObject(TListFolderResult, response) as TListFolderResult; 158 | end; 159 | 160 | { TFilesCreateFolderRequest } 161 | 162 | constructor TFilesCreateFolderRequest.Create(AService: TService; ACreateFolderArg: TCreateFolderArg); 163 | begin 164 | inherited Create(AService); 165 | FCreateFolderArg := ACreateFolderArg; 166 | end; 167 | 168 | function TFilesCreateFolderRequest.Execute: TFolderMetadata; 169 | var 170 | request, response: string; 171 | begin 172 | request := Service.Initializer.JsonSerializer.ObjectToJson(FCreateFolderArg); 173 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/create_folder', request); 174 | Result := Service.Initializer.JsonSerializer.JsonToObject(TFolderMetadata, response) as TFolderMetadata; 175 | end; 176 | 177 | { TFilesDeleteRequest } 178 | 179 | constructor TFilesDeleteRequest.Create(AService: TService; ADeleteArg: TDeleteArg); 180 | begin 181 | inherited Create(AService); 182 | FDeleteArg := ADeleteArg; 183 | end; 184 | 185 | function TFilesDeleteRequest.Execute: TMetadata; 186 | var 187 | request, response: string; 188 | begin 189 | request := Service.Initializer.JsonSerializer.ObjectToJson(FDeleteArg); 190 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/delete', request); 191 | Result := Service.Initializer.JsonSerializer.JsonToObject(TMetadata, response) as TMetadata; 192 | end; 193 | 194 | { TFilesListFolderContinueRequest } 195 | 196 | constructor TFilesListFolderContinueRequest.Create(AService: TService; AListFolderContinueArg: TListFolderContinueArg); 197 | begin 198 | inherited Create(AService); 199 | FListFolderContinueArg := AListFolderContinueArg; 200 | end; 201 | 202 | function TFilesListFolderContinueRequest.Execute: TListFolderResult; 203 | var 204 | request, response: string; 205 | begin 206 | request := Service.Initializer.JsonSerializer.ObjectToJson(FListFolderContinueArg); 207 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/list_folder/continue', request); 208 | Result := Service.Initializer.JsonSerializer.JsonToObject(TListFolderResult, response) as TListFolderResult; 209 | end; 210 | 211 | { TFilesUploadRequest } 212 | 213 | constructor TFilesUploadRequest.Create(AService: TService; ACommitInfo: TCommitInfo; ABody: TStream); 214 | begin 215 | inherited Create(AService); 216 | 217 | FCommitInfo := ACommitInfo; 218 | FBody := ABody; 219 | end; 220 | 221 | function TFilesUploadRequest.Execute: TFileMetadata; 222 | var 223 | request, response: string; 224 | begin 225 | request := Service.Initializer.JsonSerializer.ObjectToJson(FCommitInfo); 226 | response := Service.Initializer.HttpClient.ContentUploadEndPointRequest('https://content.dropboxapi.com/2/files/upload', request, FBody); 227 | Result := Service.Initializer.JsonSerializer.JsonToObject(TFileMetadata, response) as TFileMetadata; 228 | end; 229 | 230 | { TFilesDownloadRequest } 231 | 232 | constructor TFilesDownloadRequest.Create(AService: TService; ADownloadArg: TDownloadArg; ABody: TStream); 233 | begin 234 | inherited Create(AService); 235 | 236 | FDownloadArg := ADownloadArg; 237 | FBody := ABody; 238 | end; 239 | 240 | function TFilesDownloadRequest.Execute: TFileMetadata; 241 | var 242 | request, response: string; 243 | begin 244 | request := Service.Initializer.JsonSerializer.ObjectToJson(FDownloadArg); 245 | response := Service.Initializer.HttpClient.ContentDownloadEndPointRequest('https://content.dropboxapi.com/2/files/download', request, FBody); 246 | Result := Service.Initializer.JsonSerializer.JsonToObject(TFileMetadata, response) as TFileMetadata; 247 | end; 248 | 249 | { TFilesSearchRequest } 250 | 251 | constructor TFilesSearchRequest.Create(AService: TService; ASearchArg: TSearchArg); 252 | begin 253 | inherited Create(AService); 254 | FSearchArg := ASearchArg; 255 | end; 256 | 257 | function TFilesSearchRequest.Execute: TSearchResult; 258 | var 259 | request, response: string; 260 | begin 261 | request := Service.Initializer.JsonSerializer.ObjectToJson(FSearchArg); 262 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/search', request); 263 | Result := Service.Initializer.JsonSerializer.JsonToObject(TSearchResult, response) as TSearchResult; 264 | end; 265 | 266 | { TFilesCopyRequest } 267 | 268 | constructor TFilesCopyRequest.Create(AService: TService; ARelocationArg: TRelocationArg); 269 | begin 270 | inherited Create(AService); 271 | FRelocationArg := ARelocationArg; 272 | end; 273 | 274 | function TFilesCopyRequest.Execute: TMetadata; 275 | var 276 | request, response: string; 277 | begin 278 | request := Service.Initializer.JsonSerializer.ObjectToJson(FRelocationArg); 279 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/copy', request); 280 | Result := Service.Initializer.JsonSerializer.JsonToObject(TMetadata, response) as TMetadata; 281 | end; 282 | 283 | { TFilesMoveRequest } 284 | 285 | constructor TFilesMoveRequest.Create(AService: TService; ARelocationArg: TRelocationArg); 286 | begin 287 | inherited Create(AService); 288 | FRelocationArg := ARelocationArg; 289 | end; 290 | 291 | function TFilesMoveRequest.Execute: TMetadata; 292 | var 293 | request, response: string; 294 | begin 295 | FRelocationArg.AllowSharedFolder := True; 296 | 297 | request := Service.Initializer.JsonSerializer.ObjectToJson(FRelocationArg); 298 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/move', request); 299 | Result := Service.Initializer.JsonSerializer.JsonToObject(TMetadata, response) as TMetadata; 300 | end; 301 | 302 | { TFilesSaveUrlRequest } 303 | 304 | constructor TFilesSaveUrlRequest.Create(AService: TService; ASaveUrlArg: TSaveUrlArg); 305 | begin 306 | inherited Create(AService); 307 | FSaveUrlArg := ASaveUrlArg; 308 | end; 309 | 310 | function TFilesSaveUrlRequest.Execute: TSaveUrlResult; 311 | var 312 | request, response: string; 313 | begin 314 | request := Service.Initializer.JsonSerializer.ObjectToJson(FSaveUrlArg); 315 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/save_url', request); 316 | Result := Service.Initializer.JsonSerializer.JsonToObject(TSaveUrlResult, response) as TSaveUrlResult; 317 | end; 318 | 319 | { TFilesSaveUrlCheckJobStatusRequest } 320 | 321 | constructor TFilesSaveUrlCheckJobStatusRequest.Create(AService: TService; APollArg: TPollArg); 322 | begin 323 | inherited Create(AService); 324 | FPollArg := APollArg; 325 | end; 326 | 327 | function TFilesSaveUrlCheckJobStatusRequest.Execute: TSaveUrlJobStatus; 328 | var 329 | request, response: string; 330 | begin 331 | request := Service.Initializer.JsonSerializer.ObjectToJson(FPollArg); 332 | response := Service.Initializer.HttpClient.RpcEndPointRequest('https://api.dropboxapi.com/2/files/save_url/check_job_status', request); 333 | Result := Service.Initializer.JsonSerializer.JsonToObject(TSaveUrlJobStatus, response) as TSaveUrlJobStatus; 334 | end; 335 | 336 | end. 337 | -------------------------------------------------------------------------------- /src/DropboxApi.Data.pas: -------------------------------------------------------------------------------- 1 | { 2 | Copyright (C) 2017 by Clever Components 3 | 4 | Author: Sergey Shirokov 5 | 6 | Website: www.CleverComponents.com 7 | 8 | This file is part of Dropbox Client Library for Delphi. 9 | 10 | Dropbox Client Library for Delphi is free software: 11 | you can redistribute it and/or modify it under the terms of 12 | the GNU Lesser General Public License version 3 13 | as published by the Free Software Foundation and appearing in the 14 | included file COPYING.LESSER. 15 | 16 | Dropbox Client Library for Delphi is distributed in the hope 17 | that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | See the GNU Lesser General Public License for more details. 20 | 21 | You should have received a copy of the GNU Lesser General Public License 22 | along with Dropbox Client Library. If not, see . 23 | 24 | The current version of Dropbox Client Client Library for Delphi needs for 25 | the non-free library Clever Internet Suite. This is a drawback, 26 | and we suggest the task of changing 27 | the program so that it does the same job without the non-free library. 28 | Anyone who thinks of doing substantial further work on the program, 29 | first may free it from dependence on the non-free library. 30 | } 31 | 32 | unit DropboxApi.Data; 33 | 34 | interface 35 | 36 | uses 37 | System.Classes, clJsonSerializerBase; 38 | type 39 | TError = class 40 | strict private 41 | FTag: string; 42 | public 43 | [TclJsonString('.tag')] 44 | property Tag: string read FTag write FTag; 45 | end; 46 | 47 | TListFolderArg = class 48 | strict private 49 | FPath: string; 50 | FRecursive: Boolean; 51 | FIncludeMediaInfo: Boolean; 52 | FIncludeDeleted: Boolean; 53 | FIncludeHasExplicitSharedMembers: Boolean; 54 | public 55 | [TclJsonRequired] 56 | [TclJsonString('path')] 57 | property Path: string read FPath write FPath; 58 | 59 | [TclJsonProperty('recursive')] 60 | property Recursive: Boolean read FRecursive write FRecursive; 61 | 62 | [TclJsonProperty('include_media_info')] 63 | property IncludeMediaInfo: Boolean read FIncludeMediaInfo write FIncludeMediaInfo; 64 | 65 | [TclJsonProperty('include_deleted')] 66 | property IncludeDeleted: Boolean read FIncludeDeleted write FIncludeDeleted; 67 | 68 | [TclJsonProperty('include_has_explicit_shared_members')] 69 | property IncludeHasExplicitSharedMembers: Boolean read FIncludeHasExplicitSharedMembers write FIncludeHasExplicitSharedMembers; 70 | end; 71 | 72 | TListFolderContinueArg = class 73 | strict private 74 | FCursor: string; 75 | public 76 | [TclJsonString('cursor')] 77 | property Cursor: string read FCursor write FCursor; 78 | end; 79 | 80 | [TclJsonTypeNameMap('.tag', 'file', 'DropboxApi.Data.TFileMetadata')] 81 | [TclJsonTypeNameMap('.tag', 'folder', 'DropboxApi.Data.TFolderMetadata')] 82 | [TclJsonTypeNameMap('.tag', 'deleted', 'DropboxApi.Data.TDeletedMetadata')] 83 | TMetadata = class 84 | strict private 85 | FTag: string; 86 | public 87 | [TclJsonString('.tag')] 88 | property Tag: string read FTag write FTag; 89 | end; 90 | 91 | TFileSharingInfo = class 92 | strict private 93 | FParentSharedFolderId: string; 94 | FModifiedBy: string; 95 | FReadOnly: Boolean; 96 | public 97 | [TclJsonProperty('read_only')] 98 | property ReadOnly: Boolean read FReadOnly write FReadOnly; 99 | 100 | [TclJsonString('parent_shared_folder_id')] 101 | property ParentSharedFolderId: string read FParentSharedFolderId write FParentSharedFolderId; 102 | 103 | [TclJsonString('modified_by')] 104 | property ModifiedBy: string read FModifiedBy write FModifiedBy; 105 | end; 106 | 107 | TFileMetadata = class(TMetadata) 108 | strict private 109 | FRev: string; 110 | FName: string; 111 | FPathDisplay: string; 112 | FPathLower: string; 113 | FId: string; 114 | FSize: Int64; 115 | FHasExplicitSharedMembers: Boolean; 116 | FServerModified: string; 117 | FClientModified: string; 118 | FSharingInfo: TFileSharingInfo; 119 | 120 | procedure SetSharingInfo(const Value: TFileSharingInfo); 121 | public 122 | constructor Create; 123 | destructor Destroy; override; 124 | 125 | [TclJsonString('name')] 126 | property Name: string read FName write FName; 127 | 128 | [TclJsonString('id')] 129 | property Id: string read FId write FId; 130 | 131 | [TclJsonString('client_modified')] 132 | property ClientModified: string read FClientModified write FClientModified; 133 | 134 | [TclJsonString('server_modified')] 135 | property ServerModified: string read FServerModified write FServerModified; 136 | 137 | [TclJsonString('rev')] 138 | property Rev: string read FRev write FRev; 139 | 140 | [TclJsonProperty('size')] 141 | property Size: Int64 read FSize write FSize; 142 | 143 | [TclJsonString('path_lower')] 144 | property PathLower: string read FPathLower write FPathLower; 145 | 146 | [TclJsonString('path_display')] 147 | property PathDisplay: string read FPathDisplay write FPathDisplay; 148 | 149 | //media_info 150 | 151 | [TclJsonProperty('sharing_info')] 152 | property SharingInfo: TFileSharingInfo read FSharingInfo write SetSharingInfo; 153 | 154 | //property_groups 155 | 156 | [TclJsonProperty('has_explicit_shared_members')] 157 | property HasExplicitSharedMembers: Boolean read FHasExplicitSharedMembers write FHasExplicitSharedMembers; 158 | end; 159 | 160 | TFolderSharingInfo = class 161 | strict private 162 | FTraverseOnly: Boolean; 163 | FSharedFolderId: string; 164 | FParentSharedFolderId: string; 165 | FReadOnly: Boolean; 166 | FNoAccess: Boolean; 167 | public 168 | [TclJsonProperty('read_only')] 169 | property ReadOnly: Boolean read FReadOnly write FReadOnly; 170 | 171 | [TclJsonString('parent_shared_folder_id')] 172 | property ParentSharedFolderId: string read FParentSharedFolderId write FParentSharedFolderId; 173 | 174 | [TclJsonString('shared_folder_id')] 175 | property SharedFolderId: string read FSharedFolderId write FSharedFolderId; 176 | 177 | [TclJsonProperty('traverse_only')] 178 | property TraverseOnly: Boolean read FTraverseOnly write FTraverseOnly; 179 | 180 | [TclJsonProperty('no_access')] 181 | property NoAccess: Boolean read FNoAccess write FNoAccess; 182 | end; 183 | 184 | TFolderMetadata = class(TMetadata) 185 | strict private 186 | FName: string; 187 | FPathDisplay: string; 188 | FPathLower: string; 189 | FId: string; 190 | FSharingInfo: TFolderSharingInfo; 191 | 192 | procedure SetSharingInfo(const Value: TFolderSharingInfo); 193 | public 194 | constructor Create; 195 | destructor Destroy; override; 196 | 197 | [TclJsonString('name')] 198 | property Name: string read FName write FName; 199 | 200 | [TclJsonString('id')] 201 | property Id: string read FId write FId; 202 | 203 | [TclJsonString('path_lower')] 204 | property PathLower: string read FPathLower write FPathLower; 205 | 206 | [TclJsonString('path_display')] 207 | property PathDisplay: string read FPathDisplay write FPathDisplay; 208 | 209 | [TclJsonProperty('sharing_info')] 210 | property SharingInfo: TFolderSharingInfo read FSharingInfo write SetSharingInfo; 211 | 212 | //property_groups 213 | end; 214 | 215 | TDeletedMetadata = class(TMetadata) 216 | strict private 217 | FName: string; 218 | FPathDisplay: string; 219 | FPathLower: string; 220 | public 221 | constructor Create; 222 | 223 | [TclJsonString('name')] 224 | property Name: string read FName write FName; 225 | 226 | [TclJsonString('path_lower')] 227 | property PathLower: string read FPathLower write FPathLower; 228 | 229 | [TclJsonString('path_display')] 230 | property PathDisplay: string read FPathDisplay write FPathDisplay; 231 | end; 232 | 233 | TListFolderResult = class 234 | strict private 235 | FEntries: TArray; 236 | FCursor: string; 237 | FHasMore: Boolean; 238 | 239 | procedure SetEntries(const Value: TArray); 240 | public 241 | constructor Create; 242 | destructor Destroy; override; 243 | 244 | [TclJsonProperty('entries')] 245 | property Entries: TArray read FEntries write SetEntries; 246 | 247 | [TclJsonString('cursor')] 248 | property Cursor: string read FCursor write FCursor; 249 | 250 | [TclJsonProperty('has_more')] 251 | property HasMore: Boolean read FHasMore write FHasMore; 252 | end; 253 | 254 | TCreateFolderArg = class 255 | strict private 256 | FPath: string; 257 | FAutoRename: Boolean; 258 | public 259 | [TclJsonString('path')] 260 | property Path: string read FPath write FPath; 261 | 262 | [TclJsonProperty('autorename')] 263 | property AutoRename: Boolean read FAutoRename write FAutoRename; 264 | end; 265 | 266 | TDeleteArg = class 267 | strict private 268 | FPath: string; 269 | public 270 | [TclJsonString('path')] 271 | property Path: string read FPath write FPath; 272 | end; 273 | 274 | [TclJsonTypeNameMap('.tag', 'add', 'DropboxApi.Data.TAddWriteMode')] 275 | [TclJsonTypeNameMap('.tag', 'overwrite', 'DropboxApi.Data.TOverwriteWriteMode')] 276 | [TclJsonTypeNameMap('.tag', 'update', 'DropboxApi.Data.TUpdateWriteMode')] 277 | TWriteMode = class 278 | strict private 279 | FTag: string; 280 | public 281 | [TclJsonString('.tag')] 282 | property Tag: string read FTag write FTag; 283 | end; 284 | 285 | TAddWriteMode = class(TWriteMode) 286 | public 287 | constructor Create; 288 | end; 289 | 290 | TOverwriteWriteMode = class(TWriteMode) 291 | public 292 | constructor Create; 293 | end; 294 | 295 | TUpdateWriteMode = class(TWriteMode) 296 | strict private 297 | FUpdate: string; 298 | public 299 | constructor Create; 300 | 301 | [TclJsonString('update')] 302 | property Update: string read FUpdate write FUpdate; 303 | end; 304 | 305 | TCommitInfo = class 306 | strict private 307 | FPath: string; 308 | FMode: TWriteMode; 309 | FMute: Boolean; 310 | FAutoRename: Boolean; 311 | FClientModified: string; 312 | 313 | procedure SetMode(const Value: TWriteMode); 314 | public 315 | constructor Create; 316 | destructor Destroy; override; 317 | 318 | [TclJsonString('path')] 319 | property Path: string read FPath write FPath; 320 | 321 | [TclJsonProperty('mode')] 322 | property Mode: TWriteMode read FMode write SetMode; 323 | 324 | [TclJsonProperty('autorename')] 325 | property AutoRename: Boolean read FAutoRename write FAutoRename; 326 | 327 | [TclJsonProperty('client_modified')] 328 | property ClientModified: string read FClientModified write FClientModified; 329 | 330 | [TclJsonProperty('mute')] 331 | property Mute: Boolean read FMute write FMute; 332 | end; 333 | 334 | TDownloadArg = class 335 | strict private 336 | FPath: string; 337 | public 338 | [TclJsonString('path')] 339 | property Path: string read FPath write FPath; 340 | end; 341 | 342 | [TclJsonTypeNameMap('.tag', 'filename', 'DropboxApi.Data.TFileNameSearchMode')] 343 | [TclJsonTypeNameMap('.tag', 'filename_and_content', 'DropboxApi.Data.TFilenameAndContentSearchMode')] 344 | [TclJsonTypeNameMap('.tag', 'deleted_filename', 'DropboxApi.Data.TDeletedFilenameSearchMode')] 345 | TSearchMode = class 346 | strict private 347 | FTag: string; 348 | public 349 | [TclJsonString('.tag')] 350 | property Tag: string read FTag write FTag; 351 | end; 352 | 353 | TFileNameSearchMode = class(TSearchMode) 354 | public 355 | constructor Create; 356 | end; 357 | 358 | TFilenameAndContentSearchMode = class(TSearchMode) 359 | public 360 | constructor Create; 361 | end; 362 | 363 | TDeletedFilenameSearchMode = class(TSearchMode) 364 | public 365 | constructor Create; 366 | end; 367 | 368 | TSearchArg = class 369 | strict private 370 | FPath: string; 371 | FQuery: string; 372 | FStart: Int64; 373 | FMaxResults: Int64; 374 | FMode: TSearchMode; 375 | 376 | procedure SetMode(const Value: TSearchMode); 377 | public 378 | constructor Create; 379 | destructor Destroy; override; 380 | 381 | [TclJsonRequired] 382 | [TclJsonString('path')] 383 | property Path: string read FPath write FPath; 384 | 385 | [TclJsonRequired] 386 | [TclJsonString('query')] 387 | property Query: string read FQuery write FQuery; 388 | 389 | [TclJsonProperty('start')] 390 | property Start: Int64 read FStart write FStart; 391 | 392 | [TclJsonProperty('max_results')] 393 | property MaxResults: Int64 read FMaxResults write FMaxResults; 394 | 395 | [TclJsonProperty('mode')] 396 | property Mode: TSearchMode read FMode write SetMode; 397 | end; 398 | 399 | [TclJsonTypeNameMap('.tag', 'filename', 'DropboxApi.Data.TFileNameSearchMatchType')] 400 | [TclJsonTypeNameMap('.tag', 'content', 'DropboxApi.Data.TContentSearchMatchType')] 401 | [TclJsonTypeNameMap('.tag', 'both', 'DropboxApi.Data.TBothSearchMatchType')] 402 | TSearchMatchType = class 403 | strict private 404 | FTag: string; 405 | public 406 | [TclJsonString('.tag')] 407 | property Tag: string read FTag write FTag; 408 | end; 409 | 410 | TFileNameSearchMatchType = class(TSearchMatchType) 411 | public 412 | constructor Create; 413 | end; 414 | 415 | TContentSearchMatchType = class(TSearchMatchType) 416 | public 417 | constructor Create; 418 | end; 419 | 420 | TBothSearchMatchType = class(TSearchMatchType) 421 | public 422 | constructor Create; 423 | end; 424 | 425 | TSearchMatch = class 426 | strict private 427 | FMatchType: TSearchMatchType; 428 | FMetadata: TMetadata; 429 | 430 | procedure SetMatchType(const Value: TSearchMatchType); 431 | procedure SetMetadata(const Value: TMetadata); 432 | public 433 | constructor Create; 434 | destructor Destroy; override; 435 | 436 | [TclJsonProperty('match_type')] 437 | property MatchType: TSearchMatchType read FMatchType write SetMatchType; 438 | 439 | [TclJsonProperty('metadata')] 440 | property Metadata: TMetadata read FMetadata write SetMetadata; 441 | end; 442 | 443 | TSearchResult = class 444 | strict private 445 | FMatches: TArray; 446 | FMore: Boolean; 447 | FStart: Int64; 448 | 449 | procedure SetMatches(const Value: TArray); 450 | public 451 | constructor Create; 452 | destructor Destroy; override; 453 | 454 | [TclJsonProperty('matches')] 455 | property Matches: TArray read FMatches write SetMatches; 456 | 457 | [TclJsonProperty('more')] 458 | property More: Boolean read FMore write FMore; 459 | 460 | [TclJsonProperty('start')] 461 | property Start: Int64 read FStart write FStart; 462 | end; 463 | 464 | TRelocationArg = class 465 | strict private 466 | FFromPath: string; 467 | FToPath: string; 468 | FAllowSharedFolder: Boolean; 469 | FAutoRename: Boolean; 470 | public 471 | [TclJsonString('from_path')] 472 | property FromPath: string read FFromPath write FFromPath; 473 | 474 | [TclJsonString('to_path')] 475 | property ToPath: string read FToPath write FToPath; 476 | 477 | [TclJsonProperty('allow_shared_folder')] 478 | property AllowSharedFolder: Boolean read FAllowSharedFolder write FAllowSharedFolder; 479 | 480 | [TclJsonProperty('autorename')] 481 | property AutoRename: Boolean read FAutoRename write FAutoRename; 482 | end; 483 | 484 | TSaveUrlArg = class 485 | strict private 486 | FPath: string; 487 | FUrl: string; 488 | public 489 | [TclJsonString('path')] 490 | property Path: string read FPath write FPath; 491 | 492 | [TclJsonString('url')] 493 | property Url: string read FUrl write FUrl; 494 | end; 495 | 496 | [TclJsonTypeNameMap('.tag', 'async_job_id', 'DropboxApi.Data.TSaveUrlResultAsyncJobId')] 497 | [TclJsonTypeNameMap('.tag', 'complete', 'DropboxApi.Data.TSaveUrlResultComplete')] 498 | TSaveUrlResult = class 499 | strict private 500 | FTag: string; 501 | public 502 | [TclJsonString('.tag')] 503 | property Tag: string read FTag write FTag; 504 | end; 505 | 506 | TSaveUrlResultAsyncJobId = class(TSaveUrlResult) 507 | strict private 508 | FAsyncJobId: string; 509 | public 510 | constructor Create; 511 | 512 | [TclJsonString('async_job_id')] 513 | property AsyncJobId: string read FAsyncJobId write FAsyncJobId; 514 | end; 515 | 516 | //TODO implement unions of different types without the common ancentor in json serializer 517 | //here must be the TFileMetadata class 518 | TSaveUrlResultComplete = class(TSaveUrlResult) 519 | public 520 | constructor Create; 521 | end; 522 | 523 | TPollArg = class 524 | strict private 525 | FAsyncJobId: string; 526 | public 527 | [TclJsonString('async_job_id')] 528 | property AsyncJobId: string read FAsyncJobId write FAsyncJobId; 529 | end; 530 | 531 | [TclJsonTypeNameMap('.tag', 'in_progress', 'DropboxApi.Data.TSaveUrlJobStatusInProgress')] 532 | [TclJsonTypeNameMap('.tag', 'complete', 'DropboxApi.Data.TSaveUrlJobStatusComplete')] 533 | [TclJsonTypeNameMap('.tag', 'failed', 'DropboxApi.Data.TSaveUrlJobStatusFailed')] 534 | TSaveUrlJobStatus = class 535 | strict private 536 | FTag: string; 537 | public 538 | [TclJsonString('.tag')] 539 | property Tag: string read FTag write FTag; 540 | end; 541 | 542 | TSaveUrlJobStatusInProgress = class(TSaveUrlJobStatus) 543 | public 544 | constructor Create; 545 | end; 546 | 547 | //TODO implement unions of different types without the common ancentor in json serializer 548 | //here must be the TFileMetadata class 549 | TSaveUrlJobStatusComplete = class(TSaveUrlJobStatus) 550 | public 551 | constructor Create; 552 | end; 553 | 554 | TSaveUrlJobStatusFailed = class(TSaveUrlJobStatus) 555 | public 556 | constructor Create; 557 | end; 558 | 559 | implementation 560 | 561 | { TListFolderResult } 562 | 563 | constructor TListFolderResult.Create; 564 | begin 565 | inherited Create(); 566 | FEntries := nil; 567 | end; 568 | 569 | destructor TListFolderResult.Destroy; 570 | begin 571 | SetEntries(nil); 572 | inherited Destroy(); 573 | end; 574 | 575 | procedure TListFolderResult.SetEntries(const Value: TArray); 576 | var 577 | obj: TObject; 578 | begin 579 | if (FEntries <> nil) then 580 | begin 581 | for obj in FEntries do 582 | begin 583 | obj.Free(); 584 | end; 585 | end; 586 | 587 | FEntries := Value; 588 | end; 589 | 590 | { TFolderMetadata } 591 | 592 | constructor TFolderMetadata.Create; 593 | begin 594 | inherited Create(); 595 | 596 | FSharingInfo := nil; 597 | Tag := 'folder'; 598 | end; 599 | 600 | destructor TFolderMetadata.Destroy; 601 | begin 602 | FSharingInfo.Free(); 603 | inherited Destroy(); 604 | end; 605 | 606 | procedure TFolderMetadata.SetSharingInfo(const Value: TFolderSharingInfo); 607 | begin 608 | FSharingInfo.Free(); 609 | FSharingInfo := Value; 610 | end; 611 | 612 | { TFileMetadata } 613 | 614 | constructor TFileMetadata.Create; 615 | begin 616 | inherited Create(); 617 | 618 | FSharingInfo := nil; 619 | Tag := 'file'; 620 | end; 621 | 622 | destructor TFileMetadata.Destroy; 623 | begin 624 | FSharingInfo.Free(); 625 | inherited Destroy(); 626 | end; 627 | 628 | procedure TFileMetadata.SetSharingInfo(const Value: TFileSharingInfo); 629 | begin 630 | FSharingInfo.Free(); 631 | FSharingInfo := Value; 632 | end; 633 | 634 | { TCommitInfo } 635 | 636 | constructor TCommitInfo.Create; 637 | begin 638 | inherited Create(); 639 | FMode := nil; 640 | end; 641 | 642 | destructor TCommitInfo.Destroy; 643 | begin 644 | SetMode(nil); 645 | inherited Destroy(); 646 | end; 647 | 648 | procedure TCommitInfo.SetMode(const Value: TWriteMode); 649 | begin 650 | FMode.Free(); 651 | FMode := Value; 652 | end; 653 | 654 | { TDeletedMetadata } 655 | 656 | constructor TDeletedMetadata.Create; 657 | begin 658 | inherited Create(); 659 | Tag := 'deleted'; 660 | end; 661 | 662 | { TAdd } 663 | 664 | constructor TAddWriteMode.Create; 665 | begin 666 | inherited Create(); 667 | Tag := 'add'; 668 | end; 669 | 670 | { TUpdate } 671 | 672 | constructor TUpdateWriteMode.Create; 673 | begin 674 | inherited Create(); 675 | Tag := 'update'; 676 | end; 677 | 678 | { TOverwrite } 679 | 680 | constructor TOverwriteWriteMode.Create; 681 | begin 682 | inherited Create(); 683 | Tag := 'overwrite'; 684 | end; 685 | 686 | { TFileName } 687 | 688 | constructor TFileNameSearchMode.Create; 689 | begin 690 | inherited Create(); 691 | Tag := 'filename'; 692 | end; 693 | 694 | { TFilenameAndContent } 695 | 696 | constructor TFilenameAndContentSearchMode.Create; 697 | begin 698 | inherited Create(); 699 | Tag := 'filename_and_content'; 700 | end; 701 | 702 | { TDeletedFilename } 703 | 704 | constructor TDeletedFilenameSearchMode.Create; 705 | begin 706 | inherited Create(); 707 | Tag := 'deleted_filename'; 708 | end; 709 | 710 | { TSearchArg } 711 | 712 | constructor TSearchArg.Create; 713 | begin 714 | inherited Create(); 715 | FMode := nil; 716 | MaxResults := 100; 717 | end; 718 | 719 | destructor TSearchArg.Destroy; 720 | begin 721 | SetMode(nil); 722 | inherited Destroy(); 723 | end; 724 | 725 | procedure TSearchArg.SetMode(const Value: TSearchMode); 726 | begin 727 | FMode.Free(); 728 | FMode := Value; 729 | end; 730 | 731 | { TSearchResult } 732 | 733 | constructor TSearchResult.Create; 734 | begin 735 | inherited Create(); 736 | FMatches := nil; 737 | end; 738 | 739 | destructor TSearchResult.Destroy; 740 | begin 741 | SetMatches(nil); 742 | inherited Destroy(); 743 | end; 744 | 745 | procedure TSearchResult.SetMatches(const Value: TArray); 746 | var 747 | obj: TObject; 748 | begin 749 | if (FMatches <> nil) then 750 | begin 751 | for obj in FMatches do 752 | begin 753 | obj.Free(); 754 | end; 755 | end; 756 | 757 | FMatches := Value; 758 | end; 759 | 760 | { TFileNameSearchMatchType } 761 | 762 | constructor TFileNameSearchMatchType.Create; 763 | begin 764 | inherited Create(); 765 | Tag := 'filename'; 766 | end; 767 | 768 | { TContentSearchMatchType } 769 | 770 | constructor TContentSearchMatchType.Create; 771 | begin 772 | inherited Create(); 773 | Tag := 'content'; 774 | end; 775 | 776 | { TBothSearchMatchType } 777 | 778 | constructor TBothSearchMatchType.Create; 779 | begin 780 | inherited Create(); 781 | Tag := 'both'; 782 | end; 783 | 784 | { TSearchMatch } 785 | 786 | constructor TSearchMatch.Create; 787 | begin 788 | inherited Create(); 789 | 790 | FMatchType := nil; 791 | FMetadata := nil; 792 | end; 793 | 794 | destructor TSearchMatch.Destroy; 795 | begin 796 | SetMatchType(nil); 797 | SetMetadata(nil); 798 | 799 | inherited Destroy(); 800 | end; 801 | 802 | procedure TSearchMatch.SetMatchType(const Value: TSearchMatchType); 803 | begin 804 | FMatchType.Free(); 805 | FMatchType := Value; 806 | end; 807 | 808 | procedure TSearchMatch.SetMetadata(const Value: TMetadata); 809 | begin 810 | FMetadata.Free(); 811 | FMetadata := Value; 812 | end; 813 | 814 | { TSaveUrlResultAsyncJobId } 815 | 816 | constructor TSaveUrlResultAsyncJobId.Create; 817 | begin 818 | inherited Create(); 819 | Tag := 'async_job_id'; 820 | end; 821 | 822 | { TSaveUrlResultComplete } 823 | 824 | constructor TSaveUrlResultComplete.Create; 825 | begin 826 | inherited Create(); 827 | Tag := 'complete'; 828 | end; 829 | 830 | { TSaveUrlJobStatusInProgress } 831 | 832 | constructor TSaveUrlJobStatusInProgress.Create; 833 | begin 834 | inherited Create(); 835 | Tag := 'in_progress'; 836 | end; 837 | 838 | { TSaveUrlJobStatusComplete } 839 | 840 | constructor TSaveUrlJobStatusComplete.Create; 841 | begin 842 | inherited Create(); 843 | Tag := 'complete'; 844 | end; 845 | 846 | { TSaveUrlJobStatusFailed } 847 | 848 | constructor TSaveUrlJobStatusFailed.Create; 849 | begin 850 | inherited Create(); 851 | Tag := 'failed'; 852 | end; 853 | 854 | procedure ForceReferenceToClass(C: TClass); 855 | begin 856 | end; 857 | 858 | initialization 859 | ForceReferenceToClass(TError); 860 | ForceReferenceToClass(TListFolderArg); 861 | ForceReferenceToClass(TListFolderContinueArg); 862 | ForceReferenceToClass(TMetadata); 863 | ForceReferenceToClass(TFileSharingInfo); 864 | ForceReferenceToClass(TFileMetadata); 865 | ForceReferenceToClass(TFolderSharingInfo); 866 | ForceReferenceToClass(TFolderMetadata); 867 | ForceReferenceToClass(TDeletedMetadata); 868 | ForceReferenceToClass(TListFolderResult); 869 | ForceReferenceToClass(TCreateFolderArg); 870 | ForceReferenceToClass(TDeleteArg); 871 | ForceReferenceToClass(TWriteMode); 872 | ForceReferenceToClass(TAddWriteMode); 873 | ForceReferenceToClass(TOverwriteWriteMode); 874 | ForceReferenceToClass(TUpdateWriteMode); 875 | ForceReferenceToClass(TCommitInfo); 876 | ForceReferenceToClass(TDownloadArg); 877 | ForceReferenceToClass(TSearchMode); 878 | ForceReferenceToClass(TFileNameSearchMode); 879 | ForceReferenceToClass(TFilenameAndContentSearchMode); 880 | ForceReferenceToClass(TDeletedFilenameSearchMode); 881 | ForceReferenceToClass(TSearchArg); 882 | ForceReferenceToClass(TSearchMatchType); 883 | ForceReferenceToClass(TFileNameSearchMatchType); 884 | ForceReferenceToClass(TContentSearchMatchType); 885 | ForceReferenceToClass(TBothSearchMatchType); 886 | ForceReferenceToClass(TSearchMatch); 887 | ForceReferenceToClass(TSearchResult); 888 | ForceReferenceToClass(TRelocationArg); 889 | ForceReferenceToClass(TSaveUrlArg); 890 | ForceReferenceToClass(TSaveUrlResult); 891 | ForceReferenceToClass(TSaveUrlResultAsyncJobId); 892 | ForceReferenceToClass(TSaveUrlResultComplete); 893 | ForceReferenceToClass(TPollArg); 894 | ForceReferenceToClass(TSaveUrlJobStatus); 895 | ForceReferenceToClass(TSaveUrlJobStatusInProgress); 896 | ForceReferenceToClass(TSaveUrlJobStatusComplete); 897 | ForceReferenceToClass(TSaveUrlJobStatusFailed); 898 | 899 | end. 900 | --------------------------------------------------------------------------------