Skip to content

Commit b67ee0f

Browse files
author
Massimo Gengarelli
committed
Merge head with main repo
2 parents 5bda75a + 60f1e87 commit b67ee0f

File tree

6 files changed

+250
-26
lines changed

6 files changed

+250
-26
lines changed

CMakeLists.txt

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,42 @@ cmake_minimum_required(VERSION 2.8)
44

55
include(FindOpenSSL)
66

7+
###############################################################################
8+
# finding cppunit
9+
###############################################################################
10+
find_path( CPPUNIT_INCLUDE_DIR cppunit/TestFixture.h /usr/include
11+
/usr/local/include
12+
${CPPUNIT_PREFIX}/include )
13+
find_library( CPPUNIT_LIBRARY_DEBUG NAMES cppunit cppunit_dll
14+
PATHS /usr/lib
15+
/usr/lib64
16+
/usr/local/lib
17+
/usr/local/lib64
18+
${CPPUNIT_PREFIX}/lib
19+
PATH_SUFFIXES debug )
20+
21+
find_library( CPPUNIT_LIBRARY_RELEASE NAMES cppunit cppunit_dll
22+
PATHS /usr/lib
23+
/usr/lib64
24+
/usr/local/lib
25+
/usr/local/lib64
26+
${CPPUNIT_PREFIX}/lib
27+
PATH_SUFFIXES release )
28+
29+
set( CPPUNIT_LIBRARY debug ${CPPUNIT_LIBRARY_DEBUG}
30+
optimized ${CPPUNIT_LIBRARY_RELEASE} )
31+
32+
if ( CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY )
33+
message( STATUS "found cppunit" )
34+
set( CPPUNIT_FOUND TRUE )
35+
set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} )
36+
endif ( CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY )
37+
38+
###############################################################################
39+
740
include_directories(
841
${grive_SOURCE_DIR}/src
42+
${OPT_INCS}
943
)
1044

1145
file(GLOB DRIVE_HEADERS
@@ -51,16 +85,20 @@ set_target_properties(grive PROPERTIES
5185
SOVERSION 0 VERSION 0.0.1
5286
)
5387

54-
add_executable( unittest
55-
test/UnitTest.cc
56-
src/util/DateTime.cc
57-
test/util/DateTimeTest.cc
58-
test/util/FunctionTest.cc
59-
)
88+
if ( CPPUNIT_FOUND )
89+
add_executable( unittest
90+
test/UnitTest.cc
91+
src/util/DateTime.cc
92+
test/util/DateTimeTest.cc
93+
test/util/FunctionTest.cc
94+
)
6095

61-
target_link_libraries( unittest
62-
cppunit
63-
)
96+
target_link_libraries( unittest
97+
${CPPUNIT_LIBRARY}
98+
)
99+
else ( CPPUNIT_FOUND )
100+
message( STATUS "skip building unittest" )
101+
endif ( CPPUNIT_FOUND )
64102

65103

66104
## Install targets

src/drive/Drive.cc

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <cassert>
3232
#include <fstream>
3333
#include <map>
34+
#include <sstream>
3435

3536
// for debugging only
3637
#include <iostream>
@@ -46,8 +47,17 @@ Drive::Drive( OAuth2& auth ) :
4647
m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ;
4748
m_http_hdr.push_back( "GData-Version: 3.0" ) ;
4849

49-
5050
Json resp = Json::Parse( http::Get( root_url + "?alt=json&showfolders=true", m_http_hdr )) ;
51+
52+
std::cout << http::Get( "https://docs.google.com/feeds/metadata/default", m_http_hdr ) ;
53+
54+
Json resume_link ;
55+
if ( resp["feed"]["link"].FindInArray( "rel", "http://schemas.google.com/g/2005#resumable-create-media", resume_link ) )
56+
{
57+
m_resume_link = resume_link["href"].As<std::string>() ;
58+
std::cout << "resume_link = " << resume_link << std::endl ;
59+
}
60+
5161
Json::Array entries = resp["feed"]["entry"].As<Json::Array>() ;
5262
ConstructDirTree( entries ) ;
5363

@@ -157,7 +167,13 @@ void Drive::UpdateFile( const Json& entry )
157167
std::string filename = entry["docs$filename"]["$t"].Get() ;
158168
std::string url = entry["content"]["src"].Get() ;
159169
std::string parent_href = Parent( entry ) ;
160-
170+
/*
171+
Json kind_json ;
172+
if ( entry["category"].FindInArray( "scheme", "http://schemas.google.com/g/2005#kind", kind_json ) )
173+
{
174+
std::cout << filename << " kind = " << kind_json << std::endl ;
175+
}
176+
*/
161177
bool changed = true ;
162178
std::string path = "./" + filename ;
163179

@@ -190,7 +206,7 @@ void Drive::UpdateFile( const Json& entry )
190206
DateTime local = ifile ? os::FileMTime( path ) : DateTime() ;
191207

192208
// remote file is newer, download file
193-
if ( remote > local )
209+
if ( !ifile || remote > local )
194210
{
195211
std::cout << "downloading " << path << std::endl ;
196212
http::GetFile( url, path, m_http_hdr ) ;
@@ -199,23 +215,67 @@ std::cout << "downloading " << path << std::endl ;
199215
else
200216
{
201217
std::cout << "local " << filename << " is newer" << std::endl ;
202-
// UploadFile( entry ) ;
218+
UploadFile( entry ) ;
203219
}
204220
}
205221
}
206222
}
207223

