diff --git a/CMakeLists.txt b/CMakeLists.txt index d2937a9..676643a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,13 +3,24 @@ cmake_minimum_required(VERSION 2.8) include(GNUInstallDirs) # Grive version. remember to update it for every new release! -set( GRIVE_VERSION "0.5.2-dev" ) +set( GRIVE_VERSION "0.5.2-dev" CACHE STRING "Grive version" ) +message(WARNING "Version to build: ${GRIVE_VERSION}") # common compile options add_definitions( -DVERSION="${GRIVE_VERSION}" ) add_definitions( -D_FILE_OFFSET_BITS=64 -std=c++0x ) +if ( APPLE ) + add_definitions( -Doff64_t=off_t ) +endif ( APPLE ) + +find_program( + HAVE_SYSTEMD systemd + PATHS /lib/systemd /usr/lib/systemd + NO_DEFAULT_PATH +) +if ( HAVE_SYSTEMD ) + add_subdirectory( systemd ) +endif( HAVE_SYSTEMD ) -add_subdirectory( systemd ) add_subdirectory( libgrive ) add_subdirectory( grive ) - \ No newline at end of file diff --git a/README.md b/README.md index 18d60a9..acb07ca 100644 --- a/README.md +++ b/README.md @@ -106,9 +106,36 @@ your folder. They need to be added explicitly to your Google Drive: go to the Google Drive website, right click on the file or folder and chose 'Add to My Drive'. -## Custom client id and secret +### Different OAuth2 client to workaround over quota and google approval issues -You can specify them with --id and --secret arguments or edit them at grive/src/main.cpp and rebuild. +Google recently started to restrict access for unapproved applications: +https://developers.google.com/drive/api/v3/about-auth?hl=ru + +Grive2 is currently awaiting approval but it seems it will take forever. +Also even if they approve it the default Client ID supplied with grive may +exceed quota and grive will then fail to sync. + +You can supply your own OAuth2 client credentials to work around these problems +by following these steps: + +1. Go to https://console.developers.google.com/apis/api/drive.googleapis.com +2. Choose a project (you might need to create one first) +3. Go to https://console.developers.google.com/apis/library/drive.googleapis.com and + "Enable" the Google Drive APIs +4. Go to https://console.cloud.google.com/apis/credentials and click "Create credentials > Help me choose" +5. In the "Find out what credentials you need" dialog, choose: + - Which API are you using: "Google Drive API" + - Where will you be calling the API from: "Other UI (...CLI...)" + - What data will you be accessing: "User Data" +6. In the next steps create a client id (name doesn't matter) and + setup the consent screen (defaults are ok, no need for any URLs) +7. The needed "Client ID" and "Client Secret" are either in the shown download + or can later found by clicking on the created credential on + https://console.developers.google.com/apis/credentials/ +8. When you change client ID/secret in an existing Grive folder you must first delete + the old `.grive` configuration file. +9. Call `grive -a --id --secret ` and follow the steps + to authenticate the OAuth2 client to allow it to access your drive folder. ## Installation @@ -133,13 +160,13 @@ There are also some optional dependencies: On a Debian/Ubuntu/Linux Mint machine just run the following command to install all these packages: - sudo apt-get install git cmake build-essential libgcrypt11-dev libyajl-dev \ + sudo apt-get install git cmake build-essential libgcrypt20-dev libyajl-dev \ libboost-all-dev libcurl4-openssl-dev libexpat1-dev libcppunit-dev binutils-dev \ debhelper zlib1g-dev dpkg-dev pkg-config Fedora: - sudo dnf install git cmake libgcrypt-devel gcc-c++ libstdc++ yajl-devel boost libcurl-devel expat-devel binutils zlib + sudo dnf install git cmake libgcrypt-devel gcc-c++ libstdc++ yajl-devel boost-devel libcurl-devel expat-devel binutils zlib FreeBSD: @@ -163,6 +190,14 @@ Grive uses cmake to build. Basic install sequence is make -j4 sudo make install +Alternativly you can define your own client_id and client_secret during build + + mkdir build + cd build + cmake .. "-DAPP_ID:STRING=" "-DAPP_SECRET:STRING=" + make -j4 + sudo make install + ## Version History ### Grive2 v0.5.2-dev diff --git a/grive/CMakeLists.txt b/grive/CMakeLists.txt index 0908380..ac5b781 100644 --- a/grive/CMakeLists.txt +++ b/grive/CMakeLists.txt @@ -20,6 +20,17 @@ target_link_libraries( grive_executable grive ) +set(DEFAULT_APP_ID "615557989097-i93d4d1ojpen0m0dso18ldr6orjkidgf.apps.googleusercontent.com") +set(DEFAULT_APP_SECRET "xiM8Apu_WuRRdheNelJcNtOD") +set(APP_ID ${DEFAULT_APP_ID} CACHE STRING "Application Id") +set(APP_SECRET ${DEFAULT_APP_SECRET} CACHE STRING "Application Secret") + +target_compile_definitions ( grive_executable + PRIVATE + -DAPP_ID="${APP_ID}" + -DAPP_SECRET="${APP_SECRET}" +) + set_target_properties( grive_executable PROPERTIES OUTPUT_NAME grive ) diff --git a/grive/src/main.cc b/grive/src/main.cc index 31a2b07..54d5560 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -46,8 +46,8 @@ #include #include -const std::string default_id = "615557989097-i93d4d1ojpen0m0dso18ldr6orjkidgf.apps.googleusercontent.com" ; -const std::string default_secret = "xiM8Apu_WuRRdheNelJcNtOD" ; +const std::string default_id = APP_ID ; +const std::string default_secret = APP_SECRET ; using namespace gr ; namespace po = boost::program_options; @@ -113,6 +113,7 @@ int Main( int argc, char **argv ) ( "auth,a", "Request authorization token" ) ( "id,i", po::value(), "Authentication ID") ( "secret,e", po::value(), "Authentication secret") + ( "print-url", "Only print url for request") ( "path,p", po::value(), "Path to working copy root") ( "dir,s", po::value(), "Single subdirectory to sync") ( "verbose,V", "Verbose mode. Enable more messages than normal.") @@ -174,23 +175,23 @@ int Main( int argc, char **argv ) http->SetProgressReporter( pb.get() ); } - std::string id = default_id; - std::string secret = default_secret; - - if( vm.count( "id" ) ) - { - id = vm["id"].as(); - } - - if( vm.count( "secret" ) ) - { - secret = vm["secret"].as(); - } - if ( vm.count( "auth" ) ) { + std::string id = vm.count( "id" ) > 0 + ? vm["id"].as() + : default_id ; + std::string secret = vm.count( "secret" ) > 0 + ? vm["secret"].as() + : default_secret ; + OAuth2 token( http.get(), id, secret ) ; + if ( vm.count("print-url") ) + { + std::cout << token.MakeAuthURL() << std::endl ; + return 0 ; + } + std::cout << "-----------------------\n" << "Please go to this URL and get an authentication code:\n\n" @@ -206,14 +207,20 @@ int Main( int argc, char **argv ) token.Auth( code ) ; // save to config + config.Set( "id", Val( id ) ) ; + config.Set( "secret", Val( secret ) ) ; config.Set( "refresh_token", Val( token.RefreshToken() ) ) ; config.Save() ; } std::string refresh_token ; + std::string id ; + std::string secret ; try { refresh_token = config.Get("refresh_token").Str() ; + id = config.Get("id").Str() ; + secret = config.Get("secret").Str() ; } catch ( Exception& e ) { diff --git a/libgrive/src/base/Feed.cc b/libgrive/src/base/Feed.cc index 0ea834d..0a4f51b 100644 --- a/libgrive/src/base/Feed.cc +++ b/libgrive/src/base/Feed.cc @@ -30,6 +30,10 @@ Feed::Feed( const std::string &url ): { } +Feed::~Feed() +{ +} + Feed::iterator Feed::begin() const { return m_entries.begin() ; diff --git a/libgrive/src/base/Feed.hh b/libgrive/src/base/Feed.hh index d43c68c..c12f507 100644 --- a/libgrive/src/base/Feed.hh +++ b/libgrive/src/base/Feed.hh @@ -41,6 +41,7 @@ public : public : Feed( const std::string& url ); virtual bool GetNext( http::Agent *http ) = 0 ; + virtual ~Feed() = 0 ; iterator begin() const ; iterator end() const ; diff --git a/libgrive/src/bfd/SymbolInfo.cc b/libgrive/src/bfd/SymbolInfo.cc index 5876cc0..cdb5d7c 100644 --- a/libgrive/src/bfd/SymbolInfo.cc +++ b/libgrive/src/bfd/SymbolInfo.cc @@ -49,9 +49,9 @@ SymbolInfo::SymbolInfo( ) m_impl->m_bfd = 0 ; m_impl->m_symbols = 0 ; m_impl->m_symbol_count = 0 ; - + bfd_init( ) ; - + // opening itself bfd *b = bfd_openr( "/proc/self/exe", 0 ) ; if ( b == NULL ) @@ -60,13 +60,13 @@ SymbolInfo::SymbolInfo( ) << bfd_errmsg( bfd_get_error() ) << std::endl ; return ; } - + if ( bfd_check_format( b, bfd_archive ) ) { bfd_close( b ) ; return ; } - + char **matching ; if ( !bfd_check_format_matches( b, bfd_object, &matching ) ) { @@ -78,7 +78,7 @@ SymbolInfo::SymbolInfo( ) std::cerr << bfd_get_filename( b ) << ": Matching formats: " ; for ( char **p = matching ; *p != 0 ; p++ ) std::cerr << " " << *p ; - + std::cerr << std::endl ; std::free( matching ) ; } @@ -107,7 +107,7 @@ struct SymbolInfo::BacktraceInfo const char *m_func_name ; unsigned int m_lineno ; unsigned int m_is_found ; - + static void Callback( bfd *abfd, asection *section, void* addr ) ; } ; @@ -117,17 +117,24 @@ void SymbolInfo::BacktraceInfo::Callback( bfd *abfd, asection *section, BacktraceInfo *info = (BacktraceInfo *)data ; if ((section->flags & SEC_ALLOC) == 0) return ; - - bfd_vma vma = bfd_get_section_vma(abfd, section); - + + // bfd_get_section_vma works up to 7b1cfbcf1a27951fb1b3a212995075dd6fdf985b, + // removed in 7c13bc8c91abf291f0206b6608b31955c5ea70d8 (binutils 2.33.1 or so) + // so it's substituted by its implementation to avoid checking for binutils + // version (which at least on Debian SID it's not that easy because the + // version.h is not included with the official package) + bfd_vma vma = section->vma; + unsigned long address = (unsigned long)(info->m_addr); if ( address < vma ) return; - - bfd_size_type size = bfd_section_size(abfd, section); + + // bfd_section_size changed between the two objects described above, + // same rationale applies + bfd_size_type size = section->size; if ( address > (vma + size)) return ; - + const SymbolInfo *pthis = info->m_pthis ; info->m_is_found = bfd_find_nearest_line( abfd, section, pthis->m_impl->m_symbols, @@ -149,7 +156,7 @@ void SymbolInfo::PrintTrace( void *addr, std::ostream& os, std::size_t idx ) { this, addr, 0, 0, 0, false } ; - + Dl_info sym ; bfd_map_over_sections( m_impl->m_bfd, &SymbolInfo::BacktraceInfo::Callback, @@ -165,7 +172,7 @@ if ( btinfo.m_is_found ) filename.erase( pos, std::strlen( SRC_DIR ) ) ; #endif os << "#" << idx << " " << addr << " " - << filename << ":" << btinfo.m_lineno + << filename << ":" << btinfo.m_lineno << " " << (btinfo.m_func_name != 0 ? Demangle(btinfo.m_func_name) : "" ) << std::endl ; diff --git a/libgrive/src/drive2/Feed2.cc b/libgrive/src/drive2/Feed2.cc index 8f3d234..037df37 100644 --- a/libgrive/src/drive2/Feed2.cc +++ b/libgrive/src/drive2/Feed2.cc @@ -36,6 +36,10 @@ Feed2::Feed2( const std::string& url ): { } +Feed2::~Feed2() +{ +} + bool Feed2::GetNext( http::Agent *http ) { if ( m_next.empty() ) diff --git a/libgrive/src/drive2/Feed2.hh b/libgrive/src/drive2/Feed2.hh index 4de411e..c5643f6 100644 --- a/libgrive/src/drive2/Feed2.hh +++ b/libgrive/src/drive2/Feed2.hh @@ -31,6 +31,7 @@ class Feed2: public Feed { public : Feed2( const std::string& url ) ; + ~Feed2() ; bool GetNext( http::Agent *http ) ; } ; diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index ba0c91e..c08972f 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -38,6 +38,10 @@ const std::string default_root_folder = "."; Config::Config( const po::variables_map& vm ) { + if ( vm.count( "id" ) > 0 ) + m_cmd.Add( "id", Val( vm["id"].as() ) ) ; + if ( vm.count( "secret" ) > 0 ) + m_cmd.Add( "secret", Val( vm["secret"].as() ) ) ; m_cmd.Add( "new-rev", Val(vm.count("new-rev") > 0) ) ; m_cmd.Add( "force", Val(vm.count("force") > 0 ) ) ; m_cmd.Add( "path", Val(vm.count("path") > 0