diff --git a/src/Drive.cc b/src/Drive.cc index c5887be..a8c1b6e 100644 --- a/src/Drive.cc +++ b/src/Drive.cc @@ -34,7 +34,7 @@ Drive::Drive( OAuth2& auth ) : m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ; m_http_hdr.push_back( "GData-Version: 3.0" ) ; - Json resp( HttpGet( "https://docs.google.com/feeds/default/private/full?alt=json", m_http_hdr ) ) ; + Json resp = Json::Parse(HttpGet( "https://docs.google.com/feeds/default/private/full?alt=json", m_http_hdr )) ; /* Json::Object map = resp["feed"]["id"].As() ; for ( Json::Object::iterator i = map.begin() ; i != map.end() ; ++i ) diff --git a/src/Json.cc b/src/Json.cc index e5c5c74..e99b3c3 100644 --- a/src/Json.cc +++ b/src/Json.cc @@ -23,16 +23,43 @@ #include #include -#include +#include +#include #include namespace gr { -Json::Json( const std::string& str ) : - m_json( ::json_tokener_parse( str.c_str() ) ) +Json::Json( ) : + m_json( ::json_object_new_object() ) { if ( m_json == 0 ) + throw std::runtime_error( "cannot create json object" ) ; +} + +template <> +Json::Json( const std::string& str ) : + m_json( ::json_object_new_string( str.c_str() ) ) +{ + if ( m_json == 0 ) + throw std::runtime_error( "cannot create json string \"" + str + "\"" ) ; + + // paranoid check + assert( ::json_object_get_string( m_json ) == str ) ; +} + +Json Json::Parse( const std::string& str ) +{ + struct json_object *json = ::json_tokener_parse( str.c_str() ) ; + if ( json == 0 ) throw std::runtime_error( "json parse error" ) ; + + return Json( json, NotOwned() ) ; +} + +Json::Json( struct json_object *json, NotOwned ) : + m_json( json ) +{ + assert( json != 0 ) ; } Json::Json( struct json_object *json ) : @@ -80,12 +107,36 @@ Json Json::operator[]( const std::string& key ) const return Json( j ) ; } +Json Json::operator[]( const std::size_t& idx ) const +{ + assert( m_json != 0 ) ; + + struct json_object *j = ::json_object_array_get_idx( m_json, idx ) ; + if ( j == 0 ) + { + std::ostringstream ss ; + ss << "index " << idx << " is not found in array" ; + throw std::runtime_error( ss.str() ) ; + } + + return Json( j ) ; +} + bool Json::Has( const std::string& key ) const { assert( m_json != 0 ) ; return ::json_object_object_get( m_json, key.c_str() ) != 0 ; } +void Json::Add( const std::string& key, const Json& json ) +{ + assert( m_json != 0 ) ; + assert( json.m_json != 0 ) ; + + ::json_object_get( json.m_json ) ; + ::json_object_object_add( m_json, key.c_str(), json.m_json ) ; +} + template <> std::string Json::As() const { diff --git a/src/Json.hh b/src/Json.hh index 6900674..b80c641 100644 --- a/src/Json.hh +++ b/src/Json.hh @@ -34,11 +34,17 @@ public : typedef std::vector Array ; public : - Json( const std::string& str ) ; + template + explicit Json( const T& val ) ; + + Json() ; Json( const Json& rhs ) ; ~Json( ) ; + static Json Parse( const std::string& str ) ; + Json operator[]( const std::string& key ) const ; + Json operator[]( const std::size_t& idx ) const ; Json& operator=( const Json& rhs ) ; void Swap( Json& other ) ; @@ -50,6 +56,7 @@ public : bool Is() const ; bool Has( const std::string& key ) const ; + void Add( const std::string& key, const Json& json ) ; friend std::ostream& operator<<( std::ostream& os, const Json& json ) ; @@ -60,6 +67,9 @@ public : private : Json( struct json_object *json ) ; + struct NotOwned {} ; + Json( struct json_object *json, NotOwned ) ; + private : struct json_object *m_json ; } ; diff --git a/src/OAuth2.cc b/src/OAuth2.cc index c4d1774..71b0ae5 100644 --- a/src/OAuth2.cc +++ b/src/OAuth2.cc @@ -49,7 +49,7 @@ void OAuth2::Auth( const std::string& auth_code ) "&redirect_uri=" + "urn:ietf:wg:oauth:2.0:oob" + "&grant_type=authorization_code" ; - Json resp( HttpPostData( token_url, post ) ) ; + Json resp = Json::Parse( HttpPostData( token_url, post ) ) ; m_access = resp["access_token"].As() ; m_refresh = resp["refresh_token"].As() ; } @@ -78,7 +78,7 @@ void OAuth2::Refresh( ) "&client_secret=" + client_secret + "&grant_type=refresh_token" ; - Json resp( HttpPostData( token_url, post ) ) ; + Json resp = Json::Parse( HttpPostData( token_url, post ) ) ; m_access = resp["access_token"].As() ; } diff --git a/src/main.cc b/src/main.cc index 1e612db..b5178b0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -19,14 +19,54 @@ #include "OAuth2.hh" #include "Drive.hh" +#include "Json.hh" +#include #include - +#include #include +#include + +namespace gr +{ + const std::string& ConfigFilename() + { + static const char *env_cfg = ::getenv( "GR_CONFIG" ) ; + static const std::string filename = + (env_cfg != 0) ? env_cfg : std::string( ::getenv( "HOME") ) + "/.grive" ; + + return filename ; + } + + Json ReadConfig() + { + std::cout << ConfigFilename() << std::endl ; + std::ifstream ifile( ConfigFilename().c_str() ) ; + + if ( ifile ) + { + std::string cfg_str( + (std::istreambuf_iterator( ifile )), + (std::istreambuf_iterator()) ) ; + + return Json::Parse( cfg_str ) ; + } + else + return Json() ; + } + + void SaveConfig( const Json& config ) + { + std::ofstream ofile( ConfigFilename().c_str() ) ; + ofile << config ; + } +} int main( int argc, char **argv ) { using namespace gr ; + + Json config = ReadConfig() ; int c ; while ((c = getopt (argc, argv, "ac:")) != -1) @@ -35,24 +75,31 @@ int main( int argc, char **argv ) { case 'a' : { - std::cout << - OAuth2::MakeAuthURL( "22314510474.apps.googleusercontent.com" ) << std::endl ; - return 0 ; - } - - case 'c' : - { + std::cout + << "Please go to this URL and enter the code:\n" + << OAuth2::MakeAuthURL( "22314510474.apps.googleusercontent.com" ) + << std::endl ; + + std::string code ; + std::cin >> code ; + OAuth2 token ; - token.Auth( optarg ) ; + token.Auth( code ) ; // print the refresh token an exist - std::cout << token.RefreshToken() << std::endl ; - return 0 ; + std::cout << "got refresh token: " << token.RefreshToken() << std::endl ; + + // save to config + config.Add( "refresh_token", Json( token.RefreshToken() ) ) ; + assert( config["refresh_token"].As() == token.RefreshToken() ) ; + SaveConfig( config ) ; + + break ; } } } - OAuth2 token( getenv( "GR_REFRESH_CODE" ) ) ; + OAuth2 token( config["refresh_token"].As() ) ; Drive drive( token ) ; return 0 ;