mirror of https://github.com/vitalif/grive2
build up data structures for the collections
parent
e094e69d1a
commit
4001cbdbcc
|
@ -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 )
|
||||
|
|
|
@ -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 ) ;
|
||||
}
|
||||
}
|
|
@ -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 ) ;
|
||||
}
|
94
src/Drive.cc
94
src/Drive.cc
|
@ -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" ) )
|
||||
{
|
||||
|
|
19
src/Drive.hh
19
src/Drive.hh
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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 ) ;
|
||||
|
||||
|
|
Loading…
Reference in New Issue