meedocs.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /*
  2. MeeDocs - A Google Docs / Google Drive client for N9
  3. Copyright 2012 Marcel D. Juhnke <marcel.juhnke@ovi.com>
  4. This file is part of MeeDocs.
  5. MeeDocs is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 2 of the License, or
  8. (at your option) any later version.
  9. MeeDocs is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with MeeDocs. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "meedocs.h"
  17. MeeDocs::MeeDocs()
  18. {
  19. // construct TransferUI client
  20. transferClient = new TransferUI::Client::Client(this);
  21. if(!transferClient->init()) {
  22. qDebug()<<"Cannot initialize TUIClient"; //error
  23. delete transferClient;
  24. }
  25. /* m_client_id = "688932937241.apps.googleusercontent.com";
  26. m_client_secret = "MkwxK2cUClP0pTbPD5QqA2bw";
  27. m_redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
  28. m_grant_type = "authorization_code"; */
  29. }
  30. void MeeDocs::doDownload(const QUrl &url, const QString &accessToken, QString name, const QString &doctype)
  31. {
  32. // Download file at the given URL
  33. //connect(&manager, SIGNAL(finished(QNetworkReply*)),
  34. // SLOT(downloadFinished(QNetworkReply*)));
  35. // Define needed HTTP headers for GDocs download request, such as the access token
  36. QByteArray auth_header("Bearer ");
  37. auth_header.append(accessToken);
  38. QNetworkRequest request(url);
  39. request.setRawHeader("Authorization", auth_header);
  40. downReply = manager.get(request);
  41. // Create entry in Transfer UI for the download
  42. downloadTransfer = transferClient->registerTransfer(name, TransferUI::Client::TRANSFER_TYPES_DOWNLOAD);
  43. downloadTransfer->waitForCommit();
  44. downloadTransfer->setName(name);
  45. downloadTransfer->setActive(0.0);
  46. downloadTransfer->commit();
  47. transferClient->showUI();
  48. m_download_progress_iterator = 1;
  49. connect(downloadTransfer, SIGNAL(cancel()), SLOT(cancelDownload()));
  50. connect(downReply, SIGNAL(finished()), SLOT(downloadFinished()));
  51. connect(downReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(downloadStatus(qint64,qint64)));
  52. // Slashes and Colons in local filenames not good, therefore swap those characters for the downloaded filename
  53. name.replace("/", "_");
  54. name.replace(":", "_");
  55. m_filename = "/home/user/MyDocs/Downloads/";
  56. // m_filename = "C:/Users/marrat/";
  57. m_filename.append(name);
  58. /* if the downloaded file is a document and not a raw file, its mimetype is "text/html", but Google doesn't
  59. append .html to the filename automatically, hence we do it here manually */
  60. /* if ( doctype == "text/html") {
  61. m_filename.append(".html");
  62. } */
  63. }
  64. // Self describing
  65. bool MeeDocs::saveToDisk(const QString &filename, QIODevice *data)
  66. {
  67. QFile file(filename);
  68. if (!file.exists(filename)) {
  69. if (!file.open(QIODevice::WriteOnly)) {
  70. fprintf(stderr, "Could not open %s for writing: %s\n",
  71. qPrintable(filename),
  72. qPrintable(file.errorString()));
  73. return false;
  74. }
  75. file.write(data->readAll());
  76. file.close();
  77. }
  78. return true;
  79. }
  80. // When the download's NetworkReply has been received without errors, save it to disk
  81. void MeeDocs::downloadFinished()
  82. {
  83. QUrl url = downReply->url();
  84. if (downReply->error()){
  85. fprintf(stderr, "Download of %s failed: %s\n", url.toEncoded().constData(), qPrintable(downReply->errorString()));
  86. downloadTransfer->markCancelled();
  87. } else {
  88. if (saveToDisk(m_filename, downReply)){
  89. printf("Download of %s succeeded (saved to %s)\n", url.toEncoded().constData(), qPrintable(m_filename));
  90. downloadTransfer->markCompleted(true, "", m_filename);
  91. }
  92. }
  93. downReply->deleteLater();
  94. downloadTransfer->commit();
  95. transferClient->removeTransfer(downloadTransfer->transferId());
  96. delete downloadTransfer;
  97. downloadTransfer = 0;
  98. m_transfer_size_set = false;
  99. }
  100. // Lists the content of a given directory and return them as a StringList
  101. QStringList MeeDocs::listDirContent(const QString &path)
  102. {
  103. QStringList fileEntry;
  104. QDir directory;
  105. directory.cd(path);
  106. fileEntry = directory.entryList(QDir::NoFilter, QDir::DirsFirst);
  107. return fileEntry;
  108. }
  109. // Checks if a given path is a directory
  110. bool MeeDocs::isDir(const QString &path)
  111. {
  112. QDir directory;
  113. if (directory.cd(path)) {
  114. return true;
  115. }
  116. else {
  117. return false;
  118. }
  119. }
  120. // Upload a local file to the given URL (GData upload link)
  121. void MeeDocs::doUpload(const QString &path, const QString &filename, const QString &accessToken)
  122. {
  123. m_filename = path;
  124. m_filename.append(filename);
  125. // specifies the mimetype of the file to upload and sets upload chunk size to 512 KiB
  126. m_content_type = contentType(m_filename);
  127. m_chunk_size = 524288;
  128. // opens the specified file
  129. m_upload_file = new QFile(m_filename);
  130. m_upload_file->open(QIODevice::ReadOnly);
  131. // calculates number of chunks needed for the given upload file
  132. m_file_size = QByteArray::number(m_upload_file->size());
  133. m_file_parts = m_upload_file->size() / m_chunk_size + 1;
  134. m_current_file_part = 0;
  135. // appends access token header
  136. m_auth_header = QByteArray("Bearer ");
  137. m_auth_header.append(accessToken);
  138. const QString url = "https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false";
  139. QNetworkRequest request(url);
  140. request.setRawHeader("GData-Version", "3.0");
  141. request.setRawHeader("Authorization", m_auth_header);
  142. request.setRawHeader("Content-Length", "0");
  143. request.setRawHeader("Slug", filename.toUtf8());
  144. request.setRawHeader("X-Upload-Content-Type", m_content_type);
  145. request.setRawHeader("X-Upload-Content-Length", m_file_size);
  146. // send the first request as POST to upload link to tell the Google server we want to upload new doc
  147. putReply = manager.post(request, "");
  148. fprintf(stderr, "Sending POST to start upload");
  149. // after receiving a reply steer it to resumeUpload()
  150. connect(putReply, SIGNAL(finished()), SLOT(resumeUpload()));
  151. }
  152. void MeeDocs::resumeUpload()
  153. {
  154. qDebug() << "Entering resumeUpload()";
  155. /* was only for debugging purposes
  156. QList<QByteArray> headerList = putReply->rawHeaderList();
  157. QList<QByteArray> headerValues;
  158. for (int s = 0; s < headerList.size(); ++s) {
  159. headerValues.append(putReply->rawHeader(headerList[s]));
  160. } */
  161. // asks the server which bytes it already received successfully
  162. m_succeeded_range = putReply->rawHeader("Range");
  163. // ask the server for resumable-create-media (that's where the file itself has to be uploaded to)
  164. if(m_next_location.isEmpty()) {
  165. m_next_location = QUrl::fromEncoded(putReply->rawHeader("Location"));
  166. }
  167. // if no new resumable link has been received continue using the old one
  168. else if(!putReply->rawHeader("Location").isEmpty()) {
  169. m_next_location = QUrl::fromEncoded(putReply->rawHeader("Location"));
  170. }
  171. m_current_file_part++;
  172. /* only for debugging
  173. QString error = putReply->errorString();
  174. QVariant http_error = putReply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
  175. QString next = m_next_location.toString(); */
  176. if (putReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "201"){
  177. // HTTP 201 is received when all chunks have been received successfully by server
  178. qDebug() << "Upload finished!";
  179. uploadTransfer->markCompleted(false);
  180. uploadTransfer->commit();
  181. transferClient->removeTransfer(uploadTransfer->transferId());
  182. delete uploadTransfer;
  183. uploadTransfer = 0;
  184. m_transfer_size_set = false;
  185. putReply->deleteLater();
  186. m_upload_file->close();
  187. return;
  188. } else if (putReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "308" || putReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "200"){
  189. // HTTP 308 is received when chunk was sent successfully and server awaits next chunk
  190. qDebug() << "Uploading next chunk";
  191. putReply->deleteLater();
  192. nextUpload(m_next_location);
  193. } else {
  194. qDebug() << putReply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
  195. emit uploadFailed();
  196. putReply->deleteLater();
  197. m_upload_file->close();
  198. }
  199. }
  200. void MeeDocs::nextUpload(const QUrl &url)
  201. {
  202. // Server wants to know which bytes it will receive in next chunk, so we build the range here
  203. m_content_range_begin = m_chunk_size*m_current_file_part-m_chunk_size;
  204. m_content_range_end = m_chunk_size*m_current_file_part - 1;
  205. if ( m_content_range_end >= m_upload_file->size() ) {
  206. m_content_range_end = m_upload_file->size() - 1;
  207. }
  208. // seek to current chunk's beginning in the file
  209. m_upload_file->seek(m_content_range_begin);
  210. // Build a HTTP header for the server to tell it which byte range we will send
  211. QByteArray ba_content_range_begin = QByteArray::number(m_content_range_begin);
  212. QByteArray ba_content_range_end;
  213. ba_content_range_end = QByteArray::number(m_content_range_end);
  214. QByteArray ba_content_range_header = "bytes "+ba_content_range_begin+"-"+ba_content_range_end+"/"+m_file_size;
  215. qint64 content_length = m_chunk_size;
  216. if (m_upload_file->size() < m_chunk_size) {
  217. content_length = m_upload_file->size();
  218. }
  219. QNetworkRequest request(url);
  220. request.setRawHeader("GData-Version", "3.0");
  221. request.setRawHeader("Authorization", m_auth_header);
  222. request.setRawHeader("Content-Length", QByteArray::number(content_length));
  223. request.setRawHeader("Content-Type", m_content_type);
  224. request.setRawHeader("Content-Range", ba_content_range_header);
  225. // do a HTTP PUT to the resumable-create-media link with the current chunk as content
  226. qDebug() << "Uploading file part " << m_current_file_part << " of " << m_file_parts;
  227. putReply = manager.put(request, m_upload_file->read(m_chunk_size));
  228. // Create entry in Transfer UI for the upload
  229. m_upload_progress_iterator = 1;
  230. if (!uploadTransfer){
  231. uploadTransfer = transferClient->registerTransfer(m_filename, TransferUI::Client::TRANSFER_TYPES_UPLOAD);
  232. uploadTransfer->waitForCommit();
  233. uploadTransfer->setName(m_filename);
  234. uploadTransfer->setActive(0.0);
  235. uploadTransfer->commit();
  236. transferClient->showUI();
  237. connect(uploadTransfer, SIGNAL(cancel()), SLOT(cancelUpload()));
  238. }
  239. // do the same as long not all chunks have been successfully received by the server
  240. connect(putReply, SIGNAL(uploadProgress(qint64,qint64)), SLOT(uploadStatus(qint64,qint64)));
  241. connect(putReply, SIGNAL(finished()), SLOT(resumeUpload()));
  242. }
  243. void MeeDocs::uploadStatus(const qint64 &bytesSent, const qint64 &bytesTotal)
  244. {
  245. m_bytes_sent = bytesSent + m_chunk_size * (m_current_file_part - 1);
  246. qDebug() << "Sent " << m_bytes_sent << " of " << m_upload_file->size();
  247. m_upload_progress = 1.0/10*m_upload_progress_iterator;
  248. if (!m_transfer_size_set){
  249. if (uploadTransfer->setSize(m_upload_file->size())){
  250. uploadTransfer->commit();
  251. }
  252. m_transfer_size_set = true;
  253. }
  254. if (m_bytes_sent >= m_upload_file->size()/10*m_upload_progress_iterator){
  255. m_upload_progress_iterator = m_upload_progress_iterator + 1;
  256. uploadTransfer->setProgress(m_upload_progress);
  257. uploadTransfer->commit();
  258. }
  259. }
  260. void MeeDocs::downloadStatus(const qint64 &bytesReceived, const qint64 &bytesTotal)
  261. {
  262. m_bytes_received = bytesReceived;
  263. m_bytes_total = bytesTotal;
  264. // qDebug() << "Received " << m_bytes_received << " of " << bytesTotal;
  265. m_download_progress = 1.0/10*m_download_progress_iterator;
  266. if (!m_transfer_size_set){
  267. if (downloadTransfer->setSize(bytesTotal)){
  268. downloadTransfer->commit();
  269. }
  270. m_transfer_size_set = true;
  271. }
  272. if (bytesReceived >= bytesTotal/10*m_download_progress_iterator){
  273. m_download_progress_iterator = m_download_progress_iterator + 1;
  274. downloadTransfer->setProgress(m_download_progress);
  275. downloadTransfer->commit();
  276. }
  277. // qDebug() << "Transfer progress iterator: " << m_download_progress_iterator;
  278. // qDebug() << bytesTotal/5*m_download_progress_iterator << " = " << m_download_progress;
  279. }
  280. QByteArray MeeDocs::contentType(const QString &filename)
  281. {
  282. // compares extension of given file with a list of mimetypes and returns the type if matched
  283. // QFile mimeFile("C:/Users/marrat/Qt/MeeDocs/qml/share/mimetypes.txt");
  284. QFile mimeFile("/opt/MeeDocs/qml/share/mimetypes.txt");
  285. if (!mimeFile.open(QIODevice::ReadOnly)) {
  286. return "application/octet-stream";
  287. }
  288. QTextStream extensionList(&mimeFile);
  289. QString mimeLine;
  290. QStringList extension;
  291. while (mimeLine != "EOF") {
  292. mimeLine = extensionList.readLine();
  293. extension = mimeLine.split(9);
  294. if ( filename.endsWith(extension[0]) ) {
  295. return extension[1].toUtf8();
  296. }
  297. }
  298. return "application/octet-stream";
  299. }
  300. void MeeDocs::cancelDownload()
  301. {
  302. downReply->abort();
  303. // not handling downloadTransfer here, because it is handled by downloadFinished(),
  304. // which is called by the QNetworkManager also in an abort case!
  305. qDebug() << "Download has been cancelled!";
  306. }
  307. void MeeDocs::cancelUpload()
  308. {
  309. putReply->abort();
  310. uploadTransfer->markCancelled();
  311. delete uploadTransfer;
  312. uploadTransfer = 0;
  313. m_transfer_size_set = false;
  314. m_upload_file->close();
  315. qDebug() << "Upload has been cancelled!";
  316. }
  317. void MeeDocs::createCollection(const QString &collectionTitle, const QString &accessToken)
  318. {
  319. // Define needed HTTP headers for GDocs API request, such as the access token
  320. m_auth_header = QByteArray("Bearer ");
  321. m_auth_header.append(accessToken);
  322. QString url("https://docs.google.com/feeds/default/private/full");
  323. QNetworkRequest request(url);
  324. request.setRawHeader("Authorization", m_auth_header);
  325. request.setRawHeader("GData-Version", "3.0");
  326. request.setRawHeader("Content-Type", "application/atom+xml");
  327. QByteArray xmlBody("<?xml version='1.0' encoding='UTF-8'?>");
  328. xmlBody.append("<entry xmlns=\"http://www.w3.org/2005/Atom\"><category scheme=\"http://schemas.google.com/g/2005#kind\" term=\"http://schemas.google.com/docs/2007#folder\"/><title>");
  329. xmlBody.append(collectionTitle);
  330. xmlBody.append("</title></entry>");
  331. qDebug() << QByteArray::number(xmlBody.length());
  332. qDebug() << xmlBody;
  333. request.setRawHeader("Content-Length", QByteArray::number(xmlBody.length()));
  334. downReply = manager.post(request, xmlBody);
  335. connect(downReply, SIGNAL(finished()), SLOT(isCollectionCreated()));
  336. }
  337. // When the download's NetworkReply has been received without errors, save it to disk
  338. void MeeDocs::isCollectionCreated()
  339. {
  340. if (downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "201"){
  341. // HTTP 201 is received when all chunks have been received successfully by server
  342. qDebug() << "Collection created";
  343. emit collectionCreated();
  344. downReply->deleteLater();
  345. return;
  346. } else {
  347. qDebug() << "Collection failed";
  348. qDebug() << downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString();
  349. emit collectionFailed();
  350. downReply->deleteLater();
  351. }
  352. }
  353. void MeeDocs::deleteCollection(const QString &collectionId, const QString &accessToken)
  354. {
  355. // Define needed HTTP headers for GDocs API request, such as the access token
  356. m_auth_header = QByteArray("Bearer ");
  357. m_auth_header.append(accessToken);
  358. QString url(collectionId);
  359. QNetworkRequest request(url);
  360. request.setRawHeader("Authorization", m_auth_header);
  361. request.setRawHeader("GData-Version", "3.0");
  362. request.setRawHeader("If-Match", "*");
  363. downReply = manager.deleteResource(request);
  364. connect(downReply, SIGNAL(finished()), SLOT(isCollectionDeleted()));
  365. }
  366. // When the download's NetworkReply has been received without errors, save it to disk
  367. void MeeDocs::isCollectionDeleted()
  368. {
  369. if (downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "200"){
  370. // HTTP 201 is received when all chunks have been received successfully by server
  371. qDebug() << "Collection deleted";
  372. emit collectionCreated();
  373. downReply->deleteLater();
  374. return;
  375. } else {
  376. qDebug() << "Collection delete failed";
  377. qDebug() << downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString();
  378. emit collectionFailed();
  379. downReply->deleteLater();
  380. }
  381. }
  382. void MeeDocs::addToCollection(const QString &collectionId, const QString &resourceId, const QString &accessToken)
  383. {
  384. // Define needed HTTP headers for GDocs API request, such as the access token
  385. m_auth_header = QByteArray("Bearer ");
  386. m_auth_header.append(accessToken);
  387. QString url(collectionId);
  388. QNetworkRequest request(url);
  389. request.setRawHeader("Authorization", m_auth_header);
  390. request.setRawHeader("GData-Version", "3.0");
  391. request.setRawHeader("Content-Type", "application/atom+xml");
  392. QByteArray xmlBody("<?xml version='1.0' encoding='UTF-8'?>");
  393. xmlBody.append("<entry xmlns=\"http://www.w3.org/2005/Atom\"><category scheme=\"http://schemas.google.com/g/2005#kind\" term=\"http://schemas.google.com/docs/2007#folder\"/><id>https://docs.google.com/feeds/default/private/full/");
  394. xmlBody.append(resourceId);
  395. xmlBody.append("</id></entry>");
  396. qDebug() << QByteArray::number(xmlBody.length());
  397. qDebug() << xmlBody;
  398. request.setRawHeader("Content-Length", QByteArray::number(xmlBody.length()));
  399. downReply = manager.post(request, xmlBody);
  400. connect(downReply, SIGNAL(finished()), SLOT(isAddedToCollection()));
  401. }
  402. void MeeDocs::isAddedToCollection()
  403. {
  404. if (downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "201"){
  405. // HTTP 201 is received when the request was successful.
  406. qDebug() << "Document is added to collection";
  407. emit addedToCollection();
  408. downReply->deleteLater();
  409. return;
  410. } else {
  411. qDebug() << "Adding to collection failed";
  412. qDebug() << downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString();
  413. emit addedToCollectionFailed();
  414. downReply->deleteLater();
  415. }
  416. }
  417. void MeeDocs::removeFromCollection(const QString &url, const QString &accessToken)
  418. {
  419. // Define needed HTTP headers for GDocs API request, such as the access token
  420. m_auth_header = QByteArray("Bearer ");
  421. m_auth_header.append(accessToken);
  422. qDebug() << url;
  423. QNetworkRequest request(url);
  424. request.setRawHeader("Authorization", m_auth_header);
  425. request.setRawHeader("GData-Version", "3.0");
  426. request.setRawHeader("If-Match", "*");
  427. downReply = manager.deleteResource(request);
  428. connect(downReply, SIGNAL(finished()), SLOT(isRemovedFromCollection()));
  429. }
  430. void MeeDocs::isRemovedFromCollection()
  431. {
  432. if (downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "200"){
  433. qDebug() << "Document is removed from collection";
  434. emit addedToCollection();
  435. downReply->deleteLater();
  436. return;
  437. } else {
  438. qDebug() << "Removing from collection failed";
  439. qDebug() << downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString();
  440. emit addedToCollectionFailed();
  441. downReply->deleteLater();
  442. }
  443. }
  444. void MeeDocs::trashFile(const QString &selfLink, const QString &accessToken)
  445. {
  446. // Define needed HTTP headers for GDocs API request, such as the access token
  447. m_auth_header = QByteArray("Bearer ");
  448. m_auth_header.append(accessToken);
  449. QString url(selfLink);
  450. QNetworkRequest request(url);
  451. request.setRawHeader("Authorization", m_auth_header);
  452. request.setRawHeader("GData-Version", "3.0");
  453. request.setRawHeader("If-Match", "*");
  454. downReply = manager.deleteResource(request);
  455. connect(downReply, SIGNAL(finished()), SLOT(isFileTrashed()));
  456. }
  457. void MeeDocs::isFileTrashed()
  458. {
  459. if (downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "200"){
  460. qDebug() << "File moved to Trash";
  461. emit collectionCreated();
  462. downReply->deleteLater();
  463. return;
  464. } else {
  465. qDebug() << "Move to Trash failed";
  466. qDebug() << downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString();
  467. emit collectionFailed();
  468. downReply->deleteLater();
  469. }
  470. }
  471. void MeeDocs::shareDoc(const QString &resourceId, const QString &accessToken)
  472. {
  473. // Define needed HTTP headers for GDocs API request, such as the access token
  474. m_auth_header = QByteArray("Bearer ");
  475. m_auth_header.append(accessToken);
  476. QString url("https://docs.google.com/feeds/default/private/full/");
  477. url.append(resourceId);
  478. url.append("/acl");
  479. QNetworkRequest request(url);
  480. request.setRawHeader("Authorization", m_auth_header);
  481. request.setRawHeader("GData-Version", "3.0");
  482. request.setRawHeader("Content-Type", "application/atom+xml");
  483. QByteArray xmlBody("<?xml version='1.0' encoding='UTF-8'?>");
  484. xmlBody.append("<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:gAcl='http://schemas.google.com/acl/2007'><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/><gAcl:withKey key='with link'><gAcl:role value='reader' /></gAcl:withKey><gAcl:scope type='default'/></entry>");
  485. qDebug() << QByteArray::number(xmlBody.length());
  486. qDebug() << xmlBody;
  487. request.setRawHeader("Content-Length", QByteArray::number(xmlBody.length()));
  488. downReply = manager.post(request, xmlBody);
  489. connect(downReply, SIGNAL(finished()), SLOT(isDocShared()));
  490. }
  491. void MeeDocs::isDocShared()
  492. {
  493. if (downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "201" || downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == "409"){
  494. qDebug() << "ACL entry successfully updated";
  495. emit addedToCollection();
  496. downReply->deleteLater();
  497. } else {
  498. qDebug() << "Error on updating ACL entry";
  499. qDebug() << downReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString();
  500. emit addedToCollectionFailed();
  501. downReply->deleteLater();
  502. }
  503. }
  504. QByteArray MeeDocs::uploadFileSize(const QString &path, const QString &filename)
  505. {
  506. m_filename = path;
  507. m_filename.append(filename);
  508. // specifies the mimetype of the file to upload and sets upload chunk size to 512 KiB
  509. m_content_type = contentType(m_filename);
  510. m_chunk_size = 524288;
  511. // opens the specified file
  512. m_upload_file = new QFile(m_filename);
  513. m_upload_file->open(QIODevice::ReadOnly);
  514. // calculates number of chunks needed for the given upload file
  515. m_file_size = QByteArray::number(m_upload_file->size());
  516. return m_file_size;
  517. }
  518. void MeeDocs::openShareUI(const QString &url)
  519. {
  520. MDataUri duri;
  521. duri.setMimeType ("text/x-url");
  522. duri.setTextData (url);
  523. //duri.setAttribute ("title", title);
  524. //duri.setAttribute ("description", desc);
  525. if (duri.isValid() == false) {
  526. qCritical() << "Invalid URI";
  527. return;
  528. }
  529. QStringList items;
  530. items << duri.toString();
  531. //qDebug() << "URI:" << items.join (" ");
  532. // Create a interface object
  533. ShareUiInterface shareIf("com.nokia.ShareUi");
  534. // Check if interface is valid
  535. if (shareIf.isValid()) {
  536. // Start ShareUI application with selected files.
  537. //qDebug() << "Signalling share-ui daemon...";
  538. shareIf.share (items);
  539. } else {
  540. qCritical() << "Invalid interface";
  541. return;
  542. }
  543. }