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 "util/Path.hh"
|
||||
#include "util/OS.hh"
|
||||
#include "xml/Node.hh"
|
||||
#include "xml/NodeSet.hh"
|
||||
|
||||
#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(
|
||||
const std::string& title,
|
||||
const std::string& href ) :
|
||||
|
@ -99,6 +106,12 @@ bool Collection::IsCollection( const Json& entry )
|
|||
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 )
|
||||
{
|
||||
m_entry.Swap( coll.m_entry ) ;
|
||||
|
|
|
@ -34,11 +34,13 @@ class Collection
|
|||
{
|
||||
public :
|
||||
explicit Collection( const Json& entry ) ;
|
||||
explicit Collection( const xml::Node& entry ) ;
|
||||
Collection( const std::string& title, const std::string& href ) ;
|
||||
|
||||
// default copy ctor & op= are fine
|
||||
|
||||
static bool IsCollection( const Json& entry ) ;
|
||||
static bool IsCollection( const xml::Node& entry ) ;
|
||||
static std::string ParentHref( const Json& entry ) ;
|
||||
|
||||
std::string Title() const ;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "util/OS.hh"
|
||||
#include "util/Path.hh"
|
||||
#include "xml/Node.hh"
|
||||
#include "xml/NodeSet.hh"
|
||||
|
||||
// standard C++ library
|
||||
#include <algorithm>
|
||||
|
@ -56,19 +57,20 @@ Drive::Drive( OAuth2& auth ) :
|
|||
http::Agent http ;
|
||||
ConstructDirTree( &http ) ;
|
||||
|
||||
http::JsonResponse str ;
|
||||
http.Get( root_url + "?alt=json&showfolders=true", &str, m_http_hdr ) ;
|
||||
Json resp = str.Response() ;
|
||||
http::XmlResponse xrsp ;
|
||||
http::ResponseLog log( "first-", ".xml", &xrsp ) ;
|
||||
|
||||
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>() ;
|
||||
http.Get( root_url + "?showfolders=true", &log, m_http_hdr ) ;
|
||||
xml::Node resp = xrsp.Response() ;
|
||||
|
||||
m_resume_link = resp["link"].
|
||||
Find( "@rel", "http://schemas.google.com/g/2005#resumable-create-media" )["@href"] ;
|
||||
|
||||
bool has_next = false ;
|
||||
do
|
||||
{
|
||||
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
|
||||
for ( Json::Array::iterator i = entries.begin() ; i != entries.end() ; ++i )
|
||||
xml::NodeSet entries = resp["entry"] ;
|
||||
for ( xml::NodeSet::iterator i = entries.begin() ; i != entries.end() ; ++i )
|
||||
{
|
||||
if ( !Collection::IsCollection( *i ) )
|
||||
{
|
||||
|
@ -76,13 +78,13 @@ Drive::Drive( OAuth2& auth ) :
|
|||
}
|
||||
}
|
||||
|
||||
Json next ;
|
||||
has_next = resp["feed"]["link"].FindInArray( "rel", "next", next ) ;
|
||||
xml::NodeSet nss = resp["link"].Find( "@rel", "next" ) ;
|
||||
has_next = !nss.empty() ;
|
||||
|
||||
if ( has_next )
|
||||
{
|
||||
http.Get( next["href"].Str(), &str, m_http_hdr ) ;
|
||||
resp = str.Response() ;
|
||||
http.Get( nss["@href"], &xrsp, m_http_hdr ) ;
|
||||
resp = xrsp.Response() ;
|
||||
}
|
||||
} while ( has_next ) ;
|
||||
}
|
||||
|
@ -117,31 +119,36 @@ void Drive::ConstructDirTree( http::Agent *http )
|
|||
http::XmlResponse 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() ;
|
||||
// http::JsonResponse jrsp ;
|
||||
// http->Get( root_url + "/-/folder?alt=json", &jrsp, m_http_hdr ) ;
|
||||
// Json resp = jrsp.Response() ;
|
||||
|
||||
xml::Node resp = xml.Response() ;
|
||||
|
||||
assert( m_coll.empty() ) ;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
|
||||
xml::NodeSet entries = resp["entry"] ;
|
||||
|
||||
// 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 ) )
|
||||
m_coll.push_back( Collection( *i ) ) ;
|
||||
}
|
||||
|
||||
Json next ;
|
||||
if ( !resp["feed"]["link"].FindInArray( "rel", "next", next ) )
|
||||
// Json next ;
|
||||
// if ( !resp["feed"]["link"].FindInArray( "rel", "next", next ) )
|
||||
// break ;
|
||||
xml::NodeSet next = resp["link"].Find( "@rel", "next" ) ;
|
||||
if ( next.empty() )
|
||||
break ;
|
||||
|
||||
http->Get( next["href"].Str(), &jrsp, m_http_hdr ) ;
|
||||
resp = jrsp.Response() ;
|
||||
http->Get( next["@href"], &xml, m_http_hdr ) ;
|
||||
resp = xml.Response() ;
|
||||
}
|
||||
|
||||
// second, build up linkage between parent and child
|
||||
|
@ -171,10 +178,10 @@ void Drive::ConstructDirTree( http::Agent *http )
|
|||
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
|
||||
if ( entry.Has( "docs$suggestedFilename" ) )
|
||||
if ( !entry["docs:suggestedFilename"].empty() )
|
||||
{
|
||||
Entry file( entry ) ;
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ namespace http
|
|||
{
|
||||
class Agent ;
|
||||
}
|
||||
namespace xml
|
||||
{
|
||||
class Node ;
|
||||
}
|
||||
|
||||
class OAuth2 ;
|
||||
class Json ;
|
||||
|
@ -45,7 +49,7 @@ public :
|
|||
~Drive( ) ;
|
||||
|
||||
private :
|
||||
void UpdateFile( const Json& entry, http::Agent *http ) ;
|
||||
void UpdateFile( const xml::Node& entry, 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 )
|
||||
? node["href"].Str() : std::string() ;
|
||||
|
||||
// convert to lower case for easy comparison
|
||||
// convert to lower case for easy comparison
|
||||
std::transform(
|
||||
m_server_md5.begin(),
|
||||
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" ) ;
|
||||
for ( xml::NodeSet::iterator i = parents.begin() ; i != parents.end() ; ++i )
|
||||
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 )
|
||||
|
|
|
@ -416,6 +416,12 @@ std::size_t Node::size() const
|
|||
return m_ptr->Size() ;
|
||||
}
|
||||
|
||||
NodeSet Node::Children() const
|
||||
{
|
||||
assert( m_ptr != 0 ) ;
|
||||
return NodeSet( begin(), end() ) ;
|
||||
}
|
||||
|
||||
NodeSet Node::Attr() const
|
||||
{
|
||||
assert( m_ptr != 0 ) ;
|
||||
|
|
|
@ -75,9 +75,11 @@ public :
|
|||
iterator begin() const ;
|
||||
iterator end() const ;
|
||||
std::size_t size() const ;
|
||||
NodeSet Children() const ;
|
||||
|
||||
NodeSet Attr() const ;
|
||||
std::string Attr( const std::string& attr ) const ;
|
||||
bool HasAttr( const std::string& attr ) const ;
|
||||
|
||||
private :
|
||||
explicit Node( Impl *impl ) ;
|
||||
|
|
Loading…
Reference in New Issue