mirror of https://github.com/vitalif/grive2
use XML for downloading files and folders
parent
444bf61c73
commit
b2d0bf2ba8
|
@ -22,6 +22,8 @@
|
||||||
#include "protocol/Json.hh"
|
#include "protocol/Json.hh"
|
||||||
#include "util/Path.hh"
|
#include "util/Path.hh"
|
||||||
#include "util/OS.hh"
|
#include "util/OS.hh"
|
||||||
|
#include "xml/Node.hh"
|
||||||
|
#include "xml/NodeSet.hh"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
@ -36,6 +38,11 @@ Collection::Collection( const Json& entry ) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collection::Collection( const xml::Node& entry ) :
|
||||||
|
m_entry ( entry ),
|
||||||
|
m_parent ( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
Collection::Collection(
|
Collection::Collection(
|
||||||
const std::string& title,
|
const std::string& title,
|
||||||
const std::string& href ) :
|
const std::string& href ) :
|
||||||
|
@ -99,6 +106,12 @@ bool Collection::IsCollection( const Json& entry )
|
||||||
node["label"].As<std::string>() == "folder" ;
|
node["label"].As<std::string>() == "folder" ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Collection::IsCollection( const xml::Node& entry )
|
||||||
|
{
|
||||||
|
return entry["category"].Find( "@scheme", "http://schemas.google.com/g/2005#kind" )["@label"].front().Value()
|
||||||
|
== "folder" ;
|
||||||
|
}
|
||||||
|
|
||||||
void Collection::Swap( Collection& coll )
|
void Collection::Swap( Collection& coll )
|
||||||
{
|
{
|
||||||
m_entry.Swap( coll.m_entry ) ;
|
m_entry.Swap( coll.m_entry ) ;
|
||||||
|
|
|
@ -34,11 +34,13 @@ class Collection
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
explicit Collection( const Json& entry ) ;
|
explicit Collection( const Json& entry ) ;
|
||||||
|
explicit Collection( const xml::Node& entry ) ;
|
||||||
Collection( const std::string& title, const std::string& href ) ;
|
Collection( const std::string& title, const std::string& href ) ;
|
||||||
|
|
||||||
// default copy ctor & op= are fine
|
// default copy ctor & op= are fine
|
||||||
|
|
||||||
static bool IsCollection( const Json& entry ) ;
|
static bool IsCollection( const Json& entry ) ;
|
||||||
|
static bool IsCollection( const xml::Node& entry ) ;
|
||||||
static std::string ParentHref( const Json& entry ) ;
|
static std::string ParentHref( const Json& entry ) ;
|
||||||
|
|
||||||
std::string Title() const ;
|
std::string Title() const ;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "util/OS.hh"
|
#include "util/OS.hh"
|
||||||
#include "util/Path.hh"
|
#include "util/Path.hh"
|
||||||
#include "xml/Node.hh"
|
#include "xml/Node.hh"
|
||||||
|
#include "xml/NodeSet.hh"
|
||||||
|
|
||||||
// standard C++ library
|
// standard C++ library
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -56,19 +57,20 @@ Drive::Drive( OAuth2& auth ) :
|
||||||
http::Agent http ;
|
http::Agent http ;
|
||||||
ConstructDirTree( &http ) ;
|
ConstructDirTree( &http ) ;
|
||||||
|
|
||||||
http::JsonResponse str ;
|
http::XmlResponse xrsp ;
|
||||||
http.Get( root_url + "?alt=json&showfolders=true", &str, m_http_hdr ) ;
|
http::ResponseLog log( "first-", ".xml", &xrsp ) ;
|
||||||
Json resp = str.Response() ;
|
|
||||||
|
|
||||||
Json resume_link ;
|
http.Get( root_url + "?showfolders=true", &log, m_http_hdr ) ;
|
||||||
if ( resp["feed"]["link"].FindInArray( "rel", "http://schemas.google.com/g/2005#resumable-create-media", resume_link ) )
|
xml::Node resp = xrsp.Response() ;
|
||||||
m_resume_link = resume_link["href"].As<std::string>() ;
|
|
||||||
|
|
||||||
|
m_resume_link = resp["link"].
|
||||||
|
Find( "@rel", "http://schemas.google.com/g/2005#resumable-create-media" )["@href"] ;
|
||||||
|
|
||||||
bool has_next = false ;
|
bool has_next = false ;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
|
xml::NodeSet entries = resp["entry"] ;
|
||||||
for ( Json::Array::iterator i = entries.begin() ; i != entries.end() ; ++i )
|
for ( xml::NodeSet::iterator i = entries.begin() ; i != entries.end() ; ++i )
|
||||||
{
|
{
|
||||||
if ( !Collection::IsCollection( *i ) )
|
if ( !Collection::IsCollection( *i ) )
|
||||||
{
|
{
|
||||||
|
@ -76,13 +78,13 @@ Drive::Drive( OAuth2& auth ) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Json next ;
|
xml::NodeSet nss = resp["link"].Find( "@rel", "next" ) ;
|
||||||
has_next = resp["feed"]["link"].FindInArray( "rel", "next", next ) ;
|
has_next = !nss.empty() ;
|
||||||
|
|
||||||
if ( has_next )
|
if ( has_next )
|
||||||
{
|
{
|
||||||
http.Get( next["href"].Str(), &str, m_http_hdr ) ;
|
http.Get( nss["@href"], &xrsp, m_http_hdr ) ;
|
||||||
resp = str.Response() ;
|
resp = xrsp.Response() ;
|
||||||
}
|
}
|
||||||
} while ( has_next ) ;
|
} while ( has_next ) ;
|
||||||
}
|
}
|
||||||
|
@ -117,31 +119,36 @@ void Drive::ConstructDirTree( http::Agent *http )
|
||||||
http::XmlResponse xml ;
|
http::XmlResponse xml ;
|
||||||
http::ResponseLog log( "dir-", ".xml", &xml ) ;
|
http::ResponseLog log( "dir-", ".xml", &xml ) ;
|
||||||
|
|
||||||
http->Get( root_url + "/-/folder?showroot=true&max-results=10", &log, m_http_hdr ) ;
|
http->Get( root_url + "/-/folder?max-results=10", &log, m_http_hdr ) ;
|
||||||
|
|
||||||
|
// http::JsonResponse jrsp ;
|
||||||
|
// http->Get( root_url + "/-/folder?alt=json", &jrsp, m_http_hdr ) ;
|
||||||
|
// Json resp = jrsp.Response() ;
|
||||||
|
|
||||||
|
xml::Node resp = xml.Response() ;
|
||||||
|
|
||||||
http::JsonResponse jrsp ;
|
|
||||||
http->Get( root_url + "/-/folder?alt=json", &jrsp, m_http_hdr ) ;
|
|
||||||
Json resp = jrsp.Response() ;
|
|
||||||
|
|
||||||
assert( m_coll.empty() ) ;
|
assert( m_coll.empty() ) ;
|
||||||
|
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
|
xml::NodeSet entries = resp["entry"] ;
|
||||||
|
|
||||||
// first, get all collections from the query result
|
// first, get all collections from the query result
|
||||||
for ( Json::Array::const_iterator i = entries.begin() ; i != entries.end() ; ++i )
|
for ( xml::NodeSet::iterator i = entries.begin() ; i != entries.end() ; ++i )
|
||||||
{
|
{
|
||||||
if ( Collection::IsCollection( *i ) )
|
if ( Collection::IsCollection( *i ) )
|
||||||
m_coll.push_back( Collection( *i ) ) ;
|
m_coll.push_back( Collection( *i ) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json next ;
|
// Json next ;
|
||||||
if ( !resp["feed"]["link"].FindInArray( "rel", "next", next ) )
|
// if ( !resp["feed"]["link"].FindInArray( "rel", "next", next ) )
|
||||||
|
// break ;
|
||||||
|
xml::NodeSet next = resp["link"].Find( "@rel", "next" ) ;
|
||||||
|
if ( next.empty() )
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
http->Get( next["href"].Str(), &jrsp, m_http_hdr ) ;
|
http->Get( next["@href"], &xml, m_http_hdr ) ;
|
||||||
resp = jrsp.Response() ;
|
resp = xml.Response() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// second, build up linkage between parent and child
|
// second, build up linkage between parent and child
|
||||||
|
@ -171,10 +178,10 @@ void Drive::ConstructDirTree( http::Agent *http )
|
||||||
m_root.CreateSubDir( Path() ) ;
|
m_root.CreateSubDir( Path() ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Drive::UpdateFile( const Json& entry, http::Agent *http )
|
void Drive::UpdateFile( const xml::Node& entry, http::Agent *http )
|
||||||
{
|
{
|
||||||
// only handle uploaded files
|
// only handle uploaded files
|
||||||
if ( entry.Has( "docs$suggestedFilename" ) )
|
if ( !entry["docs:suggestedFilename"].empty() )
|
||||||
{
|
{
|
||||||
Entry file( entry ) ;
|
Entry file( entry ) ;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@ namespace http
|
||||||
{
|
{
|
||||||
class Agent ;
|
class Agent ;
|
||||||
}
|
}
|
||||||
|
namespace xml
|
||||||
|
{
|
||||||
|
class Node ;
|
||||||
|
}
|
||||||
|
|
||||||
class OAuth2 ;
|
class OAuth2 ;
|
||||||
class Json ;
|
class Json ;
|
||||||
|
@ -45,7 +49,7 @@ public :
|
||||||
~Drive( ) ;
|
~Drive( ) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
void UpdateFile( const Json& entry, http::Agent *http ) ;
|
void UpdateFile( const xml::Node& entry, http::Agent *http ) ;
|
||||||
|
|
||||||
void ConstructDirTree( http::Agent *http ) ;
|
void ConstructDirTree( http::Agent *http ) ;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ void Entry::Update( const Json& entry )
|
||||||
FindInArray( "rel", "http://schemas.google.com/g/2005#resumable-edit-media", node )
|
FindInArray( "rel", "http://schemas.google.com/g/2005#resumable-edit-media", node )
|
||||||
? node["href"].Str() : std::string() ;
|
? node["href"].Str() : std::string() ;
|
||||||
|
|
||||||
// convert to lower case for easy comparison
|
// convert to lower case for easy comparison
|
||||||
std::transform(
|
std::transform(
|
||||||
m_server_md5.begin(),
|
m_server_md5.begin(),
|
||||||
m_server_md5.end(),
|
m_server_md5.end(),
|
||||||
|
@ -111,6 +111,16 @@ void Entry::Update( const xml::Node& n )
|
||||||
xml::NodeSet parents = n["link"].Find( "@rel", "http://schemas.google.com/docs/2007#parent" ) ;
|
xml::NodeSet parents = n["link"].Find( "@rel", "http://schemas.google.com/docs/2007#parent" ) ;
|
||||||
for ( xml::NodeSet::iterator i = parents.begin() ; i != parents.end() ; ++i )
|
for ( xml::NodeSet::iterator i = parents.begin() ; i != parents.end() ; ++i )
|
||||||
m_parent_hrefs.push_back( (*i)["@href"] ) ;
|
m_parent_hrefs.push_back( (*i)["@href"] ) ;
|
||||||
|
|
||||||
|
if ( !m_parent_hrefs.empty() )
|
||||||
|
m_parent_href = m_parent_hrefs.front() ;
|
||||||
|
|
||||||
|
// convert to lower case for easy comparison
|
||||||
|
std::transform(
|
||||||
|
m_server_md5.begin(),
|
||||||
|
m_server_md5.end(),
|
||||||
|
m_server_md5.begin(),
|
||||||
|
tolower ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Entry::Parent( const Json& entry )
|
std::string Entry::Parent( const Json& entry )
|
||||||
|
|
|
@ -416,6 +416,12 @@ std::size_t Node::size() const
|
||||||
return m_ptr->Size() ;
|
return m_ptr->Size() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeSet Node::Children() const
|
||||||
|
{
|
||||||
|
assert( m_ptr != 0 ) ;
|
||||||
|
return NodeSet( begin(), end() ) ;
|
||||||
|
}
|
||||||
|
|
||||||
NodeSet Node::Attr() const
|
NodeSet Node::Attr() const
|
||||||
{
|
{
|
||||||
assert( m_ptr != 0 ) ;
|
assert( m_ptr != 0 ) ;
|
||||||
|
|
|
@ -75,9 +75,11 @@ public :
|
||||||
iterator begin() const ;
|
iterator begin() const ;
|
||||||
iterator end() const ;
|
iterator end() const ;
|
||||||
std::size_t size() const ;
|
std::size_t size() const ;
|
||||||
|
NodeSet Children() const ;
|
||||||
|
|
||||||
NodeSet Attr() const ;
|
NodeSet Attr() const ;
|
||||||
std::string Attr( const std::string& attr ) const ;
|
std::string Attr( const std::string& attr ) const ;
|
||||||
|
bool HasAttr( const std::string& attr ) const ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
explicit Node( Impl *impl ) ;
|
explicit Node( Impl *impl ) ;
|
||||||
|
|
Loading…
Reference in New Issue