Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

The GOD : Google, Onedrive and Dropbox Access in One REST Windows Library!

0.00/5 (No votes)
30 May 2019 1  
C++ dir, upload, download and management library

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

  • 3-2-2017: First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here