build up data structures for the collections

pull/40/head
Matchman Green 2012-04-26 23:40:38 +08:00
parent e094e69d1a
commit 4001cbdbcc
14 changed files with 322 additions and 25 deletions

View File

@ -8,6 +8,7 @@ add_executable( grive
src/main.cc
src/OAuth2.cc
src/Drive.cc
src/Collection.cc
src/protocol/HTTP.cc
src/protocol/Json.cc
src/protocol/Download.cc )

113
src/Collection.cc Normal file
View File

@ -0,0 +1,113 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Collection.hh"
#include "protocol/Json.hh"
// OS specific library
#include <sys/stat.h>
#include <sys/types.h>
// for debugging
#include <iostream>
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_parent ( Parent( entry ) )
{
std::cout << "title: " << m_title << " {" << m_parent << "}" << std::endl ;
}
Collection::Collection(
const std::string& title,
const std::string& href,
const std::string& parent ) :
m_title ( title ),
m_href ( href ),
m_parent( parent )
{
}
std::string Collection::Parent( const Json& entry )
{
Json node ;
return entry["link"].FindInArray( "rel", "http://schemas.google.com/docs/2007#parent", node ) ?
node["href"].As<std::string>() : std::string() ;
}
const std::string& Collection::Href() const
{
return m_href ;
}
const std::string& Collection::Title() const
{
return m_title ;
}
const std::string& Collection::Parent() const
{
return m_parent ;
}
void Collection::AddChild( Collection *child )
{
m_child.push_back( child ) ;
}
bool Collection::IsCollection( const Json& entry )
{
Json node ;
return
entry["category"].FindInArray( "scheme", "http://schemas.google.com/g/2005#kind", node ) &&
node["label"].As<std::string>() == "folder" ;
}
void Collection::Swap( Collection& coll )
{
m_title.swap( coll.m_title ) ;
m_href.swap( coll.m_href ) ;
m_child.swap( coll.m_child ) ;
}
void Collection::CreateSubDir( const std::string& prefix )
{
std::string dir = prefix + m_title ;
std::cout << dir << std::endl ;
mkdir( dir.c_str(), 0700 ) ;
for ( std::vector<Collection*>::iterator i = m_child.begin() ; i != m_child.end() ; ++i )
{
(*i)->CreateSubDir( prefix + m_title + "/" ) ;
}
}
} // end of namespace
namespace std
{
void swap( gr::Collection& c1, gr::Collection& c2 )
{
c1.Swap( c2 ) ;
}
}

66
src/Collection.hh Normal file
View File

