In this post, you will learn about a header-only library that allows an application to use an abstract interface and interact with Google Drive, OneDrive and DropBox when saving/opening a file.
Introduction
Now that cloud storage is as available as it never was, lots of applications would want to be able to load or save files to the cloud. Here is a header-only library that allows an application to use an abstract interface and interact with Google Drive, OneDrive and DropBox when saving/opening a file. It's provided in two GUI versions, either with UWP (for Windows 10 1903+) or without UWP.
Here is the interface with UWP:
And here it is without it:
Quick Setup
The library uses my REST, my GOD library, my UWPLib library, my XML library, my RKEY library and my AX library all combined in a single header system.
- Include rgf1.hpp for the library
- For UWP interface, include rgf2.hpp (along with 1.manifest)
- For the non UWP interface, include rgf3.hpp and the .rc file.
RGB::RGBF s;
s.google.tokens.resize(3);
s.google.id = "...";
s.google.secret = "...";
s.google.tokens[0] = "... access token ...";
s.google.tokens[1] = "... refresh token ...";
You have to create an application for any platform you want to use. All three use OAUTH2
for authentication. If you do not pass an access token, the user will be asked to login. By default, this is done in an external browser (your default), but you can change the function RunUrl
to use my own AX interface which opens an IWebBrowser
control. Note that IWebBrowser2
might be incompatible with the latest HTML features, so it is recommended to use the default external browser. Your redirect URL is listening at port 9932 by default.
- For OneDrive, you have to create a "Converged Application" here, or a new Azure App here.
- For Google Drive, you create a new application in the Google Cloud Platform here.
- For DropBox, you create a new app here.
The RGBF Structure
struct RGBF
{
int func = 0; HWND hParent = 0;
bool NoBrowserKey = false;
HRESULT rs = E_ABORT;
GOD::ystring resultFile;
GOD::ystring DefExt;
std::vector<wchar_t> Filter;
std::shared_ptr<RGF::GOD::GOOGLEDRIVE> goo = 0;
std::shared_ptr<RGF::GOD::ONEDRIVE> one = 0;
std::shared_ptr<RGF::GOD::DROPBOX> drop = 0;
AUTH google;
AUTH onedrive;
AUTH db;
std::wstring Title;
DWORD sz = 0;
const char* d = nullptr;
std::function<HRESULT(char*, size_t)> cbf = nullptr;
std::vector<char>* read = 0;
HWND hH = 0;
bool InProgress = false;
bool ShouldCancelProp = false;
};
Opening a File
RGF::RGBF s;
std::vector<char> r;
s.read = &r;
HRESULT rv = RGF::Open(s); HRESULT rv = RGF::Open2(s);
On success (rv == S_*
) the passed vector is filled with the data of the opened file, whether it is a local file or a remote file. Unlike the common dialog, RGF will load the file for you in the provided vector. If you do not provide a vector, then only the file name (or ID, if in cloud) will be returned.
Saving a File
RGF::RGBF s;
s.d = d.data();
s.sz = (DWORD)d.size();
s.resultFile = L"r:\\1.dat"; s.DefExt = L"dat"; HRESULT rv = RGF::Save(s); HRESULT rv = RGF::Save2(s);
In this function, you provide the data to be saved beforehand as well.
The Sample Project
A sample project is included (VS 2019) that saves/loads credentials/tokens in a XML file. You can #define USE_UWP instdfx.h
to use the UWP interface.
BAR (Backup ARchiver) project
I've always wanted to create my own archiver. Here is a simple open source tool that uses the Compression API to compress, Remote Differential Comrpession to efficiently create incremental/differential backups and it also uses RGF to upload them to cloud storage. All that in a multithreaded environment using my multicore tools. The name is BAR (Backup ARchiver).
BAR archives use a tagged, extensible format. Each tag contains a header and the size of tag. At the moment, three tags are defined:
- Header
- Item information (attributes, name, time, CRC, etc.)
- Item data
Item data contains the stored data of the item. It can be:
- Uncompressed
- Signature of the file, to be used later in incremental backups
- Compressed with a method defined in the Compression API (Default is
COMPRESS_ALGORITHM_LZMS
) - Differential data based on previous backup
- Linked to another file (if storing duplicate files)
All the signature information is put before the actual compressed data, this allows the tool to download only the beginning of the files (when they are stored remotely) and to be able to create incremental backups without needing the entire full backup.
It can optionally encrypt data (it hashes the provided password with SHA-2 and encrypts using AES-256).
Command line
BAR <command> <options> <files>
Backup Archiver commands:
a - Create new archive or update archive
d - Delete files
e - Extract archive
ee - Extract from an archive folder (main archive and differential updates)
l - List archive contents
ll - List archive contents (csv)
m - Merge archives
s - Generate signature for archive
t - Test archive
tt - Test from an archive folder (main archive and differential updates)
u - Differentially update archive
uu - Differentially update archive (backup to folder)
z - Separate archive to signatures only
Backup Archiver Switches:
-i <mask> - Include files
-p <pwd> - Set password
-r - Recurse subdirectories
-o - Overwrite archive if it exists before adding files
-s - Generate signatures
-t - Test run
-y - Yes to all questions
-x - Exclude files
--ir - Include files with regexp
--dup - On duplicate files found, don't store them again, just link them.
--xr - Exclude files with regexp
--rgf <f> - Specify file for OneDrive/GoogleDrive/DropBox
-- keep <dir> - Keep an archive uploaded with uu to a local folder
-- incr <d> - Add incremental backup to "u" command.
--threads<n> - Use n threads (if not specified, it gets 2* available CPUs).
Most of the switches can be used with many commands (a,e,d, etc.)
Archive
BAR a target.bar -r -s --dup -x *.exe -x *.lib -x *.dll -p 12345678 c:\mytools
Will create an archive without exe/lib files with signatures (so it can be used later for incremental backups) and with password 12345678.
List
BAR l target.bar
BAR ll target.bar
Lists the archive contents in plain form or CSV.
Delete
BAR d target.bar *.dat
Will delete all "dat" files from archive.
Test/Extract
BAR t target.bar
BAR e target.bar c:\r
Will test, or extract the archive to c:\r.
Local Incremental Backup to Local File
BAR u target3.bar --incr target1.bar --incr target2.bar -r -s ... c:\mytools
Assuming that target1.bar and target2.bar were created with the -s
option, this will create an archive with incremental information (based on target1
and target2
) of the current state of c:\mytools. If nothing has changed, nothing will be created.
Local Incremental Backup to Local Folder
BAR uu c:\backups -r -s ... c:\mytools
Assuming that c:\backups contains other full/incremental backups, this will create a backup of c:\mytools. If no backups are there, a full backup will be created. If a full backup is there, an incremental backup of that backup will be created.
Local Incremental Backup to Cloud
BAR uu onedrive:BACKUPS\MYTOOLS --rgf 1.xml -r -s ... c:\mytools
Assuming that 1.xml contains client/secret/access tokens for onedrive (the format is the one used by the RGF library) this will create a backup of c:\mytools and upload it to onedrive. If no backups are there, a full backup will be created. If a full backup is there, an incremental backup of that backup will be created.
Because the BAR format stores signatures at the beginning, BAR does not need to download the entire full backup from the server in order to generate the differential backup.
Extract from folder/cloud
BAR ee c:\mybackups c:\r
BAR ee onedrive:BACKUPS\ --rgf 1.xml c:\r
Will extract all the backups to c:\r.
You can extract incremental backups with "e
" manually as well, for example if you have backup1.bar and backup2.bar, extracting the 2nd file after extracting the first will generate the incremental restore.
To Be Implemented (Yet)
- There is a UWP bug that prevents typing in a
TextBox
, use pasting for the moment. - DropBox does not work yet in non-UWP mode.
- DropBox logout does not work yet.
History
- 2nd June, 2019: Including BAR
- 1st June, 2019: First release