mirror of https://github.com/vitalif/grive2
Merge branch 'working'
commit
5d41ba7c1a
|
@ -4,8 +4,42 @@ cmake_minimum_required(VERSION 2.8)
|
|||
|
||||
include(FindOpenSSL)
|
||||
|
||||
###############################################################################
|
||||
# finding cppunit
|
||||
###############################################################################
|
||||
find_path( CPPUNIT_INCLUDE_DIR cppunit/TestFixture.h /usr/include
|
||||
/usr/local/include
|
||||
${CPPUNIT_PREFIX}/include )
|
||||
find_library( CPPUNIT_LIBRARY_DEBUG NAMES cppunit cppunit_dll
|
||||
PATHS /usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
${CPPUNIT_PREFIX}/lib
|
||||
PATH_SUFFIXES debug )
|
||||
|
||||
find_library( CPPUNIT_LIBRARY_RELEASE NAMES cppunit cppunit_dll
|
||||
PATHS /usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
${CPPUNIT_PREFIX}/lib
|
||||
PATH_SUFFIXES release )
|
||||
|
||||
set( CPPUNIT_LIBRARY debug ${CPPUNIT_LIBRARY_DEBUG}
|
||||
optimized ${CPPUNIT_LIBRARY_RELEASE} )
|
||||
|
||||
if ( CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY )
|
||||
message( STATUS "found cppunit" )
|
||||
set( CPPUNIT_FOUND TRUE )
|
||||
set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} )
|
||||
endif ( CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY )
|
||||
|
||||
###############################################################################
|
||||
|
||||
include_directories(
|
||||
${grive_SOURCE_DIR}/src
|
||||
${OPT_INCS}
|
||||
)
|
||||
|
||||
add_executable( grive
|
||||
|
@ -27,6 +61,8 @@ target_link_libraries( grive
|
|||
${OPENSSL_LIBRARIES}
|
||||
)
|
||||
|
||||
if ( CPPUNIT_FOUND )
|
||||
|
||||
add_executable( unittest
|
||||
test/UnitTest.cc
|
||||
src/util/DateTime.cc
|
||||
|
@ -35,5 +71,9 @@ add_executable( unittest
|
|||
)
|
||||
|
||||
target_link_libraries( unittest
|
||||
cppunit
|
||||
${CPPUNIT_LIBRARY}
|
||||
)
|
||||
|
||||
else ( CPPUNIT_FOUND )
|
||||
message( STATUS "skip building unittest" )
|
||||
endif ( CPPUNIT_FOUND )
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
// for debugging only
|
||||
#include <iostream>
|
||||
|
@ -46,8 +47,17 @@ 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 = Json::Parse( http::Get( root_url + "?alt=json&showfolders=true", m_http_hdr )) ;
|
||||
|
||||
std::cout << http::Get( "https://docs.google.com/feeds/metadata/default", m_http_hdr ) ;
|
||||
|
||||
Json resume_link ;
|
||||
if ( resp["feed"]["link"].FindInArray( "rel", "http://schemas.google.com/g/2005#resumable-create-media", resume_link ) )
|
||||
{
|
||||
m_resume_link = resume_link["href"].As<std::string>() ;
|
||||
std::cout << "resume_link = " << resume_link << std::endl ;
|
||||
}
|
||||
|
||||
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
|
||||
ConstructDirTree( entries ) ;
|
||||
|
||||
|
@ -157,7 +167,13 @@ void Drive::UpdateFile( const Json& entry )
|
|||
std::string filename = entry["docs$filename"]["$t"].Get() ;
|
||||
std::string url = entry["content"]["src"].Get() ;
|
||||
std::string parent_href = Parent( entry ) ;
|
||||
|
||||
/*
|
||||
Json kind_json ;
|
||||
if ( entry["category"].FindInArray( "scheme", "http://schemas.google.com/g/2005#kind", kind_json ) )
|
||||
{
|
||||
std::cout << filename << " kind = " << kind_json << std::endl ;
|
||||
}
|
||||
*/
|
||||
bool changed = true ;
|
||||
std::string path = "./" + filename ;
|
||||
|
||||
|
@ -190,7 +206,7 @@ void Drive::UpdateFile( const Json& entry )
|
|||
DateTime local = ifile ? os::FileMTime( path ) : DateTime() ;
|
||||
|
||||
// remote file is newer, download file
|
||||
if ( remote > local )
|
||||
if ( !ifile || remote > local )
|
||||
{
|
||||
std::cout << "downloading " << path << std::endl ;
|
||||
http::GetFile( url, path, m_http_hdr ) ;
|
||||
|
@ -199,7 +215,7 @@ std::cout << "downloading " << path << std::endl ;
|
|||
else
|
||||
{
|
||||
std::cout << "local " << filename << " is newer" << std::endl ;
|
||||
// UploadFile( entry ) ;
|
||||
UploadFile( entry ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,15 +223,59 @@ std::cout << "local " << filename << " is newer" << std::endl ;
|
|||
|
||||
void Drive::UploadFile( const Json& entry )
|
||||
{
|
||||
// std::cout << "entry:\n" << entry << std::endl ;
|
||||
|
||||
/* std::string meta =
|
||||
"<?xml version='1.0' encoding='UTF-8'?>"
|
||||
"<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:docs=\"http://schemas.google.com/docs/2007\">"
|
||||
"<category scheme=\"http://schemas.google.com/g/2005#kind\""
|
||||
"term=\"http://schemas.google.com/docs/2007#file\"/>"
|
||||
"<title>Test document</title>"
|
||||
"</entry>" ;
|
||||
*/
|
||||
http::Headers hdr( m_http_hdr ) ;
|
||||
// hdr.push_back( "Slug: Grive Document" ) ;
|
||||
// hdr.push_back( "Content-Type: application/atom+xml" ) ;
|
||||
hdr.push_back( "X-Upload-Content-Type: text/plain" ) ;
|
||||
hdr.push_back( "X-Upload-Content-Length: 1000" ) ;
|
||||
hdr.push_back( "Expect:" ) ;
|
||||
/*
|
||||
std::string resp = http::PostDataWithHeader(
|
||||
m_resume_link + "?convert=false",
|
||||
meta,
|
||||
hdr ) ;
|
||||
*/
|
||||
Json resume_link = entry["link"].FindInArray( "rel",
|
||||
"http://schemas.google.com/g/2005#resumable-edit-media" )["href"] ;
|
||||
std::cout << resume_link.As<std::string>() << std::endl ;
|
||||
|
||||
std::string resp = http::Put( resume_link.Get(), "", m_http_hdr ) ;
|
||||
std::string etag = entry["gd$etag"].As<std::string>() ;
|
||||
std::cout << "etag = " << etag << std::endl ;
|
||||
|
||||
std::cout << "resp " << resp ;
|
||||
hdr.push_back( "If-Match: " + etag ) ;
|
||||
std::string resp = http::Put( resume_link.Get(), "", hdr ) ;
|
||||
|
||||
std::cout << "resp " << resp << std::endl ;
|
||||
std::istringstream ss( resp ) ;
|
||||
|
||||
std::string line ;
|
||||
while ( std::getline( ss, line ) )
|
||||
{
|
||||
static const std::string location = "Location: " ;
|
||||
if ( line.substr( 0, location.size() ) == location )
|
||||
{
|
||||
std::string uplink = line.substr( location.size() ) ;
|
||||
uplink = uplink.substr( 0, uplink.size() -1 ) ;
|
||||
|
||||
std::string data( 1000, 'x' ) ;
|
||||
http::Headers uphdr ;
|
||||
uphdr.push_back( "Content-Type: text/plain" ) ;
|
||||
uphdr.push_back( "Content-Range: bytes 0-999/1000" ) ;
|
||||
uphdr.push_back( "Expect:" ) ;
|
||||
uphdr.push_back( "Accept:" ) ;
|
||||
|
||||
std::string resp = http::Put( uplink, data, uphdr ) ;
|
||||
std::cout << "put response = " << resp << std::endl ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -54,6 +54,8 @@ private :
|
|||
OAuth2& m_auth ;
|
||||
std::vector<std::string> m_http_hdr ;
|
||||
|
||||
std::string m_resume_link ;
|
||||
|
||||
FolderList m_coll ;
|
||||
Collection m_root ;
|
||||
} ;
|
||||
|
|
|
@ -51,12 +51,17 @@ size_t ReadCallback( void *ptr, std::size_t size, std::size_t nmemb, std::string
|
|||
assert( ptr != 0 ) ;
|
||||
assert( data != 0 ) ;
|
||||
|
||||
std::cout << "reading " << (size*nmemb) << " bytes " << data->size() << std::endl ;
|
||||
|
||||
std::size_t count = std::min( size * nmemb, data->size() ) ;
|
||||
if ( count > 0 )
|
||||
{
|
||||
std::memcpy( &(*data)[0], ptr, count ) ;
|
||||
std::memcpy( ptr, &(*data)[0], count ) ;
|
||||
data->erase( 0, count ) ;
|
||||
}
|
||||
|
||||
std::cout << "readed " << count << " bytes " << data->size() << std::endl ;
|
||||
|
||||
return count ;
|
||||
}
|
||||
|
||||
|
@ -162,14 +167,41 @@ std::string PostData( const std::string& url, const std::string& data, const Hea
|
|||
|
||||
std::string post_data = data ;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &post_data[0] ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_data.size() ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1 ) ;
|
||||
|
||||
DoCurl( curl ) ;
|
||||
return resp;
|
||||
}
|
||||
|
||||
std::string PostDataWithHeader( const std::string& url, const std::string& data, const Headers& hdr )
|
||||
{
|
||||
std::string resp ;
|
||||
CURL *curl = InitCurl( url, &resp, hdr ) ;
|
||||
|
||||
std::string post_data = data ;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &post_data[0] ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_data.size() ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 1L );
|
||||
|
||||
try
|
||||
{
|
||||
DoCurl( curl ) ;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cout << "response = " << resp << std::endl ;
|
||||
throw ;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
std::string PostFile( const std::string& url, const std::string& filename, const Headers& hdr )
|
||||
{
|
||||
std::string resp ;
|
||||
|
@ -186,15 +218,100 @@ std::string Put(
|
|||
|
||||
std::string put_data = data ;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
||||
// set common options
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 1L );
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &ReadCallback ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA , &put_data ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE, put_data.size() ) ;
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L ) ;
|
||||
|
||||
try
|
||||
{
|
||||
DoCurl( curl ) ;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cout << "response = " << resp << std::endl ;
|
||||
throw ;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
void Custom( const std::string& url, const std::string& host, const Headers& headers )
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if ( curl == 0 )
|
||||
throw std::bad_alloc() ;
|
||||
|
||||
// set common options
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L );
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L ) ;
|
||||
if ( curl_easy_perform( curl ) != 0 )
|
||||
throw std::runtime_error( "curl perform fail" ) ;
|
||||
|
||||
long sockextr;
|
||||
curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockextr);
|
||||
curl_socket_t sockfd = sockextr ;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 60 ;
|
||||
tv.tv_usec = 0 ;
|
||||
|
||||
fd_set infd, outfd, errfd;
|
||||
FD_ZERO(&infd);
|
||||
FD_ZERO(&outfd);
|
||||
FD_ZERO(&errfd);
|
||||
|
||||
FD_SET(sockfd, &errfd); /* always check for error */
|
||||
FD_SET(sockfd, &outfd);
|
||||
if ( select(sockfd + 1, &infd, &outfd, &errfd, &tv) == -1 )
|
||||
throw std::runtime_error( "select fail" ) ;
|
||||
|
||||
std::string path = url.substr( host.size() ) ;
|
||||
std::cout << ("PUT " + path + "HTTP/1.1") << std::endl ;
|
||||
|
||||
std::ostringstream req ;
|
||||
req << ("PUT " + path + "HTTP/1.1\n")
|
||||
<< "Host: " << "docs.google.com" << "\n" ;
|
||||
|
||||
for ( Headers::const_iterator i = headers.begin() ; i != headers.end() ; ++i )
|
||||
req << *i << '\n' ;
|
||||
|
||||
std::string data = "hahaha this is the new file!!!!!" ;
|
||||
req << "Content-Length: " << data.size() << '\n'
|
||||
<< "Content-Range: 0-" << data.size()-1 << '/' << data.size() << "\n\n\n"
|
||||
<< data ;
|
||||
|
||||
std::string reqstr = req.str() ;
|
||||
std::cout << "requesting: \n" << reqstr << std::endl ;
|
||||
|
||||
std::size_t iolen ;
|
||||
if ( curl_easy_send(curl, &reqstr[0], reqstr.size(), &iolen) != CURLE_OK )
|
||||
throw std::runtime_error( "cannot send" ) ;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
char buf[1024+1] ;
|
||||
FD_ZERO(&infd);
|
||||
FD_ZERO(&outfd);
|
||||
FD_ZERO(&errfd);
|
||||
|
||||
FD_SET(sockfd, &errfd); /* always check for error */
|
||||
FD_SET(sockfd, &infd);
|
||||
if ( select(sockfd + 1, &infd, &outfd, &errfd, &tv) == -1 )
|
||||
throw std::runtime_error( "select fail" ) ;
|
||||
|
||||
if ( curl_easy_recv(curl, buf, 1024, &iolen) != CURLE_OK )
|
||||
throw std::runtime_error( "cannot send" ) ;
|
||||
|
||||
buf[iolen] = '\0' ;
|
||||
std::cout << "read: " << buf << std::endl ;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Escape( const std::string& str )
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
|
|
|
@ -43,6 +43,10 @@ namespace gr { namespace http
|
|||
const std::string& url,
|
||||
const std::string& data,
|
||||
const Headers& hdr = Headers() ) ;
|
||||
std::string PostDataWithHeader(
|
||||
const std::string& url,
|
||||
const std::string& data,
|
||||
const Headers& hdr = Headers() ) ;
|
||||
std::string PostFile(
|
||||
const std::string& url,
|
||||
const std::string& filename,
|
||||
|
@ -53,6 +57,8 @@ namespace gr { namespace http
|
|||
const std::string& data,
|
||||
const Headers& hdr = Headers() ) ;
|
||||
|
||||
void Custom( const std::string& url, const std::string& host, const Headers& headers ) ;
|
||||
|
||||
std::string Escape( const std::string& str ) ;
|
||||
std::string Unescape( const std::string& str ) ;
|
||||
|
||||
|
|
Loading…
Reference in New Issue