208224
void Drive::UploadFile( const Json& entry )
209225
{
210-
// std::cout << "entry:\n" << entry << std::endl ;
211-
226+
/* std::string meta =
227+
"<?xml version='1.0' encoding='UTF-8'?>"
228+
"<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:docs=\"http://schemas.google.com/docs/2007\">"
229+
"<category scheme=\"http://schemas.google.com/g/2005#kind\""
230+
"term=\"http://schemas.google.com/docs/2007#file\"/>"
231+
"<title>Test document</title>"
232+
"</entry>" ;
233+
*/
234+
http::Headers hdr( m_http_hdr ) ;
235+
// hdr.push_back( "Slug: Grive Document" ) ;
236+
// hdr.push_back( "Content-Type: application/atom+xml" ) ;
237+
hdr.push_back( "X-Upload-Content-Type: text/plain" ) ;
238+
hdr.push_back( "X-Upload-Content-Length: 1000" ) ;
239+
hdr.push_back( "Expect:" ) ;
240+
/*
241+
std::string resp = http::PostDataWithHeader(
242+
m_resume_link + "?convert=false",
243+
meta,
244+
hdr ) ;
245+
*/
212246
Json resume_link = entry["link"].FindInArray( "rel",
213-
"http://schemas.google.com/g/2005#resumable-edit-media" )["href"] ;
214-
std::cout << resume_link.As<std::string>() << std::endl ;
247+
"http://schemas.google.com/g/2005#resumable-edit-media" )["href"] ;
248+
std::cout << resume_link.As<std::string>() << std::endl ;
215249

216-
std::string resp = http::Put( resume_link.Get(), "", m_http_hdr ) ;
250+
std::string etag = entry["gd$etag"].As<std::string>() ;
251+
std::cout << "etag = " << etag << std::endl ;
252+
253+
hdr.push_back( "If-Match: " + etag ) ;
254+
std::string resp = http::Put( resume_link.Get(), "", hdr ) ;
255+
256+
std::cout << "resp " << resp << std::endl ;
257+
std::istringstream ss( resp ) ;
217258

218-
std::cout << "resp " << resp ;
259+
std::string line ;
260+
while ( std::getline( ss, line ) )
261+
{
262+
static const std::string location = "Location: " ;
263+
if ( line.substr( 0, location.size() ) == location )
264+
{
265+
std::string uplink = line.substr( location.size() ) ;
266+
uplink = uplink.substr( 0, uplink.size() -1 ) ;
267+
268+
std::string data( 1000, 'x' ) ;
269+
http::Headers uphdr ;
270+
uphdr.push_back( "Content-Type: text/plain" ) ;
271+
uphdr.push_back( "Content-Range: bytes 0-999/1000" ) ;
272+
uphdr.push_back( "Expect:" ) ;
273+
uphdr.push_back( "Accept:" ) ;
274+
275+
std::string resp = http::Put( uplink, data, uphdr ) ;
276+
std::cout << "put response = " << resp << std::endl ;
277+
}
278+
}
219279
}
220280

221281
} // end of namespace

src/drive/Drive.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ private :
5353
private :
5454
OAuth2& m_auth ;
5555
std::vector<std::string> m_http_hdr ;
56+
57+
std::string m_resume_link ;
5658

5759
FolderList m_coll ;
5860
Collection m_root ;

src/main.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <cstdlib>
2626
#include <fstream>
2727
#include <iostream>
28+
#include <unistd.h>
2829
#include <iterator>
2930

3031
#include <exception>

src/protocol/HTTP.cc

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,17 @@ size_t ReadCallback( void *ptr, std::size_t size, std::size_t nmemb, std::string
5151
assert( ptr != 0 ) ;
5252
assert( data != 0 ) ;
5353

54+
std::cout << "reading " << (size*nmemb) << " bytes " << data->size() << std::endl ;
55+
5456
std::size_t count = std::min( size * nmemb, data->size() ) ;
5557
if ( count > 0 )
5658
{
57-
std::memcpy( &(*data)[0], ptr, count ) ;
59+
std::memcpy( ptr, &(*data)[0], count ) ;
5860
data->erase( 0, count ) ;
5961
}
62+
63+
std::cout << "readed " << count << " bytes " << data->size() << std::endl ;
64+
6065
return count ;
6166
}
6267

@@ -162,14 +167,41 @@ std::string PostData( const std::string& url, const std::string& data, const Hea
162167

163168
std::string post_data = data ;
164169

165-
curl_easy_setopt(curl, CURLOPT_POST, 1);
170+
curl_easy_setopt(curl, CURLOPT_POST, 1L);
166171
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &post_data[0] ) ;
167172
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_data.size() ) ;
173+
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1 ) ;
168174

