mirror of https://github.com/vitalif/grive2
Merge branch 'working'
commit
1ae7a18f63
|
@ -31,8 +31,7 @@
|
|||
namespace gr {
|
||||
|
||||
Collection::Collection( const Json& entry ) :
|
||||
m_title ( entry["title"]["$t"].As<std::string>() ),
|
||||
m_href ( entry["link"].FindInArray( "rel", "self" )["href"].As<std::string>() ),
|
||||
m_entry ( entry ),
|
||||
m_parent ( 0 )
|
||||
{
|
||||
}
|
||||
|
@ -40,8 +39,7 @@ Collection::Collection( const Json& entry ) :
|
|||
Collection::Collection(
|
||||
const std::string& title,
|
||||
const std::string& href ) :
|
||||
m_title ( title ),
|
||||
m_href ( href ),
|
||||
m_entry ( title, href ),
|
||||
m_parent( 0 )
|
||||
{
|
||||
}
|
||||
|
@ -53,14 +51,14 @@ std::string Collection::ParentHref( const Json& entry )
|
|||
node["href"].As<std::string>() : std::string() ;
|
||||
}
|
||||
|
||||
const std::string& Collection::Href() const
|
||||
std::string Collection::Href() const
|
||||
{
|
||||
return m_href ;
|
||||
return m_entry.SelfHref() ;
|
||||
}
|
||||
|
||||
const std::string& Collection::Title() const
|
||||
std::string Collection::Title() const
|
||||
{
|
||||
return m_title ;
|
||||
return m_entry.Title() ;
|
||||
}
|
||||
|
||||
const Collection* Collection::Parent() const
|
||||
|
@ -73,6 +71,11 @@ Collection* Collection::Parent()
|
|||
return m_parent ;
|
||||
}
|
||||
|
||||
std::string Collection::ParentHref() const
|
||||
{
|
||||
return m_entry.ParentHref() ;
|
||||
}
|
||||
|
||||
void Collection::AddChild( Collection *child )
|
||||
{
|
||||
assert( child != 0 ) ;
|
||||
|
@ -98,8 +101,7 @@ bool Collection::IsCollection( const Json& entry )
|
|||
|
||||
void Collection::Swap( Collection& coll )
|
||||
{
|
||||
m_title.swap( coll.m_title ) ;
|
||||
m_href.swap( coll.m_href ) ;
|
||||
m_entry.Swap( coll.m_entry ) ;
|
||||
std::swap( m_parent, coll.m_parent ) ;
|
||||
m_child.swap( coll.m_child ) ;
|
||||
m_leaves.swap( coll.m_leaves ) ;
|
||||
|
@ -107,7 +109,7 @@ void Collection::Swap( Collection& coll )
|
|||
|
||||
void Collection::CreateSubDir( const Path& prefix )
|
||||
{
|
||||
Path dir = prefix / m_title ;
|
||||
Path dir = prefix / m_entry.Title() ;
|
||||
os::MakeDir( dir ) ;
|
||||
|
||||
for ( std::vector<Collection*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
|
||||
|
@ -126,7 +128,7 @@ void Collection::ForEachFile(
|
|||
Path Collection::Dir() const
|
||||
{
|
||||
assert( m_parent != this ) ;
|
||||
return m_parent != 0 ? (m_parent->Dir() / m_title) : Path() ;
|
||||
return m_parent != 0 ? (m_parent->Dir() / m_entry.Title()) : Path() ;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Entry.hh"
|
||||
#include "util/Function.hh"
|
||||
|
||||
#include <string>
|
||||
|
@ -40,10 +41,11 @@ public :
|
|||
static bool IsCollection( const Json& entry ) ;
|
||||
static std::string ParentHref( const Json& entry ) ;
|
||||
|
||||
const std::string& Title() const ;
|
||||
const std::string& Href() const ;
|
||||
std::string Title() const ;
|
||||
std::string Href() const ;
|
||||
const Collection* Parent() const ;
|
||||
Collection* Parent() ;
|
||||
std::string ParentHref() const ;
|
||||
Path Dir() const ;
|
||||
|
||||
void AddChild( Collection *child ) ;
|
||||
|
@ -58,8 +60,7 @@ public :
|
|||
const std::string& prefix = "." ) ;
|
||||
|
||||
private :
|
||||
std::string m_title ;
|
||||
std::string m_href ;
|
||||
Entry m_entry ;
|
||||
|
||||
// not owned
|
||||
Collection *m_parent ;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "CommonUri.hh"
|
||||
#include "Entry.hh"
|
||||
|
||||
#include "http/HTTP.hh"
|
||||
#include "http/Agent.hh"
|
||||
#include "http/XmlResponse.hh"
|
||||
#include "protocol/Json.hh"
|
||||
#include "protocol/JsonResponse.hh"
|
||||
|
@ -71,7 +71,7 @@ Drive::Drive( OAuth2& auth ) :
|
|||
{
|
||||
if ( !Collection::IsCollection( *i ) )
|
||||
{
|
||||
UpdateFile( *i ) ;
|
||||
UpdateFile( *i, &http ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,6 @@ abc << xml.Response()["feed"] ;
|
|||
|
||||
assert( m_coll.empty() ) ;
|
||||
|
||||
std::map<std::string, std::string> parent_href ;
|
||||
while ( true )
|
||||
{
|
||||
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
|
||||
|
@ -134,15 +133,8 @@ abc << xml.Response()["feed"] ;
|
|||
for ( Json::Array::const_iterator i = entries.begin() ; i != entries.end() ; ++i )
|
||||
{
|
||||
if ( Collection::IsCollection( *i ) )
|
||||
{
|
||||
m_coll.push_back( Collection( *i ) ) ;
|
||||
parent_href.insert(
|
||||
std::make_pair(
|
||||
m_coll.back().Href(),
|
||||
Collection::ParentHref( *i ) ) ) ;
|
||||
}
|
||||
}
|
||||
assert( m_coll.size() == parent_href.size() ) ;
|
||||
|
||||
Json next ;
|
||||
if ( !resp["feed"]["link"].FindInArray( "rel", "next", next ) )
|
||||
|
@ -156,14 +148,11 @@ abc << xml.Response()["feed"] ;
|
|||
std::sort( m_coll.begin(), m_coll.end(), SortCollectionByHref() ) ;
|
||||
for ( FolderListIterator i = m_coll.begin() ; i != m_coll.end() ; ++i )
|
||||
{
|
||||
assert( parent_href.find( i->Href() ) != parent_href.end() ) ;
|
||||
std::string parent = parent_href[i->Href()] ;
|
||||
|
||||
if ( parent.empty() )
|
||||
if ( i->ParentHref().empty() )
|
||||
m_root.AddChild( &*i ) ;
|
||||
else
|
||||
{
|
||||
FolderListIterator pit = FindFolder( parent ) ;
|
||||
FolderListIterator pit = FindFolder( i->ParentHref() ) ;
|
||||
if ( pit != m_coll.end() )
|
||||
{
|
||||
// it shouldn't happen, just in case
|
||||
|
@ -182,7 +171,7 @@ abc << xml.Response()["feed"] ;
|
|||
m_root.CreateSubDir( Path() ) ;
|
||||
}
|
||||
|
||||
void Drive::UpdateFile( const Json& entry )
|
||||
void Drive::UpdateFile( const Json& entry, http::Agent *http )
|
||||
{
|
||||
// only handle uploaded files
|
||||
if ( entry.Has( "docs$suggestedFilename" ) )
|
||||
|
@ -193,18 +182,18 @@ void Drive::UpdateFile( const Json& entry )
|
|||
Path path = Path() / file.Filename() ;
|
||||
|
||||
// determine which folder the file belongs to
|
||||
if ( !file.Parent().empty() )
|
||||
if ( !file.ParentHref().empty() )
|
||||
{
|
||||
FolderListIterator pit = FindFolder( file.Parent() ) ;
|
||||
FolderListIterator pit = FindFolder( file.ParentHref() ) ;
|
||||
if ( pit != m_coll.end() )
|
||||
path = pit->Dir() / file.Filename() ;
|
||||
}
|
||||
|
||||
|
||||
// compare checksum first if file exists
|
||||
std::ifstream ifile( path.Str().c_str(), std::ios::binary | std::ios::in ) ;
|
||||
if ( ifile && file.ServerMD5() == crypt::MD5(ifile.rdbuf()) )
|
||||
changed = false ;
|
||||
|
||||
|
||||
// if the checksum is different, file is changed and we need to update
|
||||
if ( changed )
|
||||
{
|
||||
|
@ -215,7 +204,7 @@ void Drive::UpdateFile( const Json& entry )
|
|||
if ( !ifile || remote > local )
|
||||
{
|
||||
std::cout << "downloading " << path << std::endl ;
|
||||
file.Download( path, m_http_hdr ) ;
|
||||
file.Download( http, path, m_http_hdr ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -223,7 +212,7 @@ std::cout << "local " << path << " is newer" << std::endl ;
|
|||
// re-reading the file
|
||||
ifile.seekg(0) ;
|
||||
|
||||
if ( !file.Upload( ifile.rdbuf(), m_http_hdr ) )
|
||||
if ( !file.Upload( http, ifile.rdbuf(), m_http_hdr ) )
|
||||
std::cout << path << " is read only" << std::endl ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public :
|
|||
~Drive( ) ;
|
||||
|
||||
private :
|
||||
void UpdateFile( const Json& entry ) ;
|
||||
void UpdateFile( const Json& entry, http::Agent *http ) ;
|
||||
|
||||
void ConstructDirTree( http::Agent *http ) ;
|
||||
|
||||
|
|
|
@ -46,6 +46,16 @@ Entry::Entry( const Json& entry )
|
|||
Update( entry ) ;
|
||||
}
|
||||
|
||||
Entry::Entry( const xml::Node& n )
|
||||
{
|
||||
}
|
||||
|
||||
Entry::Entry( const std::string& title, const std::string& href ) :
|
||||
m_title( title ),
|
||||
m_self_href( href )
|
||||
{
|
||||
}
|
||||
|
||||
void Entry::Update( const Json& entry )
|
||||
{
|
||||
m_title = entry["title"]["$t"].Str() ;
|
||||
|
@ -53,8 +63,9 @@ void Entry::Update( const Json& entry )
|
|||
m_filename = entry.Has("docs$suggestedFilename") ?
|
||||
entry["docs$suggestedFilename"]["$t"].Str() : "" ;
|
||||
|
||||
m_href = entry["content"]["src"].Str() ;
|
||||
m_parent = Parent( entry ) ;
|
||||
m_content_src = entry["content"]["src"].Str() ;
|
||||
m_self_href = entry["link"].FindInArray( "rel", "self" )["href"].Str() ;
|
||||
m_parent_href = Parent( entry ) ;
|
||||
m_server_modified = DateTime( entry["updated"]["$t"].Str() ) ;
|
||||
m_etag = entry["gd$etag"].Str() ;
|
||||
|
||||
|
@ -112,26 +123,25 @@ DateTime Entry::ServerModified() const
|
|||
return m_server_modified ;
|
||||
}
|
||||
|
||||
std::string Entry::Href() const
|
||||
std::string Entry::SelfHref() const
|
||||
{
|
||||
return m_href ;
|
||||
return m_self_href ;
|
||||
}
|
||||
|
||||
std::string Entry::Parent() const
|
||||
std::string Entry::ParentHref() const
|
||||
{
|
||||
return m_parent ;
|
||||
return m_parent_href ;
|
||||
}
|
||||
|
||||
void Entry::Download( const Path& file, const http::Headers& auth ) const
|
||||
void Entry::Download( gr::http::Agent* http, const Path& file, const http::Headers& auth ) const
|
||||
{
|
||||
gr::Download dl( file.Str(), Download::NoChecksum() ) ;
|
||||
http::Agent http ;
|
||||
long r = http.Get( m_href, &dl, auth ) ;
|
||||
long r = http->Get( m_content_src, &dl, auth ) ;
|
||||
if ( r <= 400 )
|
||||
os::SetFileTime( file, m_server_modified ) ;
|
||||
}
|
||||
|
||||
bool Entry::Upload( std::streambuf *file, const http::Headers& auth )
|
||||
bool Entry::Upload( gr::http::Agent* http, std::streambuf *file, const http::Headers& auth )
|
||||
{
|
||||
// upload link missing means that file is read only
|
||||
if ( m_upload_link.empty() )
|
||||
|
@ -160,10 +170,9 @@ bool Entry::Upload( std::streambuf *file, const http::Headers& auth )
|
|||
hdr.push_back( "Expect:" ) ;
|
||||
|
||||
http::StringResponse str ;
|
||||
http::Agent http ;
|
||||
http.Put( m_upload_link, meta, &str, hdr ) ;
|
||||
http->Put( m_upload_link, meta, &str, hdr ) ;
|
||||
|
||||
std::string uplink = http.RedirLocation() ;
|
||||
std::string uplink = http->RedirLocation() ;
|
||||
|
||||
// parse the header and find "Location"
|
||||
http::Headers uphdr ;
|
||||
|
@ -171,7 +180,7 @@ bool Entry::Upload( std::streambuf *file, const http::Headers& auth )
|
|||
uphdr.push_back( "Accept:" ) ;
|
||||
|
||||
http::XmlResponse xml ;
|
||||
http.Put( uplink, data, &xml, uphdr ) ;
|
||||
http->Put( uplink, data, &xml, uphdr ) ;
|
||||
|
||||
std::cout << xml.Response() << std::endl ;
|
||||
|
||||
|
@ -199,4 +208,21 @@ std::cout << root_url + "/" + m_resource_id + "?delete=true" << std::endl ;
|
|||
http->Custom( "DELETE", root_url + "/" + m_resource_id + "?delete=true", &str, hdr ) ;
|
||||
}
|
||||
|
||||
void Entry::Swap( Entry& e )
|
||||
{
|
||||
m_title.swap( e.m_title ) ;
|
||||
m_filename.swap( e.m_filename ) ;
|
||||
m_kind.swap( e.m_kind ) ;
|
||||
m_server_md5.swap( e.m_server_md5 ) ;
|
||||
m_etag.swap( e.m_etag ) ;
|
||||
m_resource_id.swap( e.m_resource_id ) ;
|
||||
|
||||
m_self_href.swap( e.m_self_href ) ;
|
||||
m_parent_href.swap( e.m_parent_href ) ;
|
||||
m_content_src.swap( e.m_content_src ) ;
|
||||
m_upload_link.swap( e.m_upload_link ) ;
|
||||
|
||||
m_server_modified.Swap( e.m_server_modified ) ;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -21,13 +21,18 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "http/HTTP.hh"
|
||||
#include "http/Agent.hh"
|
||||
#include "util/DateTime.hh"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace gr {
|
||||
|
||||
namespace xml
|
||||
{
|
||||
class Node ;
|
||||
}
|
||||
|
||||
class Json ;
|
||||
class OAuth2 ;
|
||||
class Path ;
|
||||
|
@ -37,6 +42,8 @@ class Entry
|
|||
public :
|
||||
explicit Entry( const Path& file ) ;
|
||||
explicit Entry( const Json& entry ) ;
|
||||
explicit Entry( const xml::Node& n ) ;
|
||||
Entry( const std::string& title, const std::string& href ) ;
|
||||
|
||||
std::string Title() const ;
|
||||
std::string Filename() const ;
|
||||
|
@ -47,13 +54,15 @@ public :
|
|||
std::string ResourceID() const ;
|
||||
std::string ETag() const ;
|
||||
|
||||
std::string Href() const ;
|
||||
std::string Parent() const ;
|
||||
std::string SelfHref() const ;
|
||||
std::string ParentHref() const ;
|
||||
|
||||
void Download( const Path& file, const http::Headers& auth ) const ;
|
||||
bool Upload( std::streambuf *file, const http::Headers& auth ) ;
|
||||
void Download( gr::http::Agent* http, const Path& file, const http::Headers& auth ) const ;
|
||||
bool Upload( gr::http::Agent* http, std::streambuf *file, const http::Headers& auth ) ;
|
||||
void Delete( gr::http::Agent* http, const gr::http::Headers& auth ) ;
|
||||
|
||||
void Swap( Entry& e ) ;
|
||||
|
||||
private :
|
||||
void Update( const Json& entry ) ;
|
||||
static std::string Parent( const Json& entry ) ;
|
||||
|
@ -66,8 +75,9 @@ private :
|
|||
std::string m_etag ;
|
||||
std::string m_resource_id ;
|
||||
|
||||
std::string m_href ;
|
||||
std::string m_parent ;
|
||||
std::string m_self_href ;
|
||||
std::string m_content_src ;
|
||||
std::string m_parent_href ;
|
||||
std::string m_upload_link ;
|
||||
|
||||
DateTime m_server_modified ;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "HTTP.hh"
|
||||
#include "Agent.hh"
|
||||
|
||||
#include "Download.hh"
|
||||
#include "Exception.hh"
|
||||
|
@ -71,6 +71,8 @@ struct Agent::Impl
|
|||
CURL *curl ;
|
||||
std::string location ;
|
||||
char error[CURL_ERROR_SIZE] ;
|
||||
|
||||
std::string log_prefix ;
|
||||
} ;
|
||||
|
||||
Agent::Agent() :
|
||||
|
@ -90,6 +92,15 @@ Agent::~Agent()
|
|||
::curl_easy_cleanup( m_pimpl->curl );
|
||||
}
|
||||
|
||||
void Agent::SetLogFile( const std::string& prefix )
|
||||
{
|
||||
m_pimpl->log_prefix = prefix ;
|
||||
}
|
||||
|
||||
std::string Agent::LogFilename() const
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t Agent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Agent *pthis )
|
||||
{
|
||||
char *str = reinterpret_cast<char*>(ptr) ;
|
|
@ -41,7 +41,8 @@ public :
|
|||
Agent() ;
|
||||
~Agent() ;
|
||||
|
||||
// TODO: implement put from file, or some callback interface to pull data
|
||||
void SetLogFile( const std::string& prefix ) ;
|
||||
|
||||
long Put(
|
||||
const std::string& url,
|
||||
const std::string& data,
|
||||
|
@ -75,6 +76,7 @@ private :
|
|||
static std::size_t Receive( void* ptr, size_t size, size_t nmemb, Receivable *recv ) ;
|
||||
|
||||
void SetHeader( const http::Headers& hdr ) ;
|
||||
std::string LogFilename() const ;
|
||||
|
||||
private :
|
||||
struct Impl ;
|
|
@ -22,7 +22,7 @@
|
|||
#include "JsonResponse.hh"
|
||||
#include "Json.hh"
|
||||
|
||||
#include "http/HTTP.hh"
|
||||
#include "http/Agent.hh"
|
||||
|
||||
// for debugging
|
||||
#include <iostream>
|
||||
|
|
|
@ -129,4 +129,10 @@ bool DateTime::operator<=( const DateTime& dt ) const
|
|||
return !( *this > dt ) ;
|
||||
}
|
||||
|
||||
void DateTime::Swap( DateTime& dt )
|
||||
{
|
||||
std::swap( m_sec, dt.m_sec ) ;
|
||||
std::swap( m_nsec, dt.m_nsec ) ;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -47,6 +47,8 @@ public :
|
|||
bool operator<( const DateTime& dt ) const ;
|
||||
bool operator<=( const DateTime& dt ) const ;
|
||||
|
||||
void Swap( DateTime& dt ) ;
|
||||
|
||||
private :
|
||||
std::time_t m_sec ;
|
||||
unsigned long m_nsec ;
|
||||
|
|
Loading…
Reference in New Issue