GOD class is now part of my RGF library.
Introduction
The time has come to put my good REST Library to use. Here is a simple, yet powerful library that provides an abstraction class to use Google Drive, OneDrive and DropBox services. I use them in my own BAR app.
Background
In this article, I use some simple extensions to known elements, like the ystring
(a wstring
that can also return an ANSI string
in UTF-8), TEVENT<>
(a wrapper on HEVENT
), and XSOCKET
, a wrapper of SOCKET with SSL support - all of these are simple to understand and use and they will be discussed in later articles or have been discussed in previous articles. In addition, Hong Jiang's jsonxx
library is used.
You only need to include god.h to your projects, along with jsonxx.h, sync.h, rest.h, xsocket.h and ystring.h.
The zip file contains a solution and you can uncomment main.cpp lines to download and upload files.
Abstract DRIVE Class
The entire thing is based on an abstract class called DRIVE
, a descendant of my REST
class:
class DRIVE : public REST
{
protected:
ystring cid;
ystring secret;
jsonxx::Object j;
int port = 9932;
TEVENT<> ev;
XSOCKET x;
vector<char> nd;
public:
DRIVE(const char* ccid = 0, const char* ssid = 0,int HostPort = 9932)
{
SetClient(ccid, ssid,HostPort);
}
virtual void SetClient(const char* ccid = 0, const char* ssid = 0,int HostPort = 9932)
{
if (ccid)
cid = ccid;
if (ssid)
secret = ssid;
port = HostPort;
}
virtual string jsonreturn(ihandle& r)
{
vector<char> out;
ReadToMemory(r, out);
out.resize(out.size() + 1);
char* p = (char*)out.data();
return p;
}
virtual int Auth(vector<string>&) = 0;
virtual string CreateFolder(const char* fn,const char*pid) = 0;
virtual string GetRootFolderID() = 0;
virtual string IDFromPath(const char* Path,bool CreateIfNotExists = false) = 0;
virtual string dir(const char* Path = 0,bool IsRDir = false) = 0;
virtual string ItemProps(const char* id) = 0;
virtual string SetProperty(const char* id, const char* n, const char* v) = 0;
virtual HRESULT Download(const char* fid, HANDLE hF, vector<char>* arr,
unsigned long long from = 0, unsigned long long to = (unsigned long long) - 1,
std::function<HRESULT(unsigned long long, unsigned long long, void*)> fx = 0,
void* lp = 0) = 0;
virtual HRESULT Upload(bool Resumable,HANDLE hX, vector<char>* arr,
const char* folderid, const char* filename, string& resumedata,string&
returndata,std::function<HRESULT(unsigned long long f, unsigned long long t,
void* lp)> fx = 0, void* lp = 0) = 0;
virtual string Delete(const char *rp,const char* fid, bool Trash = false) = 0;
virtual HRESULT HashItem(const char* id, string& Hash, ALG_ID& HashAlg) = 0;
};
Constructor
The problem of all these libraries is that they require some manual "OK" from the user to initially allow access, and this has to be done over a browser. Therefore, each constructor takes, along with the "client id" and "client secret" parameters, a TCP port in which a termporarily web server is listening.
DRIVE(const char* ccid = 0, const char* ssid = 0,int HostPort = 9932);
Authentication
virtual int Auth(vector<string>&);
You pass a vector<string>
to this function, containing authentication token values. If first time, you pass an empty vector. On return, this function returns:
- 0 - Failed. End of library usage
- 1 - Succeeded
- 2 - Succeeded, new tokens have arrived, you should now save the contains of this vector for further usage.
Normally, an access token, a refresh token and a code are returned. Auth()
on first time will create a listening socket, then open a web page with an authorization URL for the user to click "I accept", then, a code will be returned to the application, which is then used to claim an access token.
Files and Folders
In Google drive and one drive, files and folders are represented by IDs, where, in dropbox, files are represented by file names. To ensure compatibility, the library uses the "id
" naming no matter what.
Getting Information
string IDFromPath(const char* Path,bool CreateIfNotExists = false);
This function returns an ID from a given path name. If this item does not exist and CreateIfNotExists
is true
, the function creates a directory at that path.
string GetRootFolderID();
This function returns the ID
of the "root" folder.
string dir(const char* Path = 0,bool IsRDir = false);
This function returns the directory (as a json string) for the given path. If IsRDir
is true
, then the Path
is assumed to be an ID (if not, the function IDFromPath
is used to convert the path to an ID).
Create a Folder
virtual string CreateFolder(const char* fn,const char*pid);
Creates a folder with a given file name on a parent directory with ID pid
. Returns the describing json on success.
Delete an Item
string Delete(const char *rp,const char* fid, bool Trash = false);
Deletes an item. In Google and Onedrive, only the second parameter is used (the ID), while, in DropBox, only the first parameter (the path) is used. Trash
is true
if the file is to be sent to the recycle bin.
When you call ONEDRIVE::Delete
or DROPBOX::Delete
with Trash
set to false
, E_NOTIMPL
is returned. These drives only allow recycling from the API, not direct delete.
Hash an Item
HRESULT HashItem(const char* id, string& Hash, ALG_ID& HashAlg);
Hashes a remote item (Google Drive only), returning a CALG_MD5 string
.
Download Data
HRESULT Download(const char* fid, HANDLE hF, vector<char>* arr,
unsigned long long from = 0, unsigned long long to = (unsigned long long) - 1,
std::function<HRESULT(unsigned long long, unsigned long long, void*)> fx = 0,
void* lp = 0) = 0;
Accepting as parameters:
- The ID of the file to download
- Either a HANDLE to save to file, or a
vector<char>
to save to a buffer - from/to, download range (pass
0,-1
for entire stream) - A callback and its param for progress
This function downloads the specified item.
Uploading Data
HRESULT Upload(bool Resumable,HANDLE hX, vector<char>* arr,const char* folderid,
const char* filename, string& resumedata,string& returndata,std::function<HRESULT
(unsigned long long f, unsigned long long t, void* lp)> fx = 0, void* lp = 0) = 0;
Accepting as parameters:
- A flag to indicate if resumable uploads should be supported (Google Drive only)
- A handle or a vector to read data
- The parent folder's ID
- The new file name
- A callback and its param for progress.
This function uploads data.
For Google drive, you can use either UploadOnce()
:
HRESULT UploadOnce(HANDLE hX, vector<char>* arr, const char* folderid,
const char* filename, string& returndata, std::function<HRESULT
(unsigned long long f, unsigned long long t, void* lp)> fx = 0, void* lp = 0)
or you can use BeginResumable()
:
HRESULT BeginResumable(HANDLE hX, vector<char>* arr, const char* folderid,
const char* filename, string& returndata, string& resumedata,std::function<HRESULT
(unsigned long long f, unsigned long long t, void* lp)> fx = 0, void* lp = 0);
If this function fails, there may be resume-related data returned. In this case, you can call again the ContinueResumable()
:
HRESULT ContinueResumable(HANDLE hX, vector<char>* arr, const char* folderid,
const char* filename, string& returndata, string& resumedata,
std::function<HRESULT(unsigned long long f, unsigned long long t, void* lp)> fx = 0,
void* lp = 0);
Which can resume the upload.
History