169175
DoCurl( curl ) ;
170176
return resp;
171177
}
172178

179+
std::string PostDataWithHeader( const std::string& url, const std::string& data, const Headers& hdr )
180+
{
181+
std::string resp ;
182+
CURL *curl = InitCurl( url, &resp, hdr ) ;
183+
184+
std::string post_data = data ;
185+
186+
curl_easy_setopt(curl, CURLOPT_POST, 1L);
187+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &post_data[0] ) ;
188+
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_data.size() ) ;
189+
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L ) ;
190+
curl_easy_setopt(curl, CURLOPT_HEADER, 1L );
191+
192+
try
193+
{
194+
DoCurl( curl ) ;
195+
}
196+
catch ( ... )
197+
{
198+
std::cout << "response = " << resp << std::endl ;
199+
throw ;
200+
}
201+
202+
return resp;
203+
}
204+
173205
std::string PostFile( const std::string& url, const std::string& filename, const Headers& hdr )
174206
{
175207
std::string resp ;
@@ -183,18 +215,103 @@ std::string Put(
183215
{
184216
std::string resp ;
185217
CURL *curl = InitCurl( url, &resp, hdr ) ;
186-
187-
std::string put_data = data ;
188218

189-
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
219+
std::string put_data = data ;
220+
221+
// set common options
222+
curl_easy_setopt(curl, CURLOPT_HEADER, 1L );
223+
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L ) ;
190224
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &ReadCallback ) ;
191225
curl_easy_setopt(curl, CURLOPT_READDATA , &put_data ) ;
192226
curl_easy_setopt(curl, CURLOPT_INFILESIZE, put_data.size() ) ;
193-
194-
DoCurl( curl ) ;
227+
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L ) ;
228+
229+
try
230+
{
231+
DoCurl( curl ) ;
232+
}
233+
catch ( ... )
234+
{
235+
std::cout << "response = " << resp << std::endl ;
236+
throw ;
237+
}
238+
195239
return resp;
196240
}
197241

242+
void Custom( const std::string& url, const std::string& host, const Headers& headers )
243+
{
244+
CURL *curl = curl_easy_init();
245+
if ( curl == 0 )
246+
throw std::bad_alloc() ;
247+
248+
// set common options
249+
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
250+
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L );
251+
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L ) ;
252+
if ( curl_easy_perform( curl ) != 0 )
253+
throw std::runtime_error( "curl perform fail" ) ;
254+
255+
long sockextr;
256+
curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockextr);
257+
curl_socket_t sockfd = sockextr ;
258+
259+
struct timeval tv;
260+
tv.tv_sec = 60 ;
261+
tv.tv_usec = 0 ;
262+
263+
fd_set infd, outfd, errfd;
264+
FD_ZERO(&infd);
265+
FD_ZERO(&outfd);
266+
FD_ZERO(&errfd);
267+
268+
FD_SET(sockfd, &errfd); /* always check for error */
269+
FD_SET(sockfd, &outfd);
270+
if ( select(sockfd + 1, &infd, &outfd, &errfd, &tv) == -1 )
271+
throw std::runtime_error( "select fail" ) ;
272+
273+
std::string path = url.substr( host.size() ) ;
274+
std::cout << ("PUT " + path + "HTTP/1.1") << std::endl ;
275+
276+
std::ostringstream req ;
277+
req << ("PUT " + path + "HTTP/1.1\n")
278+
<< "Host: " << "docs.google.com" << "\n" ;
279+
280+
for ( Headers::const_iterator i = headers.begin() ; i != headers.end() ; ++i )
281+
req << *i << '\n' ;
282+
283+
std::string data = "hahaha this is the new file!!!!!" ;
284+
req << "Content-Length: " << data.size() << '\n'
285+
<< "Content-Range: 0-" << data.size()-1 << '/' << data.size() << "\n\n\n"
286+
<< data ;
287+
288+
std::string reqstr = req.str() ;
289+
std::cout << "requesting: \n" << reqstr << std::endl ;
290+
291+
std::size_t iolen ;
292+
if ( curl_easy_send(curl, &reqstr[0], reqstr.size(), &iolen) != CURLE_OK )
293+
throw std::runtime_error( "cannot send" ) ;
294+
295+
while ( true )
296+
{
297+
char buf[1024+1] ;
298+
FD_ZERO(&infd);
299+
FD_ZERO(&outfd);
300+
FD_ZERO(&errfd);
301+
302+
FD_SET(sockfd, &errfd); /* always check for error */
303+
FD_SET(sockfd, &infd);
304+
if ( select(sockfd + 1, &infd, &outfd, &errfd, &tv) == -1 )
305+
throw std::runtime_error( "select fail" ) ;
306+
307+
if ( curl_easy_recv(curl, buf, 1024, &iolen) != CURLE_OK )
308+
throw std::runtime_error( "cannot send" ) ;
309+
310+
buf[iolen] = '\0' ;
311+
std::cout << "read: " << buf << std::endl ;
312+
}
313+
}
314+
198315
std::string Escape( const std::string& str )
199316
{
200317
CURL *curl = curl_easy_init();

0 commit comments

Comments
 (0)