use XML for downloading files and folders

pull/40/head
Matchman Green 2012-05-12 17:38:41 +08:00
parent 444bf61c73
commit b2d0bf2ba8
7 changed files with 71 additions and 27 deletions

View File

@ -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 ) ;

View File

@ -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 ;

View File

@ -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 ) ;

View File

@ -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 ) ;

View File

@ -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 )

View File

@ -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 ) ;

View File

@ -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 ) ;