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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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