@ -0,0 +1,66 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <string>
#include <vector>
namespace gr {
class Json ;
class Collection
{
public :
explicit Collection( const Json& entry ) ;
Collection( const std::string& title, const std::string& href, const std::string& parent ) ;
// default copy ctor & op= are fine
static bool IsCollection( const Json& entry ) ;
const std::string& Title() const ;
const std::string& Href() const ;
const std::string& Parent() const ;
void AddChild( Collection *child ) ;
void Swap( Collection& coll ) ;
void CreateSubDir( const std::string& prefix ) ;
private :
static std::string Parent( const Json& entry ) ;
private :
std::string m_title ;
std::string m_href ;
std::string m_parent ;
// not owned
std::vector<Collection*> m_child ;
} ;
} // end of namespace
namespace std
{
void swap( gr::Collection& c1, gr::Collection& c2 ) ;
}

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
@ -23,18 +23,23 @@
#include "protocol/Json.hh"
#include "OAuth2.hh"
// dependent libraries
#include <openssl/evp.h>
// standard C++ library
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <sstream>
// for debugging only
#include <iostream>
namespace gr {
const std::string root_url = "https://docs.google.com/feeds/default/private/full" ;
std::string MD5( std::streambuf *file )
{
char buf[64 * 1024] ;
@ -60,26 +65,89 @@ std::string MD5( std::streambuf *file )
}
Drive::Drive( OAuth2& auth ) :
m_auth( auth )
m_auth( auth ),
m_root( "", "https://docs.google.com/feeds/default/private/full/folder%3Aroot", "" )
{
m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ;
m_http_hdr.push_back( "GData-Version: 3.0" ) ;
Json resp = Json::Parse(HttpGet( "https://docs.google.com/feeds/default/private/full?alt=json", m_http_hdr )) ;
/* Json::Object map = resp["feed"]["id"].As<Json::Object>() ;
for ( Json::Object::iterator i = map.begin() ; i != map.end() ; ++i )
{
std::cout << i->first << "\t" << i->second.DataType() << std::endl ;
}*/
Json::Array a = resp["feed"]["entry"].As<Json::Array>() ;
for ( Json::Array::iterator i = a.begin() ; i != a.end() ; ++i )
Json resp = Json::Parse(HttpGet( root_url + "?alt=json&showfolders=true", m_http_hdr )) ;
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
ConstructDirTree( entries ) ;
for ( Json::Array::iterator i = entries.begin() ; i != entries.end() ; ++i )
{
DownloadEntry( *i ) ;
// DownloadEntry( *i ) ;
}
}
Drive::~Drive( )
{
}
std::string Drive::Kind( const Json& entry )
{
Json node ;
return entry["category"].FindInArray( "scheme", "http://schemas.google.com/g/2005#kind", node ) ?
node["label"].As<std::string>() : std::string() ;
}
struct SortCollectionByHref
{
bool operator()( const Collection& c1, const Collection& c2 ) const
{
return c1.Href() < c2.Href() ;
}
} ;
Drive::FolderListIterator Drive::FindFolder( const std::string& href )
{
// try to find the parent by its href
std::vector<Collection>::iterator it =
std::lower_bound(
m_coll.begin(),
m_coll.end(),
Collection( "", href, "" ),
SortCollectionByHref() ) ;
return it != m_coll.end() && it->Href() == href ? it : m_coll.end() ;
}
void Drive::ConstructDirTree( const std::vector<Json>& entries )
{
// first, get all collections from the query result
for ( Json::Array::const_iterator i = entries.begin() ; i != entries.end() ; ++i )
{
if ( Collection::IsCollection( *i ) )
m_coll.push_back( Collection( *i ) ) ;
}
// second, build up linkage between parent and child
std::sort( m_coll.begin(), m_coll.end(), SortCollectionByHref() ) ;
for ( FolderListIterator i = m_coll.begin() ; i != m_coll.end() ; ++i )
{
if ( i->Parent().empty() )
m_root.AddChild( &*i ) ;
else
{
FolderListIterator pit = FindFolder( i->Parent() ) ;
if ( pit != m_coll.end() )
pit->AddChild( &*i ) ;
}
}
// lastly, iterating from the root, create the directories in the local file system
m_root.CreateSubDir( "." ) ;
}
std::string Drive::Parent( const Json& entry )
{
Json node ;
return entry["link"].FindInArray( "ref", "http://schemas.google.com/docs/2007#parent", node ) ?
node["href"].As<std::string>() : std::string() ;
}
void Drive::DownloadEntry( const Json& entry )
{
// Json::Object map = entry.As<Json::Object>() ;
@ -88,6 +156,8 @@ void Drive::DownloadEntry( const Json& entry )
// std::cout << i->first << "\t" << i->second.DataType() << std::endl ;
// }
Parent( entry ) ;
// only handle uploaded files
if ( entry.Has( "docs$filename" ) )
{

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
@ -19,6 +19,8 @@
#pragma once
#include "Collection.hh"
#include <string>
#include <vector>
@ -29,15 +31,30 @@ class Json ;
class Drive
{
public :
typedef std::vector<Collection> FolderList ;
typedef std::vector<Collection>::iterator FolderListIterator ;
public :
Drive( OAuth2& auth ) ;
~Drive( ) ;
private :
void DownloadEntry( const Json& entry ) ;
std::string Parent( const Json& entry ) ;
void ConstructDirTree( const std::vector<Json>& entries ) ;
static std::string Kind( const Json& entry ) ;
FolderListIterator FindFolder( const std::string& href ) ;
private :
OAuth2& m_auth ;
std::vector<std::string> m_http_hdr ;
FolderList m_coll ;
Collection m_root ;
} ;
} // end of namespace

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,

View File

@ -4,8 +4,8 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
@ -59,7 +59,7 @@ Json Json::Parse( const std::string& str )
Json::Json( struct json_object *json, NotOwned ) :
m_json( json )
{
assert( json != 0 ) ;
assert( m_json != 0 ) ;
}
Json::Json( struct json_object *json ) :
@ -79,7 +79,8 @@ Json::Json( const Json& rhs ) :
Json::~Json( )
{
assert( m_json != 0 ) ;
::json_object_put( m_json ) ;
if ( m_json != 0 )
::json_object_put( m_json ) ;
}
Json& Json::operator=( const Json& rhs )
@ -216,4 +217,31 @@ bool Json::Is<Json::Array>() const
return ::json_object_is_type( m_json, json_type_array ) ;
}
Json Json::FindInArray( const std::string& key, const std::string& value ) const
{
std::size_t count = ::json_object_array_length( m_json ) ;
for ( std::size_t i = 0 ; i < count ; ++i )
{
Json item( ::json_object_array_get_idx( m_json, i ) ) ;
if ( item.Has(key) && item[key].As<std::string>() == value )
return item ;
}
throw std::runtime_error( "cannot find " + key + " = " + value + " in array" ) ;
}
bool Json::FindInArray( const std::string& key, const std::string& value, Json& result ) const
{
try
{
result = FindInArray( key, value ) ;
return true ;
}
catch ( std::runtime_error& )
{
return false ;
}
}
}

View File

@ -4,7 +4,7 @@
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
@ -57,6 +57,8 @@ public :
bool Has( const std::string& key ) const ;
void Add( const std::string& key, const Json& json ) ;
Json FindInArray( const std::string& key, const std::string& value ) const ;
bool FindInArray( const std::string& key, const std::string& value, Json& result ) const ;
friend std::ostream& operator<<( std::ostream& os, const Json& json ) ;