Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / UWP

RGF: A Save/Open Dialog Box with Cloud Capabilities

5.00/5 (7 votes)
31 May 2019CPOL5 min read 10.8K  
Replace GetOpenFileName/GetSaveFileName with a new cloud API!
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:

Image 1

And here it is without it:

Image 2

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.

  1. Include rgf1.hpp for the library
  2. For UWP interface, include rgf2.hpp (along with 1.manifest)
  3. For the non UWP interface, include rgf3.hpp and the .rc file.
C++
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 ...";
// Same for s.onedrive and s.db	

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

C++
struct RGBF
    {
        int func = 0; // 0 save, 1 load
        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;

        // Saving
        DWORD sz = 0;
        const char* d = nullptr;
        std::function<HRESULT(char*, size_t)> cbf = nullptr;

        // Opening
        std::vector<char>* read = 0;

        // For Old style only
        HWND hH = 0;
        bool InProgress = false;
        bool ShouldCancelProp = false;
    };

Opening a File

C++
RGF::RGBF s;
std::vector<char> r;
s.read = &r;
HRESULT rv = RGF::Open(s);  // Uses the UWP Interface
HRESULT rv = RGF::Open2(s); // Uses the old Interface

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

C++
RGF::RGBF s;
s.d = d.data();
s.sz = (DWORD)d.size();
s.resultFile = L"r:\\1.dat"; // for default local saving
s.DefExt = L"dat"; // added automatically to remote files as well
HRESULT rv = RGF::Save(s); // Uses the UWP Interface
HRESULT rv = RGF::Save2(s); // Uses the old Interface

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)