mirror of https://github.com/vitalif/grive2
move the .grive from home directory to current directory. get change stamp
parent
0b63d9bd3c
commit
53883ab8bd
|
@ -28,32 +28,14 @@ const std::string& Config::Filename()
|
||||||
{
|
{
|
||||||
static const char *env_cfg = ::getenv( "GR_CONFIG" ) ;
|
static const char *env_cfg = ::getenv( "GR_CONFIG" ) ;
|
||||||
static const std::string filename =
|
static const std::string filename =
|
||||||
(env_cfg != 0) ? env_cfg : std::string( ::getenv( "HOME") ) + "/.grive" ;
|
(env_cfg != 0) ? env_cfg : /*std::string( ::getenv( "HOME") ) +*/ ".grive_state" ;
|
||||||
|
|
||||||
return filename ;
|
return filename ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Config()
|
Config::Config() :
|
||||||
|
m_cfg( Read( Filename() ) )
|
||||||
{
|
{
|
||||||
std::ifstream ifile( Filename().c_str() ) ;
|
|
||||||
if ( ifile )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string cfg_str(
|
|
||||||
(std::istreambuf_iterator<char>( ifile )),
|
|
||||||
(std::istreambuf_iterator<char>()) ) ;
|
|
||||||
|
|
||||||
m_cfg = Json::Parse( cfg_str ) ;
|
|
||||||
}
|
|
||||||
catch ( Exception& e )
|
|
||||||
{
|
|
||||||
throw Error()
|
|
||||||
<< File( Filename() )
|
|
||||||
<< expt::ErrMsg("Cannot open config file ")
|
|
||||||
<< expt::Nested(e) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::Save( )
|
void Config::Save( )
|
||||||
|
@ -67,4 +49,19 @@ Json& Config::Get()
|
||||||
return m_cfg ;
|
return m_cfg ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json Config::Read( const std::string& filename )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Json::ParseFile( filename ) ;
|
||||||
|
}
|
||||||
|
catch ( Exception& e )
|
||||||
|
{
|
||||||
|
throw Error()
|
||||||
|
<< File( filename )
|
||||||
|
<< expt::ErrMsg("Cannot open config file ")
|
||||||
|
<< expt::Nested(e) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
|
@ -37,6 +37,9 @@ public :
|
||||||
Json& Get() ;
|
Json& Get() ;
|
||||||
void Save() ;
|
void Save() ;
|
||||||
|
|
||||||
|
private :
|
||||||
|
Json Read( const std::string& filename ) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
Json m_cfg ;
|
Json m_cfg ;
|
||||||
} ;
|
} ;
|
||||||
|
|
|
@ -73,7 +73,7 @@ int main( int argc, char **argv )
|
||||||
// save to config
|
// save to config
|
||||||
config.Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ;
|
config.Get().Add( "refresh_token", Json( token.RefreshToken() ) ) ;
|
||||||
assert( config.Get()["refresh_token"].Str() == token.RefreshToken() ) ;
|
assert( config.Get()["refresh_token"].Str() == token.RefreshToken() ) ;
|
||||||
config.Save( ) ;
|
config.Save() ;
|
||||||
|
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
@ -113,9 +113,11 @@ int main( int argc, char **argv )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OAuth2 token( refresh_token, client_id, client_secret ) ;
|
OAuth2 token( refresh_token, client_id, client_secret ) ;
|
||||||
Drive drive( token ) ;
|
Drive drive( token, config.Get() ) ;
|
||||||
|
|
||||||
drive.Update() ;
|
drive.Update() ;
|
||||||
|
|
||||||
|
config.Save() ;
|
||||||
}
|
}
|
||||||
catch ( gr::Exception& e )
|
catch ( gr::Exception& e )
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
|
|
||||||
namespace gr
|
namespace gr
|
||||||
{
|
{
|
||||||
const std::string feed_base = "https://docs.google.com/feeds/default/private/full" ;
|
const std::string feed_base = "https://docs.google.com/feeds/default/private/full" ;
|
||||||
|
const std::string feed_changes = "https://docs.google.com/feeds/default/private/changes" ;
|
||||||
const std::string feed_changes = "https://docs.google.com/feeds/default/private/changes" ;
|
const std::string feed_metadata = "https://docs.google.com/feeds/metadata/default" ;
|
||||||
|
|
||||||
const std::string root_href =
|
const std::string root_href =
|
||||||
"https://docs.google.com/feeds/default/private/full/folder%3Aroot" ;
|
"https://docs.google.com/feeds/default/private/full/folder%3Aroot" ;
|
||||||
|
|
|
@ -49,54 +49,50 @@
|
||||||
|
|
||||||
namespace gr {
|
namespace gr {
|
||||||
|
|
||||||
Drive::Drive( OAuth2& auth ) :
|
Drive::Drive( OAuth2& auth, const Json& state ) :
|
||||||
m_auth( auth )
|
m_auth( auth ),
|
||||||
|
m_state( state )
|
||||||
{
|
{
|
||||||
m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ;
|
m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ;
|
||||||
m_http_hdr.push_back( "GData-Version: 3.0" ) ;
|
m_http_hdr.push_back( "GData-Version: 3.0" ) ;
|
||||||
|
|
||||||
|
std::string prev_change_stamp ;
|
||||||
|
if ( m_state.Has( "change_stamp" ) )
|
||||||
|
prev_change_stamp = m_state["change_stamp"].Str() ;
|
||||||
|
|
||||||
http::Agent http ;
|
http::Agent http ;
|
||||||
|
http::XmlResponse xrsp ;
|
||||||
|
http.Get( feed_metadata, &xrsp, m_http_hdr ) ;
|
||||||
|
|
||||||
|
std::string change_stamp = xrsp.Response()["docs:largestChangestamp"]["@value"] ;
|
||||||
|
Trace( "change stamp is %1%", change_stamp ) ;
|
||||||
|
|
||||||
|
m_state.Add( "change_stamp", Json( change_stamp ) ) ;
|
||||||
|
|
||||||
ConstructDirTree( &http ) ;
|
ConstructDirTree( &http ) ;
|
||||||
|
|
||||||
http::XmlResponse xrsp ;
|
// http::ResponseLog log( "first-", ".xml", &xrsp ) ;
|
||||||
http::ResponseLog log( "first-", ".xml", &xrsp ) ;
|
|
||||||
|
|
||||||
std::string change_stamp ;
|
std::string uri = feed_base + "?showfolders=true&showroot=true" ;
|
||||||
|
/* if ( !change_stamp.empty() )
|
||||||
std::ifstream sfile( ".grive_state" ) ;
|
|
||||||
if ( sfile )
|
|
||||||
{
|
|
||||||
std::string state_str(
|
|
||||||
(std::istreambuf_iterator<char>( sfile )),
|
|
||||||
(std::istreambuf_iterator<char>()) ) ;
|
|
||||||
sfile.close() ;
|
|
||||||
|
|
||||||
Json state = Json::Parse( state_str ) ;
|
|
||||||
change_stamp = state["change_stamp"].Str() ;
|
|
||||||
Trace( "config change stamp is %1%", change_stamp ) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string uri = feed_changes + "?showfolders=true&showroot=true" ;
|
|
||||||
if ( !change_stamp.empty() )
|
|
||||||
{
|
{
|
||||||
int ichangestamp = std::atoi( change_stamp.c_str() ) + 1 ;
|
int ichangestamp = std::atoi( change_stamp.c_str() ) + 1 ;
|
||||||
uri = (boost::format( "%1%&start-index=%2%" ) % uri % ichangestamp ).str() ;
|
uri = (boost::format( "%1%&start-index=%2%" ) % uri % ichangestamp ).str() ;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
http.Get( uri, &log, m_http_hdr ) ;
|
http.Get( uri, &xrsp, m_http_hdr ) ;
|
||||||
xml::Node resp = xrsp.Response() ;
|
xml::Node resp = xrsp.Response() ;
|
||||||
|
|
||||||
m_resume_link = resp["link"].
|
m_resume_link = resp["link"].
|
||||||
Find( "@rel", "http://schemas.google.com/g/2005#resumable-create-media" )["@href"] ;
|
Find( "@rel", "http://schemas.google.com/g/2005#resumable-create-media" )["@href"] ;
|
||||||
|
|
||||||
change_stamp = resp["docs:largestChangestamp"]["@value"] ;
|
// change_stamp = resp["docs:largestChangestamp"]["@value"] ;
|
||||||
Trace( "change stamp is %1%", change_stamp ) ;
|
|
||||||
|
|
||||||
std::ofstream osfile( ".grive_state" ) ;
|
// std::ofstream osfile( ".grive_state" ) ;
|
||||||
Json state ;
|
// Json state ;
|
||||||
state.Add( "change_stamp", Json( change_stamp ) ) ;
|
// state.Add( "change_stamp", Json( change_stamp ) ) ;
|
||||||
osfile << state ;
|
// osfile << state ;
|
||||||
osfile.close() ;
|
// osfile.close() ;
|
||||||
|
|
||||||
bool has_next = false ;
|
bool has_next = false ;
|
||||||
do
|
do
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Collection.hh"
|
#include "Collection.hh"
|
||||||
|
|
||||||
|
#include "protocol/Json.hh"
|
||||||
#include "util/Exception.hh"
|
#include "util/Exception.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -46,10 +48,13 @@ public :
|
||||||
typedef std::vector<Collection>::iterator FolderListIterator ;
|
typedef std::vector<Collection>::iterator FolderListIterator ;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
Drive( OAuth2& auth ) ;
|
Drive( OAuth2& auth, const Json& state ) ;
|
||||||
~Drive( ) ;
|
~Drive( ) ;
|
||||||
|
|
||||||
void Update() ;
|
void Update() ;
|
||||||
|
void Sync() ;
|
||||||
|
|
||||||
|
Json State() const ;
|
||||||
|
|
||||||
struct Error : virtual Exception {} ;
|
struct Error : virtual Exception {} ;
|
||||||
|
|
||||||
|
@ -69,6 +74,8 @@ private :
|
||||||
|
|
||||||
FolderList m_coll ;
|
FolderList m_coll ;
|
||||||
std::vector<File*> m_files ;
|
std::vector<File*> m_files ;
|
||||||
|
|
||||||
|
Json m_state ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "Json.hh"
|
#include "Json.hh"
|
||||||
|
|
||||||
|
#include "util/StdioFile.hh"
|
||||||
|
|
||||||
#include <json/json_tokener.h>
|
#include <json/json_tokener.h>
|
||||||
#include <json/linkhash.h>
|
#include <json/linkhash.h>
|
||||||
|
|
||||||
|
@ -55,6 +57,27 @@ Json Json::Parse( const std::string& str )
|
||||||
return Json( json, NotOwned() ) ;
|
return Json( json, NotOwned() ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json Json::ParseFile( const std::string& filename )
|
||||||
|
{
|
||||||
|
StdioFile file( filename, "r" ) ;
|
||||||
|
struct json_tokener *tok = ::json_tokener_new() ;
|
||||||
|
|
||||||
|
struct json_object *json = 0 ;
|
||||||
|
|
||||||
|
char buf[80] ;
|
||||||
|
std::size_t count = 0 ;
|
||||||
|
|
||||||
|
while ( (count = file.Read( buf, sizeof(buf) ) ) > 0 )
|
||||||
|
json = ::json_tokener_parse_ex( tok, buf, count ) ;
|
||||||
|
|
||||||
|
if ( json == 0 )
|
||||||
|
throw Error() << expt::ErrMsg( ::json_tokener_errors[tok->err] ) ;
|
||||||
|
|
||||||
|
::json_tokener_free( tok ) ;
|
||||||
|
|
||||||
|
return Json( json, NotOwned() ) ;
|
||||||
|
}
|
||||||
|
|
||||||
Json::Json( struct json_object *json, NotOwned ) :
|
Json::Json( struct json_object *json, NotOwned ) :
|
||||||
m_json( json )
|
m_json( json )
|
||||||
{
|
{
|
||||||
|
@ -137,8 +160,7 @@ void Json::Add( const std::string& key, const Json& json )
|
||||||
::json_object_object_add( m_json, key.c_str(), json.m_json ) ;
|
::json_object_object_add( m_json, key.c_str(), json.m_json ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
bool Json::Bool() const
|
||||||
bool Json::As<bool>() const
|
|
||||||
{
|
{
|
||||||
assert( m_json != 0 ) ;
|
assert( m_json != 0 ) ;
|
||||||
return ::json_object_get_boolean( m_json ) ;
|
return ::json_object_get_boolean( m_json ) ;
|
||||||
|
@ -151,8 +173,7 @@ bool Json::Is<bool>() const
|
||||||
return ::json_object_is_type( m_json, json_type_boolean ) ;
|
return ::json_object_is_type( m_json, json_type_boolean ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
std::string Json::Str() const
|
||||||
std::string Json::As<std::string>() const
|
|
||||||
{
|
{
|
||||||
assert( m_json != 0 ) ;
|
assert( m_json != 0 ) ;
|
||||||
return ::json_object_get_string( m_json ) ;
|
return ::json_object_get_string( m_json ) ;
|
||||||
|
@ -165,8 +186,7 @@ bool Json::Is<std::string>() const
|
||||||
return ::json_object_is_type( m_json, json_type_string ) ;
|
return ::json_object_is_type( m_json, json_type_string ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
int Json::Int() const
|
||||||
int Json::As<int>() const
|
|
||||||
{
|
{
|
||||||
assert( m_json != 0 ) ;
|
assert( m_json != 0 ) ;
|
||||||
return ::json_object_get_int( m_json ) ;
|
return ::json_object_get_int( m_json ) ;
|
||||||
|
@ -191,8 +211,7 @@ Json::Type Json::DataType() const
|
||||||
return static_cast<Type>( ::json_object_get_type( m_json ) ) ;
|
return static_cast<Type>( ::json_object_get_type( m_json ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
Json::Object Json::AsObject() const
|
||||||
Json::Object Json::As<Json::Object>() const
|
|
||||||
{
|
{
|
||||||
Object result ;
|
Object result ;
|
||||||
|
|
||||||
|
@ -211,8 +230,7 @@ bool Json::Is<Json::Object>() const
|
||||||
return ::json_object_is_type( m_json, json_type_object ) ;
|
return ::json_object_is_type( m_json, json_type_object ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
Json::Array Json::AsArray() const
|
||||||
Json::Array Json::As<Json::Array>() const
|
|
||||||
{
|
{
|
||||||
std::size_t count = ::json_object_array_length( m_json ) ;
|
std::size_t count = ::json_object_array_length( m_json ) ;
|
||||||
Array result ;
|
Array result ;
|
||||||
|
@ -237,7 +255,7 @@ Json Json::FindInArray( const std::string& key, const std::string& value ) const
|
||||||
for ( std::size_t i = 0 ; i < count ; ++i )
|
for ( std::size_t i = 0 ; i < count ; ++i )
|
||||||
{
|
{
|
||||||
Json item( ::json_object_array_get_idx( m_json, i ) ) ;
|
Json item( ::json_object_array_get_idx( m_json, i ) ) ;
|
||||||
if ( item.Has(key) && item[key].As<std::string>() == value )
|
if ( item.Has(key) && item[key].Str() == value )
|
||||||
return item ;
|
return item ;
|
||||||
}
|
}
|
||||||
throw Error() << expt::ErrMsg( "cannot find " + key + " = " + value + " in array" ) ;
|
throw Error() << expt::ErrMsg( "cannot find " + key + " = " + value + " in array" ) ;
|
||||||
|
@ -256,10 +274,4 @@ bool Json::FindInArray( const std::string& key, const std::string& value, Json&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Json::Str() const
|
|
||||||
{
|
|
||||||
return As<std::string>() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public :
|
||||||
~Json( ) ;
|
~Json( ) ;
|
||||||
|
|
||||||
static Json Parse( const std::string& str ) ;
|
static Json Parse( const std::string& str ) ;
|
||||||
|
static Json ParseFile( const std::string& filename ) ;
|
||||||
|
|
||||||
Json operator[]( const std::string& key ) const ;
|
Json operator[]( const std::string& key ) const ;
|
||||||
Json operator[]( const std::size_t& idx ) const ;
|
Json operator[]( const std::size_t& idx ) const ;
|
||||||
|
@ -53,11 +54,12 @@ public :
|
||||||
|
|
||||||
void Swap( Json& other ) ;
|
void Swap( Json& other ) ;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T As() const ;
|
|
||||||
|
|
||||||
// As<std::string>() shortcut
|
|
||||||
std::string Str() const ;
|
std::string Str() const ;
|
||||||
|
int Int() const ;
|
||||||
|
double Double() const ;
|
||||||
|
bool Bool() const ;
|
||||||
|
Array AsArray() const ;
|
||||||
|
Object AsObject() const ;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool Is() const ;
|
bool Is() const ;
|
||||||
|
|
|
@ -65,8 +65,8 @@ void OAuth2::Auth( const std::string& auth_code )
|
||||||
http.Post( token_url, post, &resp ) ;
|
http.Post( token_url, post, &resp ) ;
|
||||||
|
|
||||||
Json jresp = resp.Response() ;
|
Json jresp = resp.Response() ;
|
||||||
m_access = jresp["access_token"].As<std::string>() ;
|
m_access = jresp["access_token"].Str() ;
|
||||||
m_refresh = jresp["refresh_token"].As<std::string>() ;
|
m_refresh = jresp["refresh_token"].Str() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OAuth2::MakeAuthURL(
|
std::string OAuth2::MakeAuthURL(
|
||||||
|
@ -81,8 +81,7 @@ std::string OAuth2::MakeAuthURL(
|
||||||
h.Escape( "https://www.googleapis.com/auth/userinfo.profile" ) + "+" +
|
h.Escape( "https://www.googleapis.com/auth/userinfo.profile" ) + "+" +
|
||||||
h.Escape( "https://docs.google.com/feeds/" ) + "+" +
|
h.Escape( "https://docs.google.com/feeds/" ) + "+" +
|
||||||
h.Escape( "https://docs.googleusercontent.com/" ) + "+" +
|
h.Escape( "https://docs.googleusercontent.com/" ) + "+" +
|
||||||
h.Escape( "https://spreadsheets.google.com/feeds/" ) + /*"+" +
|
h.Escape( "https://spreadsheets.google.com/feeds/" ) +
|
||||||
h.Escape( "https://www.googleapis.com/auth/drive.file/" ) +*/
|
|
||||||
"&redirect_uri=urn:ietf:wg:oauth:2.0:oob"
|
"&redirect_uri=urn:ietf:wg:oauth:2.0:oob"
|
||||||
"&response_type=code"
|
"&response_type=code"
|
||||||
"&client_id=" + client_id ;
|
"&client_id=" + client_id ;
|
||||||
|
@ -101,7 +100,7 @@ void OAuth2::Refresh( )
|
||||||
|
|
||||||
http.Post( token_url, post, &resp ) ;
|
http.Post( token_url, post, &resp ) ;
|
||||||
|
|
||||||
m_access = resp.Response()["access_token"].As<std::string>() ;
|
m_access = resp.Response()["access_token"].Str() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OAuth2::RefreshToken( ) const
|
std::string OAuth2::RefreshToken( ) const
|
||||||
|
|
Loading…
Reference in New Issue