Merge lp:~gary-wzl77/storage-provider-onedrive/upload into lp:storage-provider-onedrive/devel

Proposed by Gary.Wang
Status: Merged
Merged at revision: 3
Proposed branch: lp:~gary-wzl77/storage-provider-onedrive/upload
Merge into: lp:storage-provider-onedrive/devel
Diff against target: 7075 lines (+6584/-27)
78 files modified
.bzr-builddeb/default.conf (+2/-0)
CMakeLists.txt (+8/-7)
data/CMakeLists.txt (+2/-2)
data/onedrive-provider.pc.in (+10/-0)
data/onedrive.pc.in (+0/-10)
debian/control (+2/-1)
debian/onedrive-provider0.install (+0/-2)
doc/Doxyfile.in (+2/-2)
include/onedrive/api/client.h (+203/-0)
include/onedrive/api/cloudfolder.h (+111/-0)
include/onedrive/api/clouditem.h (+123/-0)
include/onedrive/api/cloudresource.h (+69/-0)
include/onedrive/api/downloadtask.h (+119/-0)
include/onedrive/api/exceptions.h (+87/-0)
include/onedrive/api/storageinfo.h (+74/-0)
include/onedrive/api/syncmanager.h (+171/-0)
include/onedrive/api/task.h (+119/-0)
include/onedrive/api/taskqueue.h (+131/-0)
include/onedrive/api/uploadtask.h (+176/-0)
include/onedrive/api/visibility.h (+30/-0)
provider/CMakeLists.txt (+32/-0)
provider/OnedriveProvider.cpp (+634/-0)
provider/OnedriveProvider.h (+74/-0)
provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service (+3/-0)
src/CMakeLists.txt (+46/-3)
src/onedrive/api/client.cpp (+106/-0)
src/onedrive/api/client_priv.cpp (+780/-0)
src/onedrive/api/client_priv.h (+106/-0)
src/onedrive/api/cloudfolder.cpp (+121/-0)
src/onedrive/api/clouditem.cpp (+166/-0)
src/onedrive/api/config.h (+55/-0)
src/onedrive/api/downloadtask.cpp (+65/-0)
src/onedrive/api/downloadtask_priv.cpp (+193/-0)
src/onedrive/api/downloadtask_priv.h (+95/-0)
src/onedrive/api/storageinfo.cpp (+64/-0)
src/onedrive/api/syncmanager.cpp (+70/-0)
src/onedrive/api/syncmanager_priv.cpp (+111/-0)
src/onedrive/api/syncmanager_priv.h (+76/-0)
src/onedrive/api/syncthread.cpp (+447/-0)
src/onedrive/api/syncthread.h (+81/-0)
src/onedrive/api/taskhandler.h (+271/-0)
src/onedrive/api/uploadtask.cpp (+74/-0)
src/onedrive/api/uploadtask_priv.cpp (+208/-0)
src/onedrive/api/uploadtask_priv.h (+111/-0)
symbols.map (+15/-0)
tests/CMakeLists.txt (+8/-0)
tests/server/resources/D47F8E4CDBE19587!104.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!105_201607.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!105_Nonexists.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!139.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!140.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!151.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!152.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!156.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!888.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!999.json (+1/-0)
tests/server/resources/invalid_token.json (+1/-0)
tests/server/resources/move_D47F8E4CDBE19587!155.json (+1/-0)
tests/server/resources/move_D47F8E4CDBE19587!159.json (+1/-0)
tests/server/resources/move_empty.json (+1/-0)
tests/server/resources/name_conflict_fail.json (+1/-0)
tests/server/resources/name_conflict_rename.json (+1/-0)
tests/server/resources/new_folder_D47F8E4CDBE19587!103.json (+1/-0)
tests/server/resources/new_folder_invalid_folder_id.json (+1/-0)
tests/server/resources/rm_generate_files.sh (+2/-0)
tests/server/resources/root.json (+1/-0)
tests/server/resources/root_Getting.json (+1/-0)
tests/server/resources/root_children.json (+1/-0)
tests/server/resources/storage_info.json (+1/-0)
tests/server/resources/update_D47F8E4CDBE19587!160.json (+1/-0)
tests/server/resources/update_D47F8E4CDBE19587!161.json (+1/-0)
tests/server/resources/update_empty.json (+1/-0)
tests/server/resources/upload_template.json (+1/-0)
tests/server/server.py (+224/-0)
tests/unit/CMakeLists.txt (+9/-0)
tests/unit/onedrive/CMakeLists.txt (+30/-0)
tests/unit/onedrive/api/onedrive-rest-test.cpp (+328/-0)
tests/unit/onedrive/api/onedrive-sync-test.cpp (+514/-0)
To merge this branch: bzr merge lp:~gary-wzl77/storage-provider-onedrive/upload
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Approve
onedrive-team Pending
Review via email: mp+307157@code.launchpad.net

Commit message

Simple upload done. Support to upload content less than 100mb.

Description of the change

Simple upload done. Support to upload content less than 100mb.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
10. By Gary.Wang

debian file fixes.

11. By Gary.Wang

merge from devel and resolve the conflict.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
12. By Gary.Wang

support split mode for builddeb.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:12
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/4/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/822/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/829
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/632/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/4/rebuild

review: Needs Fixing (continuous-integration)
13. By Gary.Wang

add cmake-extras package.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:13
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/5/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/823/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/830
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/633/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/5/rebuild

review: Needs Fixing (continuous-integration)
14. By Gary.Wang

some changes to make CI feels good.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:14
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/6/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/824/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/831
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/634/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/634/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/634/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/634/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/634/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/634/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/634/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/634/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/634/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/6/rebuild

review: Needs Fixing (continuous-integration)
15. By Gary.Wang

remove http::header from async_get as it's not used anymore.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:15
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/7/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/825
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/832
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/635/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/7/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '.bzr-builddeb'
=== added file '.bzr-builddeb/default.conf'
--- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000
+++ .bzr-builddeb/default.conf 2016-09-30 08:26:58 +0000
@@ -0,0 +1,2 @@
1[BUILDDEB]
2split = True
03
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2016-09-26 04:27:03 +0000
+++ CMakeLists.txt 2016-09-30 08:26:58 +0000
@@ -16,7 +16,7 @@
1616
17cmake_minimum_required(VERSION 2.8)17cmake_minimum_required(VERSION 2.8)
1818
19project(onedrive)19project(onedrive-provider)
2020
21include(GNUInstallDirs)21include(GNUInstallDirs)
2222
@@ -26,9 +26,9 @@
26set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra")26set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra")
27set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")27set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
2828
29set(ONEDRIVE_LIB_VERSION_MAJOR 0)29set(ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR 0)
30set(ONEDRIVE_LIB_VERSION_MINOR 0)30set(ONEDRIVE_PROVIDER_LIB_VERSION_MINOR 0)
31set(ONEDRIVE_LIB_VERSION_PATCH 1)31set(ONEDRIVE_PROVIDER_LIB_VERSION_PATCH 1)
3232
33include(CTest)33include(CTest)
3434
@@ -36,7 +36,7 @@
36 include/36 include/
37)37)
3838
39file(GLOB_RECURSE ONEDRIVE_LIB_INTERFACE_HEADERS include/*.h)39file(GLOB_RECURSE ONEDRIVE_PROVIDER_LIB_INTERFACE_HEADERS include/*.h)
4040
41include(EnableCoverageReport)41include(EnableCoverageReport)
4242
@@ -45,11 +45,12 @@
45add_subdirectory(include)45add_subdirectory(include)
46add_subdirectory(src)46add_subdirectory(src)
47add_subdirectory(tests)47add_subdirectory(tests)
48add_subdirectory(provider)48#add_subdirectory(provider)
4949
50enable_coverage_report(50enable_coverage_report(
51 TARGETS 51 TARGETS
52 onedrive52 onedrive-provider
53 #onedrive-provider-bin
53 FILTER54 FILTER
54 ${CMAKE_SOURCE_DIR}/test/*55 ${CMAKE_SOURCE_DIR}/test/*
55 ${CMAKE_BINARY_DIR}/*56 ${CMAKE_BINARY_DIR}/*
5657
=== modified file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 2016-09-26 04:27:03 +0000
+++ data/CMakeLists.txt 2016-09-30 08:26:58 +0000
@@ -15,10 +15,10 @@
15# Authored by: Gary Wang <gary.wang@canonical.com>15# Authored by: Gary Wang <gary.wang@canonical.com>
1616
17configure_file(17configure_file(
18 onedrive.pc.in onedrive.pc @ONLY18 onedrive-provider.pc.in onedrive-provider.pc @ONLY
19)19)
2020
21install(21install(
22 FILES ${CMAKE_CURRENT_BINARY_DIR}/onedrive.pc22 FILES ${CMAKE_CURRENT_BINARY_DIR}/onedrive-provider.pc
23 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig23 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
24)24)
2525
=== added file 'data/onedrive-provider.pc.in'
--- data/onedrive-provider.pc.in 1970-01-01 00:00:00 +0000
+++ data/onedrive-provider.pc.in 2016-09-30 08:26:58 +0000
@@ -0,0 +1,10 @@
1prefix=@CMAKE_INSTALL_PREFIX@
2exec_prefix=${prefix}
3libdir=${exec_prefix}/lib
4includedir=${exec_prefix}/include
5
6Name: @CMAKE_PROJECT_NAME@
7Description: Cloud based content sharing library for Microsoft Onedrive service
8Version: @ONEDRIVE_LIB_VERSION_MAJOR@.@ONEDRIVE_LIB_VERSION_MINOR@.@ONEDRIVE_LIB_VERSION_PATCH@
9Libs: -L${libdir} -lonedrive
10Cflags: -I${includedir}
011
=== removed file 'data/onedrive.pc.in'
--- data/onedrive.pc.in 2016-09-26 04:27:03 +0000
+++ data/onedrive.pc.in 1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
1prefix=@CMAKE_INSTALL_PREFIX@
2exec_prefix=${prefix}
3libdir=${exec_prefix}/lib
4includedir=${exec_prefix}/include
5
6Name: @CMAKE_PROJECT_NAME@
7Description: Cloud based content sharing library for Microsoft Onedrive service
8Version: @ONEDRIVE_LIB_VERSION_MAJOR@.@ONEDRIVE_LIB_VERSION_MINOR@.@ONEDRIVE_LIB_VERSION_PATCH@
9Libs: -L${libdir} -lonedrive
10Cflags: -I${includedir}
110
=== modified file 'debian/control'
--- debian/control 2016-09-30 05:26:58 +0000
+++ debian/control 2016-09-30 08:26:58 +0000
@@ -2,11 +2,12 @@
2Priority: optional2Priority: optional
3Maintainer: Gary Wang <gary.wang@canonical.com>3Maintainer: Gary Wang <gary.wang@canonical.com>
4Build-Depends: cmake,4Build-Depends: cmake,
5 cmake-extras (>= 0.4),
5 debhelper (>= 9),6 debhelper (>= 9),
6 doxygen,7 doxygen,
7 google-mock,8 google-mock,
8 graphviz,9 graphviz,
9 libnet-cpp-dev,10 libnet-cpp-dev (>= 2.0.0),
10 libboost-dev (>= 1.58) | libboost1.58-dev,11 libboost-dev (>= 1.58) | libboost1.58-dev,
11 libboost-filesystem-dev (>= 1.58) | libboost-filesystem1.58-dev,12 libboost-filesystem-dev (>= 1.58) | libboost-filesystem1.58-dev,
12 libboost-system-dev (>= 1.58) | libboost-system1.58-dev,13 libboost-system-dev (>= 1.58) | libboost-system1.58-dev,
1314
=== modified file 'debian/onedrive-provider0.install'
--- debian/onedrive-provider0.install 2016-09-30 05:26:58 +0000
+++ debian/onedrive-provider0.install 2016-09-30 08:26:58 +0000
@@ -1,3 +1,1 @@
1usr/lib/*/lib*.so.*1usr/lib/*/lib*.so.*
2usr/bin/*
3usr/share/dbus-1/services/*
42
=== modified file 'doc/Doxyfile.in'
--- doc/Doxyfile.in 2016-09-26 04:27:03 +0000
+++ doc/Doxyfile.in 2016-09-30 08:26:58 +0000
@@ -32,13 +32,13 @@
32# This could be handy for archiving the generated documentation or32# This could be handy for archiving the generated documentation or
33# if some version control system is used.33# if some version control system is used.
3434
35PROJECT_NUMBER = @ONEDIRVE_LIB_VERSION_MAJOR@.@ONEDIRVE_LIB_VERSION_MINOR@.@ONEDIRVE_LIB_VERSION_PATCH@35PROJECT_NUMBER = @ONEDIRVE_PROVIDER_LIB_VERSION_MAJOR@.@ONEDIRVE_PROVIDER_LIB_VERSION_MINOR@.@ONEDIRVE_PROVIDER_LIB_VERSION_PATCH@
3636
37# Using the PROJECT_BRIEF tag one can provide an optional one line description37# Using the PROJECT_BRIEF tag one can provide an optional one line description
38# for a project that appears at the top of each page and should give viewer38# for a project that appears at the top of each page and should give viewer
39# a quick idea about the purpose of the project. Keep the description short.39# a quick idea about the purpose of the project. Keep the description short.
4040
41PROJECT_BRIEF = "Onedrive API library For Microsoft OneDrive Service"41PROJECT_BRIEF = "Onedrive API library For Microsoft OneDrive Service and a Storage Provider."
4242
43# With the PROJECT_LOGO tag one can specify an logo or icon that is43# With the PROJECT_LOGO tag one can specify an logo or icon that is
44# included in the documentation. The maximum height of the logo should not44# included in the documentation. The maximum height of the logo should not
4545
=== added file 'include/onedrive/api/client.h'
--- include/onedrive/api/client.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/client.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,203 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_CLIENT_H_
20#define ONEDRIVE_API_CLIENT_H_
21
22#include <onedrive/api/visibility.h>
23#include <onedrive/api/taskqueue.h>
24#include <onedrive/api/storageinfo.h>
25#include <onedrive/api/cloudresource.h>
26#include <onedrive/api/clouditem.h>
27#include <onedrive/api/cloudfolder.h>
28#include <onedrive/api/downloadtask.h>
29#include <onedrive/api/uploadtask.h>
30#include <onedrive/api/syncmanager.h>
31
32#include <deque>
33
34namespace onedrive {
35namespace api {
36
37class ClientPriv;
38
39/*!
40 \class Client
41 \brief Onedrive API provides developer to easily access login user's cloud contents stored on microsoft onedrive service,
42 such as musics, movie, docs, images, and so on.
43
44 The API enable developers to
45 <list type="bullet">
46 <item>retrieve authorized user cloud content list.</item>
47 <item>create, delete, move and update cloud resources.</item>
48 <item>query content infomation.</item>
49 <item>create an extranet link to share.</item>
50 <item>upload a local content to onedrive.</item>
51 <item>download a content from onedrive.</item>
52 </list>
53
54 Also sync up manager will be running on the background when client is constructed. It handles over
55 local content upload and cloud item download. \sa syncmanager.
56
57 \note Onedrive API covers cloud resourece access and content sync-up between local and cloud. It does not take
58 responsibility of account authentication. So before using onedrive APIs, developers need to call \sa set_access_token to
59 manually set a valid access_token or \sa refresh_token to fetch access token,
60 which is used to call onedrive APIs internally to pass through authentication.
61 */
62
63class ONEDRIVE_API_DLL_PUBLIC Client {
64
65 public:
66 typedef std::shared_ptr<Client> Ptr;
67
68 typedef std::deque<CloudResource::Ptr> ResourceList;
69
70 typedef std::vector<std::string> Stringlist;
71
72 /*!
73 * \brief Constructs a onedrive Client object with \a request_timeout seconds.
74 * Meanwhile client launches sync-up manager to deal with task download and upload by default.
75 */
76 Client(int request_timeout = 10);
77
78 Client(const Client&) = delete;
79
80 Client& operator=(const Client&) = delete;
81
82 virtual ~Client();
83
84 /*!
85 * \brief Set \a access_token to authenticate all onedrive API calls with the bearer HTTP authorization scheme.
86 * The access token can be fetched through ubuntu sso services.
87 */
88 void set_access_token(const std::string &access_token);
89
90 /*!
91 * \brief Retrieves and refreshes access token by using \a refresh_token.
92 * The refresh token can be fetched through ubuntu sso services.
93 * \throw std::runtime_error if error occurs.
94 * \returns true if access token is refreshed, otherwise returns false.
95 */
96// bool refresh_token(const std::string &refresh_token);
97
98 /*!
99 * \brief Returns login user's onedrive cloud storage information.
100 * \throw std::runtime_error if error occurs.
101 * @sa UserInfo
102 */
103 StorageInfo storage_info();
104
105 /*!
106 * \brief Returns root folder object on onedrive.
107 * \throw std::runtime_error if error occurs.
108 * \sa cloud_content_list(), storage_info()
109 */
110 CloudFolder::Ptr root_folder();
111
112 /*!
113 * \brief Returns cloud item list and next page token when querying one specific folder \a folder_id.
114 * if \a folder_id is empty, returns item list under root directory of onedrive.
115 * if \a page_token is empty, queries contents from the first page.
116 * The fetched content count is 200 at most per call.
117 * \a page_token indicates the specific page index on the onedrive.
118 * \throw std::runtime_error if error occurs.
119 * \sa root_folder(), metadata(), search()
120 */
121 std::tuple<ResourceList, std::string> cloud_content_list(const std::string &folder_id = std::string(),
122 const std::string &page_token = std::string());
123
124 /*!
125 * \brief Returns a resouce item object if content with a given \a content_id can be found on onedrive.
126 * otherwise return nullptr.
127 * \throw std::runtime_error if error occurs.
128 * \sa cloud_content_list()
129 */
130 CloudResource::Ptr metadata(const std::string & content_id);
131
132 /*!
133 * \brief Returns a folder item object if a folder \a folder_name is created under a given \a folder_id folder,
134 * otherwise return nullptr.
135 * if \a folder_id is empty, creates a folder item under root folder of onedrive.
136 * \throw std::runtime_error if error occurs.
137 * \sa delete_item(), move_item(), copy_item()
138 */
139 CloudFolder::Ptr create_folder(const std::string &folder_name,
140 const std::string &folder_id = std::string());
141
142 /*!
143 * \brief Returns a cloud item list if there are available items that matches with \a name under a given \a folder_id folder.
144 * if \a folder_id is empty, searches items under root folder of onedrive.
145 * \throw std::runtime_error if error occurs.
146 * \sa delete_item(), metadata()
147 */
148 Client::ResourceList search(const std::string &name,
149 const std::string &folder_id = std::string());
150
151 /*!
152 * \brief Returns true if content \a content_id is deleted, otherwise return false.
153 * \throw std::runtime_error if error occurs.
154 * \sa move_item(), metadata(), copy_item()
155 */
156 bool delete_item(const std::string &content_id);
157
158 /*!
159 * \brief Returns a resource item object if an item \a item_id is copies to a given folder \a folder_id with a new \a name on onedrive.
160 * otherwise return nullptr.
161 * \throw std::runtime_error if error occurs.
162 * \sa move_item(), update_folder(), delete_item()
163 CloudResource::Ptr copy_item(const std::string &item_id,
164 const std::string &name,
165 const std::string &folder_id);
166 */
167
168 /*!
169 * \brief Returns a resource item object if an item \a item_id is moved to a given folder \a folder_id on onedrive with new \a item_name .
170 * otherwise return nullptr.
171 * if item_name is empty, name will not changed after moving to a new folder.
172 * \throw std::runtime_error if error occurs.
173 * \sa move_item(), update_folder(), delete_item()
174 */
175 CloudResource::Ptr move_item(const std::string &item_id,
176 const std::string &folder_id,
177 const std::string &item_name = std::string());
178
179 /*!
180 * \brief Returns a resource item object if an item \a item_id is updated with \a new name, otherwise return false.
181 * otherwise return nullptr.
182 * \throw std::runtime_error if error occurs.
183 * \sa delete_contents(), copy_folders(),
184 */
185 CloudResource::Ptr rename_item(const std::string &folder_id,
186 const std::string &new_folder_name);
187
188
189 /*!
190 * \brief Returns a sync-up manager running on the background.
191 * sync-up manager scheduled tasks \sa start, pause, cancel for content upload and download.
192 */
193 SyncManager::Ptr syncmanager() const;
194
195 private:
196 std::shared_ptr<ClientPriv> p;
197
198};
199
200}
201}
202
203#endif // ONEDRIVE_API_CLIENT_H_
0204
=== added file 'include/onedrive/api/cloudfolder.h'
--- include/onedrive/api/cloudfolder.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/cloudfolder.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,111 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_CLOUDFOLDER_H_
20#define ONEDRIVE_API_CLOUDFOLDER_H_
21
22#include <onedrive/api/cloudresource.h>
23#include <onedrive/api/visibility.h>
24
25namespace Json {
26 class Value;
27}
28
29namespace onedrive {
30namespace api {
31
32/*!
33 \class CloudFolder
34 \brief CloudFolder represents a folder object on onedrive.
35 */
36
37class ONEDRIVE_API_DLL_PUBLIC CloudFolder : public CloudResource {
38public:
39 typedef std::shared_ptr<CloudFolder> Ptr;
40
41 virtual ~CloudFolder() = default;
42
43 /*!
44 * \brief Returns a unique id of cloud folder object.
45 */
46 const std::string &id() const override;
47
48 /*!
49 * \brief Returns the name of cloud folder object.
50 */
51 const std::string &name() const override;
52
53 /*!
54 * \brief Returns the datetime when folder was created.
55 */
56 const std::time_t &created_date() const override;
57
58 /*!
59 * \brief Returns the datetime when folder was updated.
60 */
61 const std::time_t &updated_date() const override;
62
63 /*!
64 * \brief Returns a shared link on onedriver for a folder .
65 */
66 const std::string &download_url() const override;
67
68 /*!
69 * \brief Returns a unique id of the parent folder.
70 */
71 const std::string &folder_id() const override;
72
73 /*!
74 * \brief Returns etag of a folder object.
75 */
76 const std::string &etag() const override;
77
78 /*!
79 * \brief Returns owner id of a folder object.
80 */
81 const std::string &owner() const override;
82
83 /*!
84 * \brief Returns resource property of an object.
85 * \sa CloudResource::Property
86 */
87 CloudResource::Property property() const override;
88
89 /*!
90 * \brief Returns a item' parent folder path on onedrive.
91 */
92 const std::string &folder_path() const override;
93
94 /*!
95 * \brief Returns the number of children items under this folder.
96 */
97 int children_count() const;
98
99private:
100 CloudFolder(const Json::Value &root);
101
102 friend class ClientPriv;
103
104 class Priv;
105 std::shared_ptr<Priv> p;
106};
107
108}
109}
110
111#endif // ONEDRIVE_API_CLOUDFOLDER_H_
0112
=== added file 'include/onedrive/api/clouditem.h'
--- include/onedrive/api/clouditem.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/clouditem.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,123 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_CloudItem_H_
20#define ONEDRIVE_API_CloudItem_H_
21
22#include <onedrive/api/cloudresource.h>
23#include <onedrive/api/visibility.h>
24
25#include <unordered_map>
26
27namespace Json {
28 class Value;
29}
30
31namespace onedrive {
32namespace api {
33
34/*!
35 \class CloudItem
36 \brief CloudItem represents a item object on onedrive.
37 */
38
39class ONEDRIVE_API_DLL_PUBLIC CloudItem: public CloudResource {
40public:
41 typedef std::shared_ptr<CloudItem> Ptr;
42
43 virtual ~CloudItem() = default;
44
45 /*!
46 * \brief Returns a unique id of cloud item object.
47 */
48 const std::string &id() const override;
49
50 /*!
51 * \brief Returns the name of cloud item object.
52 */
53 const std::string &name() const override;
54
55 /*!
56 * \brief Returns the datetime when item was created.
57 */
58 const std::time_t &created_date() const override;
59
60 /*!
61 * \brief Returns the datetime when item was updated.
62 */
63 const std::time_t &updated_date() const override;
64
65 /*!
66 * \brief Returns a download link on onedriver for a item .
67 */
68 const std::string &download_url() const override;
69
70 /*!
71 * \brief Returns a item' parent folder id on onedrive.
72 */
73 const std::string &folder_id() const override;
74
75 /*!
76 * \brief Returns a item' parent folder path on onedrive.
77 */
78 const std::string &folder_path() const override;
79
80 /*!
81 * \brief Returns etag of a item object.
82 */
83 const std::string &etag() const override;
84
85 /*!
86 * \brief Returns owner id of a item object.
87 */
88 const std::string &owner() const override;
89
90 /*!
91 * \brief Returns resource type of an object.
92 */
93 CloudResource::Property property() const override;
94
95 /*!
96 * \brief Returns content size of an object in bytes.
97 */
98 int64_t size() const;
99
100 /*!
101 * \brief Returns item's mimetype.
102 */
103 const std::string &mimetype() const;
104
105 /*!
106 * \brief content specific metadata info.
107 */
108 std::unordered_map<std::string, std::string> &metadata() const;
109
110private:
111 CloudItem(const Json::Value &root);
112
113 friend class UploadTaskPriv;
114 friend class ClientPriv;
115
116 class Priv;
117 std::shared_ptr<Priv> p;
118};
119
120}
121}
122
123#endif // ONEDRIVE_API_CloudItem_H_
0124
=== added file 'include/onedrive/api/cloudresource.h'
--- include/onedrive/api/cloudresource.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/cloudresource.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,69 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_CLOUDRESOURCE_H_
20#define ONEDRIVE_API_CLOUDRESOURCE_H_
21
22#include <memory>
23#include <string>
24#include <ctime>
25
26namespace onedrive {
27namespace api {
28
29/*!
30 \class CloudResource
31 \brief CloudResource is an abstract object that provides common interfaces for CloudItem and CloudFolder.
32 */
33
34class CloudResource {
35 public:
36 typedef std::shared_ptr<CloudResource> Ptr;
37
38 enum class Property {
39 Content, ///< content resource
40 Folder ///< folder resource
41 };
42
43 virtual ~CloudResource() = default;
44
45 virtual const std::string &id() const = 0;
46
47 virtual const std::string &name() const = 0;
48
49 virtual const std::time_t &created_date() const = 0;
50
51 virtual const std::time_t &updated_date() const = 0;
52
53 virtual const std::string &download_url() const = 0;
54
55 virtual const std::string &folder_id() const = 0;
56
57 virtual const std::string &folder_path() const = 0;
58
59 virtual const std::string &etag() const = 0;
60
61 virtual const std::string &owner() const = 0;
62
63 virtual Property property() const = 0;
64};
65
66}
67}
68
69#endif // ONEDRIVE_API_CLOUDRESOURCE_H_
070
=== added file 'include/onedrive/api/downloadtask.h'
--- include/onedrive/api/downloadtask.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/downloadtask.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,119 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_DOWNLOADTASK_H_
20#define ONEDRIVE_API_DOWNLOADTASK_H_
21
22#include <onedrive/api/visibility.h>
23#include <onedrive/api/cloudresource.h>
24#include <onedrive/api/task.h>
25
26namespace onedrive {
27namespace api {
28
29class TaskHandler;
30
31/*!
32 \struct DownloadBufferCb
33 \brief DownloadBufferCb is a download request object which consists of a content id and
34 writing callback function allows content data can be received in buffering via callback function.
35 */
36struct ONEDRIVE_API_DLL_PUBLIC DownloadBufferCb
37{
38 std::string content_id;
39 Task::Buffer_Callback write_cb;
40};
41
42class DownloadTaskPriv;
43class SyncManagerPriv;
44
45/*!
46 \class DownloadTask
47 \brief DownloadTask is a task item that can be accessed from application layer to fetch
48 basic download item information, also it's used for content download by sync manager.
49 */
50class ONEDRIVE_API_DLL_PUBLIC DownloadTask : public Task {
51public:
52 typedef std::shared_ptr<DownloadTask> Ptr;
53
54 virtual ~DownloadTask() = default;
55
56 DownloadTask& operator=(const DownloadTask& ) = delete;
57
58 /*!
59 * \brief Returns a display name of cloud content on onedrive.
60 */
61 const std::string & content_name() const override;
62
63 /*!
64 * \brief Returns cloud content local storage file path.
65 */
66 const std::string & file_path() const override;
67
68 /*!
69 * \brief Returns download url assigned by onedrive for this task.
70 * \note this url will be expried after a period of time.
71 */
72 const std::string & task_url() const override;
73
74 /*!
75 * \brief Contains the error code if an error occurs during content download.
76 */
77 const std::string & error_code() const override;
78
79 /*!
80 * \brief Contains the error string if an error occurs during content download.
81 */
82 const std::string & error_message() const override;
83
84 /*!
85 * \brief Returns current sync-up status for this task.
86 * \sa Task::TaskStatus
87 */
88 Task::Status status() const override;
89
90 /*!
91 * \brief Handler for download progress of a task.
92 * \sa Task::ProgressHandler
93 */
94 Task::ProgressHandler & progress_changed() override;
95
96 /*!
97 * \brief Handler for download status of a task.
98 * \sa Task::StatusHandler
99 */
100 Task::StatusHandler & status_changed() override;
101
102 /*!
103 * \brief cancel the task.
104 * \sa Task::StatusHandler
105 */
106 void cancel() override;
107
108private:
109 DownloadTask(std::shared_ptr<DownloadTaskPriv> p);
110
111 friend class SyncManagerPriv;
112
113 std::shared_ptr<DownloadTaskPriv> p_;
114};
115
116}
117}
118
119#endif // ONEDRIVE_API_DOWNLOADTASK_H_
0120
=== added file 'include/onedrive/api/exceptions.h'
--- include/onedrive/api/exceptions.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/exceptions.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,87 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_EXCEPTIONS_H_
20#define ONEDRIVE_API_EXCEPTIONS_H_
21
22#include <onedrive/api/visibility.h>
23
24#include <exception>
25
26namespace onedrive {
27namespace api {
28
29 /**
30 * \brief Indicates a content or folder can not be found on onedrive.
31 */
32 class ONEDRIVE_API_DLL_PUBLIC NonExistentException : public std::runtime_error {
33 public:
34 using runtime_error::runtime_error;
35 };
36
37 /**
38 * \brief User ran out of space on onedrive storage.
39 */
40 class ONEDRIVE_API_DLL_PUBLIC OutofSpaceException : public std::runtime_error {
41 public:
42 using runtime_error::runtime_error;
43 };
44
45 /**
46 * \brief Indicates a timeout on HTTP requests.
47 */
48 class ONEDRIVE_API_DLL_PUBLIC HttpTimeoutException : public std::runtime_error {
49 public:
50 using runtime_error::runtime_error;
51 };
52
53 /**
54 * \brief Indicates one or more http request parameters are invalid.
55 */
56 class ONEDRIVE_API_DLL_PUBLIC ParameterInvalidException : public std::runtime_error {
57 public:
58 using runtime_error::runtime_error;
59 };
60
61 /**
62 * \brief Indicates access token is invalid or expired.
63 */
64 class ONEDRIVE_API_DLL_PUBLIC CredentialException : public std::runtime_error {
65 public:
66 using runtime_error::runtime_error;
67 };
68
69 /**
70 * \brief Indicates The service is not available. Try the request again after a delay.
71 */
72 class ONEDRIVE_API_DLL_PUBLIC ServiceNotAvailableException : public std::runtime_error {
73 public:
74 using runtime_error::runtime_error;
75 };
76
77 /**
78 * \brief Unknown exception.
79 */
80 class ONEDRIVE_API_DLL_PUBLIC UnknownException : public std::runtime_error {
81 public:
82 using runtime_error::runtime_error;
83 };
84}
85}
86
87#endif // ONEDRIVE_API_EXCEPTIONS_H_
088
=== added file 'include/onedrive/api/storageinfo.h'
--- include/onedrive/api/storageinfo.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/storageinfo.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_STORAGEINFO_H_
20#define ONEDRIVE_API_STORAGEINFO_H_
21
22#include <onedrive/api/visibility.h>
23
24#include <memory>
25#include <string>
26
27namespace Json {
28 class Value;
29}
30
31namespace onedrive {
32namespace api {
33
34/*!
35 \class StorageInfo
36 \brief StorageInfo is a class that provides basic user's account and storage usage information on onedrive.
37 */
38
39class ONEDRIVE_API_DLL_PUBLIC StorageInfo {
40public:
41 virtual ~StorageInfo() = default;
42
43 /*!
44 * \brief Returns authorized user's id.
45 */
46 const std::string &id() const;
47
48 /*!
49 * \brief Returns authorized user's name.
50 */
51 const std::string &name() const;
52
53 /*!
54 * \brief Returns used disk size of user cloud storage in Bytes.
55 */
56 int64_t used_disk_size() const;
57
58 /*!
59 * \brief Returns total disk size assigned by onedrive in Bytes.
60 */
61 int64_t total_disk_size() const;
62private:
63 StorageInfo(const Json::Value &root);
64
65 friend class ClientPriv;
66 class Priv;
67
68 std::shared_ptr<Priv> p;
69};
70
71}
72}
73
74#endif // ONEDRIVE_API_STORAGEINFO_H_
075
=== added file 'include/onedrive/api/syncmanager.h'
--- include/onedrive/api/syncmanager.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/syncmanager.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,171 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_SYNCMANAGER_H_
20#define ONEDRIVE_API_SYNCMANAGER_H_
21
22#include <onedrive/api/taskqueue.h>
23#include <onedrive/api/downloadtask.h>
24#include <onedrive/api/uploadtask.h>
25#include <onedrive/api/visibility.h>
26
27#include <memory>
28#include <vector>
29
30namespace onedrive {
31namespace api {
32
33class ClientPriv;
34class SyncManagerPriv;
35
36/*!
37 \class SyncManager
38 \brief SyncManager handles all the requests to upload and download.
39 It's constructed around two threads for content synchronization. One for content upload to cloud, another for cloud item download to local.
40 Both thread are running asynchronously.
41 Calls \sa add_download_task() by passing a content id list for cloud content download,
42 Calls \sa add_upload_tasks() by passing a local file path for local content upload.
43 */
44
45class ONEDRIVE_API_DLL_PUBLIC SyncManager {
46 public:
47 typedef std::shared_ptr<SyncManager> Ptr;
48
49 typedef TaskQueue<DownloadTask::Ptr> DownloadList;
50
51 typedef TaskQueue<UploadTask::Ptr> UploadList;
52
53 typedef std::vector<std::string> Stringlist;
54
55 virtual ~SyncManager() = default;
56
57 SyncManager(const SyncManager&) = delete;
58
59 SyncManager& operator=(const SyncManager &) = delete;
60
61 /*!
62 * \brief Starts to run download or upload tasks from sync-up thread.
63 * The tasks can be resumed by sync-up thread if sync manager is paused or canceled before.
64 * \sa pause(), cancel()
65 */
66 void start();
67
68 /*!
69 * \brief Cancels all download or upload tasks from sync-up thread if sync manager is running.
70 * \note A canceled download or upload task has no chance to run again by sync-up thread.
71 * \sa start(), pause()
72 */
73 void cancel();
74
75 /*!
76 * \brief Pauses download or upload task from sync-up thread if sync manager is running.
77 * Sync-up thread can continue to run previous paused task by calling \sa start()
78 * \sa start(), cancel()
79 */
80 void pause();
81
82 /*!
83 * \brief Pushes a content id \a contentid_list into download queue.
84 * \return download task item that is pushed in sync-up manager.
85 * \throw std::runtime_error if error occurs.
86 * \sa add_download_tasks(), DownloadTask
87 */
88 DownloadTask::Ptr add_download_task(const std::string &content_id);
89
90 /*!
91 * \brief Pushes a download buffer callback item \a buffer_cb_item into download queue.
92 * Each download buffer consists of the following fields
93 * - `write_cb` (std::function<size_t(void *dest, size_t buf_size)>)
94 * buffer reading callback function.
95 * The buffer area pointed at by the pointer \a dest should be filled up with at most \a buf_size number of bytes.
96 * - `content_id` (string)
97 * The id of content on onedrive.
98 * \return download task item that is pushed in sync-up manager.
99 * \throw std::runtime_error if error occurs.
100 * \sa add_download_tasks(), DownloadTask
101 */
102 DownloadTask::Ptr add_download_task(const DownloadBufferCb &buffer_cb_item);
103
104 /*!
105 * \brief Pushes a upload request item \a reqeust_item to sync manager and add regarding upload task into upload queue.
106 * A upload request consists of the following fields
107 * - `file_path` (string)
108 * local file path.
109 * - `folder_id` (string)
110 * onedrive folder id which stores content in uploads folder.
111 * - `content_name` (string)
112 * uploaded content name.
113 * If content_name is empty, local file name will be used as a content name displayed on onedrive.
114 * If folder_id is empty, content will be uploaded into root folder.
115 * \return upload task item that is pushed in sync-up manager.
116 * \throw std::runtime_error if error occurs.
117 * \note A file name can not contain any of following characters:
118 * '\', '/', ':', '*', '?', '"', '<', '>', '|'
119 * \note Sync manager will detect if the uploading file is already existing on cloud,
120 * if so, it simply sets the status of upload task completed to avoid duplicate upload.
121 * \sa add_download_tasks(), UploadRequest, UploadTask,
122 */
123 UploadTask::Ptr add_upload_task(const UploadRequest &reqeust_item);
124
125 /*!
126 * \brief Pushes a upload callback item \a buffer_cb to sync manager and add regarding upload task into upload queue.
127 * A upload buffer consists of the following fields
128 * - `read_cb` (std::function<size_t(void *dest, size_t buf_size)>)
129 * buffer reading callback function.
130 * The buffer area pointed at by the pointer \a dest should be filled up with at most \a buf_size number of bytes.
131 * - `buffer_size` (size_t)
132 * total size of data buffers.
133 * - `folder_id` (string)
134 * onedrive folder id which stores content in uploads folder.
135 * - `content_name` (string)
136 * uploaded content name, should not be empty.
137 * If folder_id is empty, content will be uploaded into root folder.
138 * \return upload task item that are pushed in sync-up manager.
139 * \throw std::runtime_error if error occurs.
140 * \note A file name can not contain any of following characters:
141 * '\', '/', ':', '*', '?', '"', '<', '>', '|'
142 * \sa add_download_tasks(), UploadRequest, UploadTask,
143 */
144 UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb);
145
146 /*!
147 * \brief Returns a download task list hold by sync up manager.
148 * Each item in the list contains basic information of associated task.
149 * \sa upload_queue(), DownloadTask
150 */
151 DownloadList download_queue();
152
153 /*!
154 * \brief Returns a upload task list hold by sync up manager.
155 * Each item in the list contains basic information of associated task.
156 * \sa download_queue(), UploadTask
157 */
158 UploadList upload_queue();
159
160private:
161 SyncManager(ClientPriv* client_priv);
162
163 friend class ClientPriv;
164
165 std::shared_ptr<SyncManagerPriv> p_;
166};
167
168}
169}
170
171#endif // ONEDRIVE_API_SYNCMANAGER_H_
0172
=== added file 'include/onedrive/api/task.h'
--- include/onedrive/api/task.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/task.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,119 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_TASK_H_
20#define ONEDRIVE_API_TASK_H_
21
22#include <onedrive/api/visibility.h>
23#include <functional>
24#include <string>
25
26namespace onedrive {
27namespace api {
28
29/*!
30 \class Task
31 \brief Task is an abstract class that defines common interfaces for upload and download task.
32 */
33
34class ONEDRIVE_API_DLL_PUBLIC Task {
35public:
36 /*!
37 * \brief The Status enum indicates current status of this task.
38 */
39 enum class Status {
40 Unstart, ///< Task is in queue and sync manager does not run this task yet.
41 Running, ///< Task is being processed by sync manager.
42 Canceled, ///< Task is in canceled status, it is caused by the call from Client::cancel_sync().
43 Paused, ///< Task is in paused status, it is caused by the call from Client::pause_sync().
44 Broken, ///< Task is broken when sync manager failed to download/upload a task after several times trying.
45 Complete, ///< Task is completed.
46 };
47
48 /*!
49 * \brief The name conflict enum which can be specified the behavior to use if the file already exists.
50 * The default for PUT is replace.
51 */
52 enum class NameConflictBehavior {
53 Fail, ///<Failed if the file already exists.
54 Replace, ///<Replace current content if the file already exists.
55 Rename ///<Automatically renamed by onedrive if the file already exists.
56 };
57
58 typedef std::function<void(float)> ProgressHandler;
59
60 typedef std::function<void(Status)> StatusHandler;
61
62 typedef std::function<size_t(void *dest, size_t buf_size)> Buffer_Callback;
63
64 virtual ~Task() = default;
65
66 /*!
67 * \brief Returns a display name of cloud content on onedrive.
68 */
69 virtual const std::string & content_name() const = 0;
70
71 /*!
72 * \brief Returns cloud content local storage file path.
73 */
74 virtual const std::string & file_path() const = 0;
75
76 /*!
77 * \brief Contains the error code if an error occurs during task running.
78 */
79 virtual const std::string & error_code() const = 0;
80
81 /*!
82 * \brief Contains the error string if an error occurs during task running.
83 */
84 virtual const std::string & error_message() const = 0;
85
86 /*!
87 * \brief Returns a item task url.
88 * \note the url will be expried after a period of time.
89 */
90 virtual const std::string & task_url() const = 0;
91
92 /*!
93 * \brief Returns current download or upload item sync-up status.
94 */
95 virtual Task::Status status() const = 0;
96
97 /*!
98 * \brief Handler for download or upload progress of a task.
99 * \sa Task::ProgressHandler
100 */
101 virtual Task::ProgressHandler & progress_changed() = 0;
102
103 /*!
104 * \brief Handler for download or upload progress of a task.
105 * \sa Task::StatusHandler
106 */
107 virtual Task::StatusHandler & status_changed() = 0;
108
109 /*!
110 * \brief Cancel the task.
111 * \sa Task::StatusHandler
112 */
113 virtual void cancel() = 0;
114};
115
116}
117}
118
119#endif // ONEDRIVE_API_TASK_H_
0120
=== added file 'include/onedrive/api/taskqueue.h'
--- include/onedrive/api/taskqueue.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/taskqueue.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,131 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_TASKQUEUE_H_
20#define ONEDRIVE_API_TASKQUEUE_H_
21
22#include <memory>
23#include <deque>
24#include <mutex>
25
26namespace onedrive {
27namespace api {
28
29/*!
30 \class TaskQueue
31 \brief A thread-safe deque template.
32 */
33template<typename T, typename Container = std::deque<T>>
34class TaskQueue {
35 public:
36 typedef std::shared_ptr<TaskQueue> Ptr;
37 typedef typename Container::size_type size_type;
38 typedef typename Container::const_iterator const_iterator;
39
40 TaskQueue() = default;
41
42 virtual ~TaskQueue() = default;
43
44 TaskQueue(TaskQueue &&queue) {
45 std::lock_guard<std::mutex> lock(mutex_);
46 tasks_ = std::move(queue.tasks_);
47 }
48
49 TaskQueue(const TaskQueue &queue) {
50 std::lock_guard<std::mutex> lock(mutex_);
51 tasks_ = queue.tasks_;
52 }
53
54 TaskQueue &operator= (const TaskQueue &queue) {
55 if (this != &queue) {
56 std::lock_guard<std::mutex> lock1(mutex_);
57 std::lock_guard<std::mutex> lock2(queue.mutex_);
58 tasks_ = queue.tasks_;
59 }
60
61 return *this;
62 }
63
64 typename Container::iterator begin() {
65 std::lock_guard<std::mutex> lock(mutex_);
66 return tasks_.begin();
67 }
68
69 typename Container::iterator end() {
70 std::lock_guard<std::mutex> lock(mutex_);
71 return tasks_.end();
72 }
73
74 typename Container::iterator cbegin() const {
75 std::lock_guard<std::mutex> lock(mutex_);
76 return tasks_.cbegin();
77 }
78
79 typename Container::iterator cend() const {
80 std::lock_guard<std::mutex> lock(mutex_);
81 return tasks_.cend();
82 }
83
84 size_type size() const {
85 std::lock_guard<std::mutex> lock(mutex_);
86 return tasks_.size();
87 }
88
89 bool empty() const {
90 std::lock_guard<std::mutex> lock(mutex_);
91 return tasks_.empty();
92 }
93
94 void push(const T &task) {
95 std::lock_guard<std::mutex> lock(mutex_);
96 tasks_.push_back(task);
97 }
98
99 void push(const TaskQueue & queue) {
100 std::lock_guard<std::mutex> lock(mutex_);
101 for (const T & task: queue.tasks_){
102 tasks_.push_back(task);
103 }
104 }
105
106 bool try_pop(T &task) {
107 std::lock_guard<std::mutex> lock(mutex_);
108
109 if (tasks_.empty())
110 return false;
111
112 task = tasks_.front();
113 tasks_.pop_front();
114 return true;
115 }
116
117 const T & operator[](int index) const {
118 std::lock_guard<std::mutex> lock(mutex_);
119 return tasks_[index];
120 }
121
122 private:
123 Container tasks_;
124
125 mutable std::mutex mutex_;
126};
127
128}
129}
130
131#endif // ONEDRIVE_API_TASKQUEUE_H_
0132
=== added file 'include/onedrive/api/uploadtask.h'
--- include/onedrive/api/uploadtask.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/uploadtask.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,176 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_UPLOADTASK_H_
20#define ONEDRIVE_API_UPLOADTASK_H_
21
22#include <onedrive/api/task.h>
23#include <onedrive/api/visibility.h>
24
25#include <memory>
26#include <vector>
27
28namespace Json {
29 class Value;
30}
31
32namespace onedrive {
33namespace api {
34
35class TaskHandler;
36
37/*!
38 \struct UploadRequest
39 \brief UploadRequest is a upload request item which consists of a upload folder id, up-front buffer size,
40 upload content name
41 */
42struct ONEDRIVE_API_DLL_PUBLIC UploadRequest
43{
44 UploadRequest(std::string local_file_path,
45 std::string parent_folder_id,
46 std::string upload_file_name,
47 Task::NameConflictBehavior conflict_name_behavior = Task::NameConflictBehavior::Replace)
48 :file_path(local_file_path),
49 folder_id(parent_folder_id),
50 content_name(upload_file_name),
51 conflict_behavior(conflict_name_behavior){
52 }
53
54 std::string file_path;
55 std::string folder_id;
56 std::string content_name;
57 Task::NameConflictBehavior conflict_behavior;
58};
59typedef std::vector<UploadRequest> UploadRequestList;
60
61/*!
62 \struct UploadBufferCb
63 \brief UploadBufferCb is a upload request item which consists of a upload folder id, upload buffer size,
64 upload content name and reading callback function allows content data can be received in buffering via call
65 back function.
66*/
67struct ONEDRIVE_API_DLL_PUBLIC UploadBufferCb
68{
69 UploadBufferCb(Task::Buffer_Callback read_callback,
70 size_t upload_buf_size,
71 std::string parent_folder_id,
72 std::string upload_file_name,
73 Task::NameConflictBehavior conflict_name_behavior = Task::NameConflictBehavior::Replace)
74 :read_cb(read_callback),
75 buffer_size(upload_buf_size),
76 folder_id(parent_folder_id),
77 content_name(upload_file_name),
78 conflict_behavior(conflict_name_behavior){
79 }
80
81 Task::Buffer_Callback read_cb;
82 size_t buffer_size;
83 std::string folder_id;
84 std::string content_name;
85 Task::NameConflictBehavior conflict_behavior = Task::NameConflictBehavior::Replace;
86};
87typedef std::vector<UploadBufferCb> UploadBufferCbList;
88
89class UploadTaskPriv;
90class CloudItem;
91
92/*!
93 \class UploadTask
94 \brief UploadTask is a task item that can be accessed from application layer to fetch
95 basic upload item information, also it's used for content upload by sync manager.
96 */
97class ONEDRIVE_API_DLL_PUBLIC UploadTask : public Task {
98public:
99 typedef std::shared_ptr<UploadTask> Ptr;
100
101 virtual ~UploadTask() = default;
102
103 UploadTask& operator=(const UploadTask& ) = delete;
104
105 /*!
106 * \brief Returns a display name of local content.
107 */
108 const std::string & content_name() const override;
109
110 /*!
111 * \brief Returns uploaded local content file path.
112 */
113 const std::string & file_path() const override;
114
115 /*!
116 * \brief Returns download url assigned by onedrive for this task.
117 * \note this url will be expried after a period of time.
118 */
119 const std::string & task_url() const override;
120
121 /*!
122 * \brief Contains the error code if an error occurs during content uploading.
123 */
124 const std::string & error_code() const override;
125
126 /*!
127 * \brief Contains the error string if an error occurs during content uploading.
128 */
129 const std::string & error_message() const override;
130
131 /*!
132 * \brief Returns current sync-up status for this task.
133 */
134 Task::Status status() const override;
135
136 /*!
137 * \brief Handler for upload progress of a task.
138 * \sa Task::ProgressHandler
139 */
140 Task::ProgressHandler & progress_changed() override;
141
142 /*!
143 * \brief Handler for upload status of a task.
144 * \sa Task::StatusHandler
145 */
146 Task::StatusHandler & status_changed() override;
147
148 /*!
149 * \brief Returns a cloud item object associated with the uploaded content.
150 * \note Returns nullptr if task failed to upload regarding content on onedrive.
151 */
152 std::shared_ptr<CloudItem> upload_item() const;
153
154 /*!
155 * \brief cancel the task.
156 * \sa Task::StatusHandler
157 */
158 void cancel() override;
159
160 /*!
161 * \brief Returns file size of upload content.
162 */
163 size_t file_size() const;
164
165private:
166 UploadTask(std::shared_ptr<UploadTaskPriv> p);
167
168 friend class SyncManagerPriv;
169
170 std::shared_ptr<UploadTaskPriv> p_;
171};
172
173}
174}
175
176#endif // ONEDRIVE_API_UPLOADTASK_H_
0177
=== added file 'include/onedrive/api/visibility.h'
--- include/onedrive/api/visibility.h 1970-01-01 00:00:00 +0000
+++ include/onedrive/api/visibility.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_VISIBILITY_H_
20#define ONEDRIVE_API_VISIBILITY_H_
21
22#if __GNUC__ >= 4
23#define ONEDRIVE_API_DLL_PUBLIC __attribute__ ((visibility ("default")))
24#define ONEDRIVE_API_DLL_LOCAL __attribute__ ((visibility ("hidden")))
25#else
26#define ONEDRIVE_API_DLL_PUBLIC
27#define ONEDRIVE_API_DLL_LOCAL
28#endif
29
30#endif // ONEDRIVE_API_VISIBILITY_H_
031
=== modified file 'provider/CMakeLists.txt'
--- provider/CMakeLists.txt 2016-09-26 04:27:03 +0000
+++ provider/CMakeLists.txt 2016-09-30 08:26:58 +0000
@@ -0,0 +1,32 @@
1find_package(PkgConfig REQUIRED)
2find_package(Boost COMPONENTS filesystem system thread REQUIRED)
3
4pkg_check_modules(STORAGE_FRAMEWORK_PROVIDER storage-framework-provider-1 REQUIRED)
5
6include_directories(${CMAKE_CURRENT_BINARY_DIR} ${STORAGE_FRAMEWORK_PROVIDER_INCLUDE_DIRS})
7
8add_definitions(-DBOOST_THREAD_VERSION=4)
9
10add_executable(onedrive-provider-bin OnedriveProvider.cpp)
11
12target_link_libraries(
13 onedrive-provider-bin
14 onedrive-provider
15
16 ${Boost_LIBRARIES}
17 ${STORAGE_FRAMEWORK_PROVIDER_LDFLAGS}
18)
19
20SET_TARGET_PROPERTIES(onedrive-provider-bin
21 PROPERTIES OUTPUT_NAME onedrive-provider
22)
23
24install(
25 TARGETS onedrive-provider-bin
26 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
27)
28
29install(
30 FILES ${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.StorageFramework.Provider.OnedriveProvider.service
31 DESTINATION /usr/share/dbus-1/services
32)
033
=== added file 'provider/OnedriveProvider.cpp'
--- provider/OnedriveProvider.cpp 1970-01-01 00:00:00 +0000
+++ provider/OnedriveProvider.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,634 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include "OnedriveProvider.h"
20#include <unity/storage/provider/ProviderBase.h>
21#include <unity/storage/provider/Server.h>
22#include <unity/storage/provider/TempfileUploadJob.h>
23#include <unity/storage/provider/UploadJob.h>
24#include <unity/storage/provider/DownloadJob.h>
25#include <unity/storage/provider/metadata_keys.h>
26#include <unity/storage/provider/Exceptions.h>
27
28#include <boost/thread.hpp>
29#include <boost/thread/future.hpp>
30#include <boost/filesystem.hpp>
31#include <boost/make_shared.hpp>
32
33#include <unistd.h>
34#include <sys/socket.h>
35#include <inttypes.h>
36#include <unistd.h>
37#include <iostream>
38#include <memory>
39#include <mutex>
40#include <stdexcept>
41#include <condition_variable>
42
43#include <onedrive/api/client.h>
44#include <onedrive/api/uploadtask.h>
45#include <onedrive/api/syncmanager.h>
46#include <onedrive/api/cloudresource.h>
47#include <onedrive/api/cloudcontent.h>
48#include <onedrive/api/cloudfolder.h>
49#include <onedrive/api/exceptions.h>
50
51using namespace std;
52using namespace unity::storage;
53using namespace unity::storage::provider;
54using namespace onedrive::api;
55
56using boost::make_ready_future;
57using boost::make_exceptional_future;
58
59namespace {
60 static const int TIME_OUT = 10;
61
62 static const char *FOLDER_TYPE[] = {"normal", "pictures", "music", "videos", "message", "docs", "app", "sync"};
63 static const char *CONTENT_TYPE[] = {"all", "image", "audio", "video", "other", "doc", "spreadsheet", "ppt"};
64 static const char *STATUS[] = {"unstart", "running", "canceled", "paused", "broken", "complete"};
65 static char constexpr SIZE_IN_BYTES[] = "size_in_bytes";
66
67 string make_job_id()
68 {
69 static int last_upload_id = 0;
70 return to_string(++last_upload_id);
71 }
72
73 string status_to_string(Task::Status status)
74 {
75 return STATUS[int(status)];
76 }
77
78 string folder_type_to_string(CloudFolder::Type type)
79 {
80 return FOLDER_TYPE[int(type)];
81 }
82
83 string content_type_to_string(CloudContent::Type type)
84 {
85 return CONTENT_TYPE[int(type)];
86 }
87
88 string time_to_iso(time_t t)
89 {
90 char buf[sizeof "2016-08-11T15:10:07"];
91 strftime(buf, sizeof buf, "%FT%T", gmtime(&t));
92 return buf;
93 }
94
95 Item content_to_item(CloudResource::Ptr resource)
96 {
97 Item item;
98 item.item_id = resource->id();
99 item.parent_ids = {resource->folder_id()};
100 item.name = resource->name();
101 item.etag = resource->etag();
102 item.metadata["owner"] = resource->owner();
103 item.metadata[provider::CREATION_TIME] = time_to_iso(resource->created_date());
104 item.metadata[provider::LAST_MODIFIED_TIME] = time_to_iso(resource->updated_date());
105 if (resource->property() == CloudResource::Property::Folder) {
106 item.type = ItemType::folder;
107 auto folder = std::static_pointer_cast<onedrive::api::CloudFolder>(resource);
108 item.metadata["folder_type"] = folder_type_to_string(folder->folder_type());
109 item.metadata["folder_path"] = folder->folder_path();
110 } else if (resource->property() == CloudResource::Property::Content){
111 item.type = ItemType::file;
112 auto file = std::static_pointer_cast<onedrive::api::CloudContent>(resource);
113 item.metadata["suffix"] = file->suffix();
114 item.metadata["content_type"] = content_type_to_string(file->type());
115
116 item.metadata[provider::SIZE_IN_BYTES] = file->content_size();
117 item.metadata["description"] = file->description();
118 item.metadata["thumbnail_url"] = file->thumbnail_url();
119 item.metadata["big_thumbnail_url"] = file->big_thumbnail_url();
120 item.metadata["present_url"] = file->big_thumbnail_url();
121 }
122
123 return item;
124 }
125}
126
127class OnedriveUploadJob : public UploadJob
128{
129public:
130 OnedriveUploadJob(string const& upload_id,
131 Client::Ptr client,
132 string const& parent_id,
133 string const& file_name,
134 int64_t size,
135 bool allow_overwrite);
136
137 boost::future<void> cancel() override;
138 boost::future<Item> finish() override;
139private:
140 boost::future<tuple<bool, string>> upload_data();
141 void stop_and_cancel();
142private:
143 ssize_t feed_size;
144 string parent_id_;
145 string file_name_;
146 int64_t upload_size_;
147 bool allow_overwrite_;
148
149 boost::future<tuple<bool, string>> upload_future_;
150
151 std::mutex mutex_;
152
153 UploadTask::Ptr task_;
154 Client::Ptr client_;
155};
156
157class OnedriveDownloadJob : public DownloadJob
158{
159public:
160 using DownloadJob::DownloadJob;
161
162 OnedriveDownloadJob(string const& download_id,
163 string const& item_id,
164 Client::Ptr client);
165
166 boost::future<void> cancel() override;
167 boost::future<void> finish() override;
168private:
169 boost::future<tuple<bool, string>> download_data();
170 void send_data();
171 void stop_and_cancel();
172private:
173 string item_id_;
174 boost::future<tuple<bool, string>> download_future_;
175
176 std::mutex mutex_;
177
178 DownloadTask::Ptr task_;
179 Client::Ptr client_;
180};
181
182OnedriveProvider::OnedriveProvider()
183 : client_(std::make_shared<Client>(TIME_OUT))
184{
185}
186
187boost::future<ItemList> OnedriveProvider::roots(Context const& ctx)
188{
189 set_access_token(ctx);
190
191 return boost::async([this](){
192 try {
193 auto root_folder_id = client_->cloud_root_folder_id();
194
195 ItemList roots = {
196 {root_folder_id, {}, "root", "", ItemType::root, {}}
197 };
198
199 return make_ready_future<ItemList>(roots);
200 } catch (runtime_error &e) {
201 return make_exceptional_future<ItemList>(
202 RemoteCommsException(string("OnedriveProvider::roots(): failed: ") + e.what()));
203 }
204 });
205}
206
207boost::future<tuple<ItemList,string>> OnedriveProvider::list(
208 string const& item_id, string const& page_token,
209 Context const& ctx)
210{
211 set_access_token(ctx);
212
213 int page_token_index = 0;
214 if (!page_token.empty()) {
215 try {
216 page_token_index = stoi(page_token);
217 } catch (invalid_argument &e) {
218 return make_exceptional_future<tuple<ItemList,string>>(
219 InvalidArgumentException(string("OnedriveProvider::list(): invalid page token: ") + e.what()));
220 }
221 }
222
223 return boost::async([this, item_id, page_token_index](){
224 try {
225 const int count_per_page = 50;
226 int start_index = 1 + page_token_index * count_per_page;
227 auto content_list = client_->cloud_content_list(start_index, count_per_page,
228 CloudContent::Type::All, item_id);
229
230 ItemList roots;
231 for (const auto & content: content_list) {
232 roots.push_back(content_to_item(content));
233 }
234
235 int offset = 0;
236 boost::promise<tuple<ItemList,string>> prom;
237 if (content_list.size() >= count_per_page) {
238 offset++;
239 }
240 prom.set_value(make_tuple(roots, std::to_string(page_token_index + offset)));
241
242 return prom.get_future();
243 } catch (InvalidIDException &e) {
244 return make_exceptional_future<tuple<ItemList,string>>(
245 NotExistsException(string("OnedriveProvider::list(): failed: ") + e.what(), item_id));
246 } catch (runtime_error &e) {
247 return make_exceptional_future<tuple<ItemList,string>>(
248 RemoteCommsException(string("OnedriveProvider::list(): failed: ") + e.what()));
249 }
250 });
251}
252
253boost::future<ItemList> OnedriveProvider::lookup(
254 string const& parent_id, string const& name,
255 Context const& ctx)
256{
257 set_access_token(ctx);
258
259 return boost::async([this, parent_id, name](){
260 try {
261 const int count_per_page = 50;
262 int page_token_index = 0;
263 int start_index = 0;
264
265 ItemList roots;
266 do {
267 page_token_index++;
268 start_index = 1 + (page_token_index - 1) * count_per_page;
269 auto content_list = client_->cloud_content_list(start_index, count_per_page,
270 CloudContent::Type::All, parent_id);
271
272 for (const auto & content: content_list) {
273 if (content->name().find(name) != string::npos) {
274 roots.push_back(content_to_item(content));
275 }
276 }
277
278 if (content_list.size() < count_per_page)
279 break;
280 } while (true);
281
282 return make_ready_future<ItemList>(roots);
283 } catch (InvalidIDException &e) {
284 return make_exceptional_future<ItemList>(
285 NotExistsException(string("OnedriveProvider::lookup(): folder not exists: ") + e.what(), parent_id));
286 } catch (runtime_error &e) {
287 return make_exceptional_future<ItemList>(
288 RemoteCommsException(string("OnedriveProvider::lookup(): failed: ") + e.what()));
289 }
290 });
291}
292
293boost::future<Item> OnedriveProvider::metadata(string const& item_id,
294 Context const& ctx)
295{
296 set_access_token(ctx);
297
298 return boost::async([this, item_id](){
299 try {
300 auto content = client_->metadata(item_id);
301 return make_ready_future<Item>(content_to_item(content));
302 } catch (NonExistentException &e) {
303 return make_exceptional_future<Item>(
304 NotExistsException(string("OnedriveProvider::metadata(): content not exists: ") + e.what(), item_id));
305 } catch (runtime_error &e) {
306 return make_exceptional_future<Item>(
307 RemoteCommsException(string("OnedriveProvider::metadata(): failed: ") + e.what()));
308 }
309 });
310}
311
312boost::future<Item> OnedriveProvider::create_folder(
313 string const& parent_id, string const& name,
314 Context const& ctx)
315{
316 set_access_token(ctx);
317
318 return boost::async([this, parent_id, name](){
319 try {
320 auto content = client_->create_folder(name, parent_id);
321 return make_ready_future<Item>(content_to_item(content));
322 } catch (NonExistentException &e) {
323 return make_exceptional_future<Item>(
324 NotExistsException(string("OnedriveProvider::create_folder(): name: ") + e.what(), name));
325 } catch (runtime_error &e) {
326 return make_exceptional_future<Item>(
327 RemoteCommsException(string("OnedriveProvider::create_folder(): failed: ") + e.what()));
328 }
329 });
330}
331
332boost::future<unique_ptr<UploadJob>> OnedriveProvider::create_file(
333 string const& parent_id, string const& name,
334 int64_t size, string const& /*content_type*/, bool allow_overwrite,
335 Context const& ctx)
336{
337 set_access_token(ctx);
338
339 return make_ready_future(unique_ptr<UploadJob>(new OnedriveUploadJob(make_job_id(), client_, parent_id, name, size, allow_overwrite)));
340}
341
342boost::future<unique_ptr<UploadJob>> OnedriveProvider::update(
343 string const& item_id, int64_t size, string const& /*old_etag*/,
344 Context const& ctx)
345{
346 set_access_token(ctx);
347
348 return boost::async([this, item_id, size, ctx](){
349 try {
350 auto content = client_->metadata(item_id);
351 auto file_name = content->name();
352 auto parent_id = content->folder_id();
353
354 delete_item(item_id, ctx);
355
356 return create_file(parent_id, file_name, size, "", true, ctx);
357 } catch (runtime_error &e) {
358 return make_exceptional_future<unique_ptr<UploadJob>>(
359 RemoteCommsException(string("OnedriveProvider::update(): failed: ") + e.what()));
360 }
361 });
362}
363
364boost::future<unique_ptr<DownloadJob>> OnedriveProvider::download(
365 string const& item_id, Context const& ctx)
366{
367 set_access_token(ctx);
368
369 return make_ready_future(unique_ptr<DownloadJob>(new OnedriveDownloadJob(make_job_id(), item_id, client_)));
370}
371
372boost::future<void> OnedriveProvider::delete_item(
373 string const& item_id, Context const& ctx)
374{
375 set_access_token(ctx);
376
377 return boost::async([this, item_id](){
378 try {
379 Client::Stringlist content_id_list{{item_id}};
380 client_->delete_contents(content_id_list);
381 return make_ready_future();
382 } catch (ParameterInvalidException &e) {
383 return make_exceptional_future<void>(
384 NotExistsException(string("OnedriveProvider::delete_item(): failed: ") + e.what(), item_id));
385 } catch (runtime_error &e) {
386 return make_exceptional_future<void>(
387 RemoteCommsException(string("OnedriveProvider::delete_item(): failed: ") + e.what()));
388 }
389 });
390}
391
392boost::future<Item> OnedriveProvider::move(
393 string const& item_id, string const& new_parent_id,
394 string const& /*new_name*/, Context const& ctx)
395{
396 set_access_token(ctx);
397
398 return boost::async([this, item_id, new_parent_id](){
399 try {
400 Client::Stringlist folderlist;
401 Client::Stringlist contentlist{{item_id}};
402 client_->move_items(folderlist, contentlist, new_parent_id);
403 auto content = client_->metadata(item_id);
404 return make_ready_future<Item>(content_to_item(content));
405 } catch (NonExistentException &e) {
406 return make_exceptional_future<Item>(
407 NotExistsException(string("OnedriveProvider::move(): content or folder not exist: ") + e.what(), ""));
408 } catch (runtime_error &e) {
409 return make_exceptional_future<Item>(
410 RemoteCommsException(string("OnedriveProvider::move(): failed: ") + e.what()));
411 }
412 });
413}
414
415boost::future<Item> OnedriveProvider::copy(
416 string const& item_id, string const& new_parent_id,
417 string const& /*new_name*/, Context const& ctx)
418{
419 set_access_token(ctx);
420
421 return boost::async([this, item_id, new_parent_id](){
422 try {
423 Client::Stringlist content_list{{item_id}};
424 auto content_id = client_->copy_contents(content_list, new_parent_id)[0];
425 auto content = client_->metadata(content_id);
426 return make_ready_future<Item>(content_to_item(content));
427 } catch (NonExistentException &e) {
428 return make_exceptional_future<Item>(
429 NotExistsException(string("OnedriveProvider::copy(): content or folder not exist: ") + e.what(), item_id));
430 } catch (runtime_error &e) {
431 return make_exceptional_future<Item>(
432 RemoteCommsException(string("OnedriveProvider::copy(): failed: ") + e.what()));
433 }
434 });
435}
436
437void OnedriveProvider::set_access_token(Context const& ctx) {
438 auto access_token = boost::get<OAuth2Credentials>(ctx.credentials).access_token;
439 std::cout <<"onedrive access_token: " << access_token << std::endl;
440 client_->set_access_token(access_token);
441}
442
443OnedriveUploadJob::OnedriveUploadJob(string const &upload_id,
444 Client::Ptr client,
445 string const& parent_id,
446 string const& file_name,
447 int64_t size,
448 bool allow_overwrite)
449 : UploadJob(upload_id)
450 , parent_id_(parent_id)
451 , file_name_(file_name)
452 , upload_size_(size)
453 , allow_overwrite_(allow_overwrite)
454 , task_(nullptr)
455 , client_(client)
456{
457 upload_future_ = upload_data();
458}
459
460boost::future<void> OnedriveUploadJob::cancel()
461{
462 printf("cancel_upload('%s')\n", upload_id().c_str());
463 stop_and_cancel();
464
465 return make_ready_future();
466}
467
468boost::future<Item> OnedriveUploadJob::finish()
469{
470 printf("finish_upload('%s')\n", upload_id().c_str());
471 return boost::async([this](){
472 try {
473 auto upload_ctx = upload_future_.get();
474 auto upload_ok = get<0>(upload_ctx);
475 auto error_str = get<1>(upload_ctx);
476 if (upload_ok){
477 auto content = client_->metadata(task_->content_id());
478 return make_ready_future<Item>(content_to_item(content));
479 }
480
481 return make_exceptional_future<Item>(
482 RemoteCommsException(string("OnedriveUploadJob::finish(): failed: ") + error_str));
483 } catch (runtime_error &e) {
484 return make_exceptional_future<Item>(
485 RemoteCommsException(string("OnedriveUploadJob::finish(): failed: ") + e.what()));
486 }
487 });
488}
489
490boost::future<tuple<bool, string>> OnedriveUploadJob::upload_data()
491{
492 auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
493
494 return boost::async([this, prom](){
495 std::lock_guard<std::mutex> guard(mutex_);
496
497 int socket_fd = read_socket();
498 UploadBufferList buffer_item_list{{[socket_fd](void *dest, size_t buf_size) -> size_t {
499 //data reading callback.
500 size_t read_size = read(socket_fd, dest, buf_size);
501 if (read_size == 0)
502 return -1;
503 return read_size;
504 }, (size_t)upload_size_, parent_id_, file_name_}};
505
506 try {
507 task_ = client_->syncmanager()->add_upload_tasks(buffer_item_list)[0];
508 task_->status_changed() = [this, prom](Task::Status status) {
509 std::cout << " status: " << status_to_string(status) << std::endl;
510 if (status == Task::Status::Complete){
511 prom->set_value(make_tuple(true, string()));
512 } else if (status == Task::Status::Canceled ||
513 status == Task::Status::Broken) {
514 prom->set_value(make_tuple(false, task_->error_string()));
515 }
516 };
517 task_->progress_changed() = [this](float percent) {
518 cout<< "uploading: " << task_->content_name() << " " << percent << endl;
519 };
520 } catch (runtime_error & e) {
521 prom->set_value(make_tuple(false, e.what()));
522 }
523
524 return prom->get_future();
525 });
526}
527
528void OnedriveUploadJob::stop_and_cancel()
529{
530 std::lock_guard<std::mutex> guard(mutex_);
531
532 if (task_ != nullptr &&
533 (task_->status() != Task::Status::Broken &&
534 task_->status() != Task::Status::Complete)) {
535 task_->cancel();
536 }
537}
538
539OnedriveDownloadJob::OnedriveDownloadJob(string const &download_id,
540 string const &item_id,
541 Client::Ptr client)
542 : DownloadJob(download_id)
543 , item_id_(item_id)
544 , task_(nullptr)
545 , client_(client)
546{
547 download_future_ = download_data();
548}
549
550boost::future<void> OnedriveDownloadJob::cancel()
551{
552 stop_and_cancel();
553
554 printf("cancel_download('%s')\n", download_id().c_str());
555 return make_ready_future();
556}
557
558boost::future<void> OnedriveDownloadJob::finish()
559{
560 return boost::async([this]() {
561 auto download_ctx = download_future_.get();
562 auto download_ok = get<0>(download_ctx);
563 auto error_str = get<1>(download_ctx);
564 if (download_ok){
565 return make_ready_future();
566 }
567
568 return make_exceptional_future<void>(
569 RemoteCommsException(string("failed to download from onedrive: ") + error_str));
570 });
571}
572
573boost::future<tuple<bool, string>> OnedriveDownloadJob::download_data()
574{
575 auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
576
577 return boost::async([this, prom](){
578 std::lock_guard<std::mutex> guard(mutex_);
579
580 int socket_fd = write_socket();
581 DownloadBufferList buffer_item_list{{item_id_,
582 [socket_fd](void *dest, size_t buf_size) -> size_t {
583 //data writing callback.
584 return write(socket_fd, dest, buf_size);
585 }
586 }};
587
588 try {
589 task_ = client_->syncmanager()->add_download_tasks(buffer_item_list)[0];
590 task_->status_changed() = [this, prom](Task::Status status) {
591 std::cout << " status: " << status_to_string(status) << std::endl;
592 if (status == Task::Status::Complete) {
593 report_complete();
594 prom->set_value(make_tuple(true, string()));
595 } else if (status == Task::Status::Canceled ||
596 status == Task::Status::Broken) {
597 prom->set_value(make_tuple(false, task_->error_string()));
598 }
599 };
600 task_->progress_changed() = [this](float percent) {
601 cout<< "downloading: " << task_->content_name() << " " << percent << endl;
602 };
603 } catch (runtime_error & e) {
604 prom->set_value(make_tuple(false, e.what()));
605 }
606
607 return prom->get_future();
608 });
609}
610
611void OnedriveDownloadJob::stop_and_cancel()
612{
613 std::lock_guard<std::mutex> guard(mutex_);
614
615 if (task_ != nullptr &&
616 (task_->status() != Task::Status::Broken &&
617 task_->status() != Task::Status::Complete)) {
618 task_->cancel();
619 }
620}
621
622int main(int argc, char **argv)
623{
624 const std::string bus_name = "com.canonical.StorageFramework.Provider.OnedriveProvider";
625 std::string account_service_id = "com.canonical.scopes.onedrive_onedrive_onedrive";
626 if (argc > 1)
627 {
628 account_service_id = argv[1];
629 }
630
631 Server<OnedriveProvider> server(bus_name, account_service_id);
632 server.init(argc, argv);
633 server.run();
634}
0635
=== added file 'provider/OnedriveProvider.h'
--- provider/OnedriveProvider.h 1970-01-01 00:00:00 +0000
+++ provider/OnedriveProvider.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Gary Wang <gary.wang@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/provider/ProviderBase.h>
22#include <onedrive/api/client.h>
23
24using namespace std;
25using namespace onedrive::api;
26using unity::storage::provider::Context;
27using unity::storage::provider::DownloadJob;
28using unity::storage::provider::ProviderBase;
29using unity::storage::provider::Item;
30using unity::storage::provider::ItemList;
31using unity::storage::provider::UploadJob;
32
33class OnedriveProvider : public ProviderBase {
34public:
35 OnedriveProvider();
36
37 boost::future<ItemList> roots(Context const& ctx) override;
38 boost::future<tuple<ItemList,string>> list(
39 string const& item_id, string const& page_token,
40 Context const& ctx) override;
41 boost::future<ItemList> lookup(
42 string const& parent_id, string const& name,
43 Context const& ctx) override;
44 boost::future<Item> metadata(
45 string const& item_id, Context const& ctx) override;
46 boost::future<Item> create_folder(
47 string const& parent_id, string const& name,
48 Context const& ctx) override;
49
50 boost::future<unique_ptr<UploadJob>> create_file(
51 string const& parent_id, string const& name,
52 int64_t size, string const& content_type, bool allow_overwrite,
53 Context const& ctx) override;
54 boost::future<unique_ptr<UploadJob>> update(
55 string const& item_id, int64_t size, string const& old_etag,
56 Context const& ctx) override;
57
58 boost::future<unique_ptr<DownloadJob>> download(
59 string const& item_id, Context const& ctx) override;
60
61 boost::future<void> delete_item(
62 string const& item_id, Context const& ctx) override;
63 boost::future<Item> move(
64 string const& item_id, string const& new_parent_id,
65 string const& new_name, Context const& ctx) override;
66 boost::future<Item> copy(
67 string const& item_id, string const& new_parent_id,
68 string const& new_name, Context const& ctx) override;
69
70private:
71 void set_access_token(Context const& ctx);
72private:
73 Client::Ptr client_;
74};
075
=== added file 'provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service'
--- provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service 1970-01-01 00:00:00 +0000
+++ provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service 2016-09-30 08:26:58 +0000
@@ -0,0 +1,3 @@
1[D-BUS Service]
2Name=com.canonical.StorageFramework.Provider.OnedriveProvider
3Exec=/usr/bin/onedrive-provider
04
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2016-09-26 04:27:03 +0000
+++ src/CMakeLists.txt 2016-09-30 08:26:58 +0000
@@ -17,10 +17,53 @@
17find_package(Boost COMPONENTS regex filesystem system REQUIRED)17find_package(Boost COMPONENTS regex filesystem system REQUIRED)
18find_package(PkgConfig REQUIRED)18find_package(PkgConfig REQUIRED)
1919
20include_directories(${Boost_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS})
21
22pkg_check_modules(JSON_CPP jsoncpp REQUIRED)20pkg_check_modules(JSON_CPP jsoncpp REQUIRED)
23pkg_check_modules(NET_CPP net-cpp>=1.3.0 REQUIRED)21pkg_check_modules(NET_CPP net-cpp>=1.3.0 REQUIRED)
24pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)22
23include_directories(${Boost_INCLUDE_DIRS} ${JSON_CPP_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS})
24
25add_library(
26 onedrive-provider SHARED
27
28 ${ONEDRIVE_PROVIDER_LIB_INTERFACE_HEADERS}
29
30 onedrive/api/client.cpp
31 onedrive/api/client_priv.cpp
32 onedrive/api/cloudfolder.cpp
33 onedrive/api/clouditem.cpp
34 onedrive/api/downloadtask.cpp
35 onedrive/api/downloadtask_priv.cpp
36 onedrive/api/uploadtask.cpp
37 onedrive/api/uploadtask_priv.cpp
38 onedrive/api/syncmanager.cpp
39 onedrive/api/syncmanager_priv.cpp
40 onedrive/api/syncthread.cpp
41 onedrive/api/storageinfo.cpp
42 onedrive/api/client.cpp
43)
44
45target_link_libraries(
46 onedrive-provider
47
48 ${CMAKE_THREAD_LIBS_INIT}
49
50 ${Boost_LIBRARIES}
51 ${JSON_CPP_LIBRARIES}
52 ${NET_CPP_LDFLAGS}
53)
2554
26set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map")55set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map")
56set_target_properties(
57 onedrive-provider
58
59 PROPERTIES
60 LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}"
61 LINK_DEPENDS ${symbol_map}
62 VERSION ${ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR}.${ONEDRIVE_PROVIDER_LIB_VERSION_MINOR}.${ONEDRIVE_PROVIDER_LIB_VERSION_PATCH}
63 SOVERSION ${ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR}
64)
65
66install(
67 TARGETS onedrive-provider
68 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
69)
2770
=== added file 'src/onedrive/api/client.cpp'
--- src/onedrive/api/client.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/client.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,106 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include <onedrive/api/client.h>
20#include "client_priv.h"
21
22#include <core/net/error.h>
23#include <core/net/uri.h>
24#include <core/net/http/client.h>
25#include <core/net/http/request.h>
26#include <core/net/http/response.h>
27
28#include <boost/filesystem.hpp>
29#include <boost/algorithm/string.hpp>
30
31using namespace onedrive::api;
32using namespace std;
33
34Client::Client(int request_timeout)
35 : p(std::make_shared<ClientPriv>(request_timeout)) {
36
37}
38
39Client::~Client() {
40 p->sync_manager()->cancel();
41}
42
43void Client::set_access_token(const string &access_token) {
44 p->set_access_token(access_token);
45// p->sync_manager()-
46}
47
48StorageInfo Client::storage_info() {
49 return p->storage_info();
50}
51
52CloudFolder::Ptr Client::root_folder() {
53 return p->root_folder();
54}
55
56tuple<Client::ResourceList, string> Client::cloud_content_list(const std::string &folder_id,
57 const std::string &page_token) {
58 return p->cloud_content_list(folder_id, page_token);
59}
60
61CloudResource::Ptr Client::metadata(const string &content_id) {
62 return p->metadata(content_id);
63}
64
65CloudFolder::Ptr Client::create_folder(const string &folder_name,
66 const string &folder_id) {
67 return p->create_folder(folder_name, folder_id);
68}
69
70Client::ResourceList Client::search(const string &name,
71 const string &parent_folder_id) {
72 return p->search(name, parent_folder_id);
73}
74
75CloudResource::Ptr Client::move_item(const std::string &item_id,
76 const std::string &folder_id,
77 const std::string &item_name) {
78 return p->move_item(item_id, folder_id, item_name);
79}
80
81bool Client::delete_item(const string &content_id) {
82 return p->delete_item(content_id);
83}
84
85/*
86CloudResource::Ptr Client::copy_item(const string &item_id,
87 const string &name,
88 const string &folder_id) {
89 return p->copy_item(item_id, name, folder_id);
90}
91*/
92
93CloudResource::Ptr Client::rename_item(const string &item_id,
94 const string &name) {
95 return p->rename_item(item_id, name);
96}
97
98//bool Client::refresh_token(const string &refresh_token) {
99// return p->refersh_token(refresh_token);
100//}
101
102SyncManager::Ptr Client::syncmanager() const {
103 return p->sync_manager();
104}
105
106
0107
=== added file 'src/onedrive/api/client_priv.cpp'
--- src/onedrive/api/client_priv.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/client_priv.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,780 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include "client_priv.h"
20#include "syncmanager_priv.h"
21#include "config.h"
22
23#include <onedrive/api/cloudfolder.h>
24#include <onedrive/api/clouditem.h>
25#include <onedrive/api/storageinfo.h>
26#include <onedrive/api/downloadtask.h>
27#include <onedrive/api/uploadtask.h>
28#include <onedrive/api/cloudresource.h>
29#include <onedrive/api/syncmanager.h>
30#include <onedrive/api/exceptions.h>
31
32#include <core/net/error.h>
33#include <core/net/uri.h>
34#include <core/net/http/client.h>
35#include <core/net/http/request.h>
36#include <core/net/http/response.h>
37
38#include <boost/algorithm/string.hpp>
39#include <boost/algorithm/string/regex.hpp>
40#include <boost/filesystem.hpp>
41#include <boost/regex.hpp>
42
43#include <json/json.h>
44
45#include <iostream>
46#include <unordered_map>
47
48namespace http = core::net::http;
49namespace json = Json;
50namespace net = core::net;
51
52namespace fs = boost::filesystem;
53namespace alg = boost::algorithm;
54
55using namespace onedrive::api;
56using namespace std;
57
58namespace {
59
60template<typename T>
61static void set_exception(std::shared_ptr<std::promise<T>> prom,
62 const json::Value &root) {
63 if (root.isMember("error")) {
64 std::string code = root["error"]["code"].asString();
65 std::string msg = root["error"]["message"].asString();
66 if (code == "unauthenticated") {
67 prom->set_exception(make_exception_ptr(CredentialException(msg)));
68 } else if (code == "itemNotFound") {
69 prom->set_exception(make_exception_ptr(NonExistentException(msg)));
70 } else if (code == "invalidRequest") {
71 prom->set_exception(make_exception_ptr(ParameterInvalidException(msg)));
72 } else if (code == "quotaLimitReached") {
73 prom->set_exception(make_exception_ptr(CredentialException(msg)));
74 } else if (code == "serviceNotAvailable") {
75 prom->set_exception(make_exception_ptr(ServiceNotAvailableException(msg)));
76 }
77
78 return;
79 }
80
81 prom->set_exception(make_exception_ptr(UnknownException(root.toStyledString())));
82}
83
84}
85
86class ClientPriv::HttpClient {
87public:
88 HttpClient(int request_timeout) :
89 client_(http::make_client()),
90 worker_ { [this]() {client_->run();} },
91 cancelled_(false) {
92 config_.request_timeout = request_timeout;
93 }
94
95 ~HttpClient() {
96 client_->stop();
97 if (worker_.joinable()) {
98 worker_.join();
99 }
100 }
101
102 std::shared_ptr<core::net::http::Client> client_;
103
104 std::thread worker_;
105
106 Config config_;
107
108 std::mutex config_mutex_;
109
110 std::atomic<bool> cancelled_;
111
112 void get(const net::Uri::Path &path,
113 const net::Uri::QueryParameters &parameters,
114 http::Request::Handler &handler) {
115 auto configuration = net_config(path, parameters);
116 configuration.header.add("User-Agent", config_.user_agent);
117
118 auto request = client_->head(configuration);
119 request->async_execute(handler);
120 }
121
122 void post(const net::Uri::Path &path,
123 const net::Uri::QueryParameters &parameters,
124 const std::string &postbody,
125 const std::string &content_type,
126 http::Request::Handler &handler) {
127 std::lock_guard<std::mutex> lock(config_mutex_);
128 http::Request::Configuration configuration = net_config(path, parameters);
129 configuration.header.add("User-Agent", config_.user_agent);
130 configuration.header.add("Content-Length", std::to_string(postbody.size()));
131 configuration.header.add("Content-Type", content_type);
132 configuration.header.add("Prefer", "respond-async");
133
134 auto request = client_->post(configuration, postbody, content_type);
135 request->async_execute(handler);
136 }
137
138 void del(const net::Uri::Path &path,
139 const net::Uri::QueryParameters &parameters,
140 http::Request::Handler &handler) {
141 std::lock_guard<std::mutex> lock(config_mutex_);
142 http::Request::Configuration configuration = net_config(path, parameters);
143 configuration.header.add("User-Agent", config_.user_agent);
144
145 auto request = client_->del(configuration);
146 request->async_execute(handler);
147 }
148
149 void patch(const net::Uri::Path &path,
150 const net::Uri::QueryParameters &parameters,
151 const std::string &postbody,
152 const std::string &content_type,
153 http::Request::Handler &handler) {
154 std::lock_guard<std::mutex> lock(config_mutex_);
155 http::Request::Configuration configuration = net_config(path, parameters);
156 configuration.header.add("User-Agent", config_.user_agent);
157 configuration.header.add("Content-Type", content_type);
158 //WORKAROUND: net-cpp doesn't support PATCH method.
159 configuration.header.add("X-HTTP-Method-Override", "PATCH");
160
161 auto request = client_->post(configuration, postbody, content_type);
162 request->async_execute(handler);
163 }
164
165 http::Request::Configuration net_config(const net::Uri::Path &path,
166 const net::Uri::QueryParameters &parameters) {
167 http::Request::Configuration configuration;
168 net::Uri::QueryParameters complete_parameters(parameters);
169 if (!config_.access_token.empty()) {
170 configuration.header.add("Authorization",
171 "bearer " + config_.access_token);
172 }
173
174 if (getenv("ONEDRIVE_LOCAL_SERVER_URL")) {
175 config_.apiroot = string(getenv("ONEDRIVE_LOCAL_SERVER_URL"));
176 configuration.header.add("Authorization",
177 "bearer " + config_.access_token);
178 }
179
180 net::Uri uri = net::make_uri(config_.apiroot, path,
181 complete_parameters);
182 configuration.uri = client_->uri_to_string(uri);
183 std::cout << "uri: "<<configuration.uri << std::endl;
184
185 return configuration;
186 }
187
188 http::Request::Progress::Next progress_changed(
189 const http::Request::Progress&) {
190 return cancelled_ ?
191 http::Request::Progress::Next::abort_operation :
192 http::Request::Progress::Next::continue_operation;
193 }
194
195 template<typename T>
196 future<T> async_get(const net::Uri::Path &path,
197 const net::Uri::QueryParameters &parameters,
198 const function<T(const json::Value &root)> &func) {
199 auto prom = make_shared<promise<T>>();
200
201 http::Request::Handler handler;
202 handler.on_progress(
203 bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
204 handler.on_error([prom](const net::Error& e)
205 {
206 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
207 });
208 handler.on_response(
209 [prom,func](const http::Response& response)
210 {
211 json::Reader reader;
212 json::Value root;
213
214 std::cout <<"http status code: " << response.status <<"response.body: " << response.body
215 << std::endl;
216
217 //for download link generation, link can be found at header[location] according to dev doc
218 if (response.status == net::http::Status::accepted) {
219 response.header.enumerate([&root](const std::string& key,
220 const std::set<std::string>& /*values*/) {
221 vector<string> headers;
222 boost::split_regex(headers, key, boost::regex(": "));
223 boost::trim_right(headers[1]);
224 root[headers[0]] = headers[1];
225 std::cout << "header: " << key <<" " << headers[1] << std::endl;
226 });
227 prom->set_value(func(root));
228 } else if (!reader.parse(response.body, root)) {
229 prom->set_exception(make_exception_ptr(UnknownException("json parse failed")));
230 } else {
231 if (response.status != net::http::Status::ok) {
232 set_exception<T>(prom, root);
233 } else {
234 prom->set_value(func(root));
235 }
236 }
237 }
238 );
239
240 get(path, parameters, handler);
241
242 return prom->get_future();
243 }
244
245 template<typename T>
246 future<T> async_post(const net::Uri::Path &path,
247 const net::Uri::QueryParameters &parameters,
248 const std::string &postmsg,
249 const std::string &content_type,
250 const function<T(const json::Value &root)> &func) {
251 auto prom = make_shared<promise<T>>();
252
253 http::Request::Handler handler;
254 handler.on_progress(
255 bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
256 handler.on_error([prom](const net::Error& e)
257 {
258 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
259 });
260 handler.on_response(
261 [path, prom,func](const http::Response& response)
262 {
263 json::Reader reader;
264 json::Value root;
265
266 std::cout <<"http status code: " << response.status <<"response.body: " << response.body
267 <<" isempty: " <<response.body.empty() << std::endl;
268
269 if (!reader.parse(response.body, root)) {
270 prom->set_exception(make_exception_ptr(runtime_error("json parse failed")));
271 } else if (response.status != net::http::Status::ok &&
272 response.status != net::http::Status::created &&
273 response.status != net::http::Status::accepted &&
274 response.status != net::http::Status::see_other) {
275 set_exception<T>(prom, root);
276 } else {
277 //To deal with AsyncJobStatus
278 //https://dev.onedrive.com/items/copy.htm
279 string cache_header;
280 if (response.status == net::http::Status::accepted) {
281 json::Value requestJson;
282 json::StyledWriter writer;
283 response.header.enumerate([&requestJson, &cache_header,
284 &writer](const std::string& key,
285 const std::set<std::string>& /*values*/) {
286 vector<string> headers;
287 boost::split_regex(headers, key, boost::regex(": "));
288 boost::trim_right(headers[1]);
289 requestJson[headers[0]] = headers[1];
290 std::cout << "sdfsdfsd: " << key <<" " << headers[1] << std::endl;
291 });
292
293 cache_header = writer.write(requestJson);
294// return;
295 }
296
297 if (!cache_header.empty() && !reader.parse(cache_header, root)) {
298 prom->set_exception(make_exception_ptr(runtime_error("json parse failed")));
299 } else {
300 prom->set_value(func(root));
301 }
302 }
303 }
304 );
305
306 post(path, parameters, postmsg, content_type, handler);
307
308 return prom->get_future();
309 }
310
311 template<typename T>
312 future<T> async_patch(const net::Uri::Path &path,
313 const net::Uri::QueryParameters &parameters,
314 const std::string &postmsg,
315 const std::string &content_type,
316 const function<T(const json::Value &root)> &func) {
317 auto prom = make_shared<promise<T>>();
318
319 http::Request::Handler handler;
320 handler.on_progress(
321 bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
322 handler.on_error([prom](const net::Error& e)
323 {
324 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
325 });
326 handler.on_response(
327 [path, prom,func](const http::Response& response)
328 {
329 json::Reader reader;
330 json::Value root;
331
332 std::cout <<"http status code: " << response.status <<"response.body: " << response.body
333 <<" isempty: " <<response.body.empty() << std::endl;
334
335 if (!reader.parse(response.body, root)) {
336 prom->set_exception(make_exception_ptr(UnknownException("json parse failed")));
337 } else {
338 if (response.status != net::http::Status::ok) {
339 set_exception<T>(prom, root);
340 } else {
341 prom->set_value(func(root));
342 }
343 }
344 }
345 );
346
347 patch(path, parameters, postmsg, content_type, handler);
348
349 return prom->get_future();
350 }
351
352 template<typename T>
353 future<T> async_del(const net::Uri::Path &path,
354 const net::Uri::QueryParameters &parameters,
355 const function<T(const json::Value &root)> &func) {
356 auto prom = make_shared<promise<T>>();
357
358 http::Request::Handler handler;
359 handler.on_progress(
360 bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
361 handler.on_error([prom](const net::Error& e)
362 {
363 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
364 });
365 handler.on_response(
366 [prom,func](const http::Response& response)
367 {
368 std::cout <<"http status code: " << response.status <<"response.body: " << response.body
369 << std::endl;
370
371 json::Reader reader;
372 json::Value root;
373 if (response.status == net::http::Status::no_content) {
374 prom->set_value(func(root));
375 } else {
376 if (!reader.parse(response.body, root)) {
377 prom->set_exception(make_exception_ptr(UnknownException("json parse failed")));
378 } else{
379 set_exception<T>(prom, root);
380 }
381 }
382 }
383 );
384
385 del(path, parameters, handler);
386
387 return prom->get_future();
388 }
389};
390
391ClientPriv::ClientPriv(int request_timeout)
392 : httpclient_(std::make_shared<HttpClient>(request_timeout))
393 , sync_manager_(std::shared_ptr<SyncManager>(new SyncManager(this))) {
394}
395
396ClientPriv::~ClientPriv() {
397 httpclient_->cancelled_ = true;
398}
399
400void ClientPriv::set_access_token(const string &access_token) {
401 httpclient_->config_.access_token = access_token;
402 sync_manager_->p_->set_access_token(access_token);
403}
404
405StorageInfo ClientPriv::storage_info() {
406 auto storage_future = httpclient_->async_get<StorageInfo>(
407 { "drive" }, { },
408 [](const json::Value &root) {
409 return StorageInfo(root);
410 });
411
412 return get_or_throw(storage_future);
413}
414
415CloudResource::Ptr ClientPriv::metadata(const string &content_id) {
416 auto disk_future = httpclient_->async_get<CloudResource::Ptr>(
417 { "drive", "items", content_id }, { },
418 [](const json::Value &root) -> CloudResource::Ptr {
419 if (root.isMember("folder"))
420 return shared_ptr<CloudFolder>(new CloudFolder(root));
421 return shared_ptr<CloudItem>(new CloudItem(root));
422 });
423
424 return get_or_throw(disk_future);
425}
426
427CloudFolder::Ptr ClientPriv::root_folder() {
428 auto folder_future = httpclient_->async_get<CloudFolder::Ptr>(
429 { "drive", "items", "root" }, { },
430 [](const json::Value &root) -> CloudFolder::Ptr {
431 return shared_ptr<CloudFolder>(new CloudFolder(root));
432 });
433
434 return get_or_throw(folder_future);
435}
436
437tuple<Client::ResourceList, string> ClientPriv::cloud_content_list(const std::string &folder_id,
438 const std::string &page_token) {
439 net::Uri::Path path { "drive", "items" };
440 if (folder_id.empty()) {
441 path.emplace_back("root");
442 } else {
443 path.emplace_back(folder_id);
444 }
445
446 net::Uri::QueryParameters params { { "expand", "children" } };
447 if (!page_token.empty()) {
448 params.emplace_back(make_pair("skiptoken", page_token));
449 }
450
451 auto resource_future = httpclient_->async_get<tuple<Client::ResourceList, string>>(
452 path, params,
453 [](const json::Value &root) -> tuple<Client::ResourceList, string> {
454 Client::ResourceList results;
455
456 json::Value children;
457 if (root.isMember("children"))
458 children = root["children"];
459 else if (root.isMember("value"))
460 children = root["value"];
461
462 for (const auto & child: children) {
463 if (child.isMember("folder")) {
464 results.push_back(std::shared_ptr<CloudFolder>(new CloudFolder(child)));
465 } else {
466 results.push_back(std::shared_ptr<CloudItem>(new CloudItem(child)));
467 }
468 }
469
470 string next_page_token;
471 if (root.isMember("children@odata.nextLink")) {
472 const string nextToken = "skiptoken";
473 string nextLink = root["children@odata.nextLink"].asString();
474 size_t pos = nextLink.find(nextToken) + nextToken.length();
475 next_page_token = nextLink.substr(pos);
476 }
477
478 return make_tuple(results, next_page_token);
479 });
480
481 return get_or_throw(resource_future);
482}
483
484Client::ResourceList ClientPriv::search(const string &name,
485 const string &folder_id) {
486 net::Uri::Path path { "drive", "items" };
487 if (folder_id.empty()) {
488 path.emplace_back("root");
489 } else {
490 path.emplace_back(folder_id);
491 }
492 path.emplace_back("view.search");
493
494 auto resource_future = httpclient_->async_get<Client::ResourceList>(
495 path, {{"q", name}},
496 [](const json::Value &root) -> Client::ResourceList {
497 Client::ResourceList results;
498
499 json::Value children;
500 if (root.isMember("children"))
501 children = root["children"];
502 else if (root.isMember("value"))
503 children = root["value"];
504 for (const auto & child: children) {
505 if (child.isMember("folder")) {
506 results.push_back(std::shared_ptr<CloudFolder>(new CloudFolder(child)));
507 } else {
508 results.push_back(std::shared_ptr<CloudItem>(new CloudItem(child)));
509 }
510 }
511
512 return results;
513 });
514
515 return get_or_throw(resource_future);
516}
517
518CloudFolder::Ptr ClientPriv::create_folder(const string &folder_name,
519 const string &folder_id) {
520 net::Uri::Path path { "drive", "items" };
521 if (folder_id.empty()) {
522 path.emplace_back("root");
523 } else {
524 path.emplace_back(folder_id);
525 }
526 path.emplace_back("children");
527
528 json::Value requestJson;
529 requestJson["name"] = folder_name;
530 requestJson["folder"] = json::Value(json::objectValue);
531
532 json::StyledWriter writer;
533 std::string postbody = writer.write( requestJson );
534 std::string content_type = "application/json";
535 std::cout << "postbody: " << postbody << std::endl;
536
537 auto created = httpclient_->async_post<CloudFolder::Ptr>(path,
538 { }, postbody, content_type,
539 [](const json::Value &root) -> CloudFolder::Ptr {
540 return shared_ptr<CloudFolder>(new CloudFolder(root));
541 });
542
543 return get_or_throw(created);
544}
545
546bool ClientPriv::delete_item(const string item_id) {
547 auto del = httpclient_->async_del<bool>(
548 { "drive", "items", item_id }, { },
549 [](const json::Value &root) -> bool {
550 return root.isNull() ? true : false;
551 });
552
553 return get_or_throw(del);
554}
555
556/*
557CloudResource::Ptr ClientPriv::copy_item(const std::string &item_id,
558 const std::string &item_name,
559 const std::string &folder_id) {
560 json::Value requestJson;
561 requestJson["parentReference"]["id"] = folder_id;
562 requestJson["name"] = item_name;
563
564 json::StyledWriter writer;
565 std::string postbody = writer.write( requestJson );
566 std::string content_type = "application/json";
567 std::cout << "postbody: " << postbody << std::endl;
568
569 auto copy = httpclient_->async_post<unordered_map<string, string>>(
570 { "drive", "items", item_id, "action.copy"}, { }, postbody, content_type,
571 [](const json::Value &root) -> unordered_map<string, string> {
572 unordered_map<string, string> map{
573 {"Content-Length", root["Content-Length"].asString()},
574 {"Location", root["Location"].asString()},
575 {"Preference-Applied", root["Preference-Applied"].asString()},
576 {"Server", root["Preference-Applied"].asString()},
577 {"X-Msnserver", root["X-Msnserver"].asString()},
578 {"X-Wlsproxy", root["X-Wlsproxy"].asString()}
579 };
580 return map;
581 });
582
583 auto cache_header = get_or_throw(copy);
584 for (const auto & c: cache_header) {
585 std::cout << c.first << " "<< c.second << std::endl;
586 }
587
588 auto ePos = cache_header["Location"].find_last_of('/');
589 auto sub_path = cache_header["Location"].substr(ePos + 1);
590
591 std::cout << "cache_header.size():" << cache_header.size() << " "<< cache_header["Location"] << " "
592 << sub_path << std::endl;
593 if (!cache_header.empty()) {
594 auto check_future = httpclient_->async_get<CloudResource::Ptr>(
595 { "monitor", sub_path}, { }, cache_header,
596 [](const json::Value &root) -> CloudResource::Ptr {
597 return root.isNull()? nullptr : nullptr;
598 });
599
600 CloudResource::Ptr ptr = get_or_throw(check_future);
601 Client::ResourceList resourceList = search(item_name, folder_id);
602 if (resourceList.size() > 0)
603 return resourceList[0];
604 }
605
606 throw runtime_error("item copy failed");
607}
608*/
609
610
611CloudResource::Ptr ClientPriv::move_item(const std::string &item_id,
612 const std::string &folder_id,
613 const std::string &item_name) {
614 json::Value requestJson;
615 requestJson["parentReference"]["id"] = folder_id;
616 if (!item_name.empty())
617 requestJson["name"] = item_name;
618
619 json::StyledWriter writer;
620 std::string postbody = writer.write(requestJson);
621 std::string content_type = "application/json";
622
623 auto move_future = httpclient_->async_patch<CloudResource::Ptr>(
624 { "drive", "items", item_id }, { },postbody, content_type,
625 [](const json::Value &root) -> CloudResource::Ptr {
626 if (root.isMember("folder"))
627 return shared_ptr<CloudFolder>(new CloudFolder(root));
628 return shared_ptr<CloudItem>(new CloudItem(root));
629 });
630
631 return get_or_throw(move_future);
632}
633
634CloudResource::Ptr ClientPriv::rename_item(const string &item_id, const string &new_name) {
635 json::Value requestJson;
636 requestJson["name"] = new_name;
637
638 json::StyledWriter writer;
639 std::string postbody = writer.write(requestJson);
640 std::string content_type = "application/json";
641
642 auto move_future = httpclient_->async_patch<CloudResource::Ptr>(
643 { "drive", "items", item_id }, { }, postbody, content_type,
644 [](const json::Value &root) -> CloudResource::Ptr {
645 if (root.isMember("folder"))
646 return shared_ptr<CloudFolder>(new CloudFolder(root));
647 return shared_ptr<CloudItem>(new CloudItem(root));
648 });
649
650 return get_or_throw(move_future);
651}
652
653string ClientPriv::request_download_link(const string &item_id) {
654 auto link_future = httpclient_->async_get<string>(
655 { "drive", "items", item_id, "content" }, { },
656 [](const json::Value &root) -> string {
657 return root["location"].asString();
658 });
659
660 return get_or_throw(link_future);
661}
662
663//DownloadTaskPriv::Ptr ClientPriv::request_download_link(const DownloadBuffer &buffer_item) {
664
665//}
666
667/*
668SyncManager::UploadList ClientPriv::create_upload_link(const UploadRequest &request_item) {
669 if (!fs::exists(request_item.file_path))
670 throw std::runtime_error(string("file not exists: ").append(request_item.file_path));
671
672 string postbody = generate_upload_body(request_item);
673
674 log(postbody);
675
676 auto future = httpclient_->async_post<SyncManager::UploadList>(
677 { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
678 [request_item](const tinyxml2::XMLElement *root) {
679 SyncManager::UploadList results;
680
681 auto upload_res = root->FirstChildElement("uploadResult");
682 std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
683
684 std::string redirection_url;
685 if (upload_res->FirstChildElement("redirectionUrl")) {
686 redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText();
687 }
688
689 auto content_list = upload_res->FirstChildElement("newContentIDList");
690 if (content_list) {
691 auto content = content_list->FirstChildElement();
692 while(content) {
693 results.push(std::shared_ptr<UploadTask>(new UploadTask(content,
694 task_id,
695 redirection_url,
696 request_item.file_path)));
697 content = content->NextSiblingElement();
698 }
699 }
700
701 return results;
702 });
703
704 return get_or_throw(future);
705}
706
707SyncManager::UploadList ClientPriv::create_upload_link(const UploadBuffer &buffer_item) {
708 string postbody = generate_upload_body(buffer_item);
709
710 log(postbody);
711
712 auto future = httpclient_->async_post<SyncManager::UploadList>(
713 { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
714 [buffer_item](const tinyxml2::XMLElement *root) {
715 SyncManager::UploadList results;
716
717 auto upload_res = root->FirstChildElement("uploadResult");
718 std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
719
720 std::string redirection_url;
721 if (upload_res->FirstChildElement("redirectionUrl")) {
722 redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText();
723 }
724
725 auto content_list = upload_res->FirstChildElement("newContentIDList");
726 if (content_list) {
727 auto content = content_list->FirstChildElement();
728 while(content) {
729 results.push(std::shared_ptr<UploadTask>(new UploadTask(content,
730 task_id,
731 redirection_url,
732 buffer_item.buffer_size,
733 buffer_item.read_cb)));
734 content = content->NextSiblingElement();
735 }
736 }
737
738 return results;
739 });
740
741 return get_or_throw(future);
742}
743
744bool ClientPriv::refersh_token(const string &refresh_token) {
745 const std::string content_type = "application/x-www-form-urlencoded";
746 const std::string postbody = "grant_type=refresh_token&refresh_token="
747 + refresh_token;
748 log(postbody);
749
750 auto future = httpclient_->async_post<bool>(
751 { "oauthApp", "OAuth2", "refreshToken" }, { }, postbody, content_type,
752 [this](const tinyxml2::XMLElement *root) {
753 boost::cmatch cap;
754 const boost::regex exp(".*\"(.*?)\"\\}");
755 if (boost::regex_match(root->GetText(), cap, exp)) {
756 httpclient_->config_.access_token = cap[1];
757 return true;
758 }
759 return false;
760 });
761
762 return get_or_throw(future);
763}
764*/
765
766void ClientPriv::cancel() {
767 httpclient_->cancelled_ = true;
768}
769
770SyncManager::Ptr ClientPriv::sync_manager() {
771 return sync_manager_;
772}
773
774template<typename T> T ClientPriv::get_or_throw(std::future<T> &f) {
775 if (f.wait_for(std::chrono::seconds(httpclient_->config_.request_timeout)) != std::future_status::ready) {
776 throw HttpTimeoutException("HTTP request timeout");
777 }
778
779 return f.get();
780}
0781
=== added file 'src/onedrive/api/client_priv.h'
--- src/onedrive/api/client_priv.h 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/client_priv.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,106 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_CLIENTPRIV_H_
20#define ONEDRIVE_API_CLIENTPRIV_H_
21
22#include <onedrive/api/client.h>
23#include <onedrive/api/visibility.h>
24#include <onedrive/api/cloudresource.h>
25
26#include <future>
27#include <string>
28#include <memory>
29
30#include "downloadtask_priv.h"
31#include "uploadtask_priv.h"
32
33namespace onedrive {
34namespace api {
35
36class Client;
37
38class ONEDRIVE_API_DLL_LOCAL ClientPriv {
39 public:
40
41 enum class ServerCode {
42 };
43
44 typedef std::shared_ptr<ClientPriv> Ptr;
45
46 ClientPriv(int request_timeout = 10);
47
48 virtual ~ClientPriv();
49
50 StorageInfo storage_info();
51
52 void set_access_token(const std::string &access_token);
53
54// bool refersh_token(const std::string &refresh_token);
55
56 CloudResource::Ptr metadata(const std::string &content_id);
57
58 CloudFolder::Ptr root_folder();
59
60 std::tuple<Client::ResourceList, std::string> cloud_content_list(const std::string &folder_id = std::string(),
61 const std::string &page_token = std::string());
62
63 Client::ResourceList search(const std::string &name,
64 const std::string &folder_id);
65
66 CloudFolder::Ptr create_folder(const std::string &folder_name,
67 const std::string &folder_id);
68
69 /*
70 CloudResource::Ptr copy_item(const std::string &item_id,
71 const std::string &item_name,
72 const std::string &folder_id);
73 */
74
75 CloudResource::Ptr move_item(const std::string &item_id,
76 const std::string &folder_id,
77 const std::string &item_name);
78
79 CloudResource::Ptr rename_item(const std::string &item_id,
80 const std::string &new_name);
81
82
83 bool delete_item(const std::string item_id);
84
85 std::string request_download_link(const std::string &item_id);
86
87// DownloadTaskPriv::Ptr request_download_link(const DownloadBuffer &buffer_item);
88
89 void cancel();
90
91 std::shared_ptr<SyncManager> sync_manager();
92
93 private:
94 template<typename T> T get_or_throw(std::future<T> &f);
95
96 private:
97 class HttpClient;
98 std::shared_ptr<HttpClient> httpclient_;
99
100 std::shared_ptr<SyncManager> sync_manager_;
101};
102
103}
104}
105
106#endif // ONEDRIVE_API_CLIENTPRIV_H_
0107
=== added file 'src/onedrive/api/cloudfolder.cpp'
--- src/onedrive/api/cloudfolder.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/cloudfolder.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,121 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include <onedrive/api/cloudfolder.h>
20
21#include <json/json.h>
22
23#include <time.h>
24#include <iostream>
25#include <sstream>
26
27namespace json = Json;
28
29using namespace onedrive::api;
30using namespace std;
31
32std::time_t string_to_time(const std::string dt) {
33 struct std::tm tm;
34 std::istringstream ss(dt);
35 strptime(dt.c_str(), "%Y%m%d%H%M%S",&tm); // std::get std::put only available in GCC 5
36 return std::mktime(&tm);
37}
38
39class CloudFolder::Priv {
40public:
41 Priv(const json::Value &root) {
42 id_ = root["id"].asString();
43 updated_date_ = string_to_time(root["lastModifiedDateTime"].asString());
44 created_date_ = string_to_time(root["createdDateTime"].asString());
45 etag_ = root["eTag"].asString();
46 name_ = root["name"].asString();
47 owner_ = root["createdBy"]["user"]["displayName"].asString();
48 folder_id_ = root.isMember("parentReference")?
49 root["parentReference"]["id"].asString() : "";
50 children_count_ = root["folder"]["childCount"].asInt();
51
52 #ifndef NDEBUG
53 cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl;
54 #endif
55
56 }
57
58 std::string id_;
59
60 std::string name_;
61
62 std::time_t created_date_;
63
64 std::time_t updated_date_;
65
66 std::string download_url_;
67
68 std::string folder_id_;
69
70 std::string etag_;
71
72 std::string owner_;
73
74 std::string folder_path_;
75
76 int children_count_;
77};
78
79CloudFolder::CloudFolder(const json::Value &root)
80 :p(std::make_shared<Priv>(root)){
81}
82
83const string &CloudFolder::id() const {
84 return p->id_;
85}
86
87const string &CloudFolder::name() const {
88 return p->name_;
89}
90
91const time_t &CloudFolder::created_date() const {
92 return p->created_date_;
93}
94
95const time_t &CloudFolder::updated_date() const {
96 return p->updated_date_;
97}
98
99const string &CloudFolder::download_url() const {
100 return p->download_url_;
101}
102
103const string &CloudFolder::folder_id() const {
104 return p->folder_id_;
105}
106
107const string &CloudFolder::folder_path() const {
108 return p->folder_path_;
109}
110
111const string &CloudFolder::etag() const {
112 return p->etag_;
113}
114
115const string &CloudFolder::owner() const {
116 return p->owner_;
117}
118
119CloudResource::Property CloudFolder::property() const {
120 return CloudResource::Property::Folder;
121}
0122
=== added file 'src/onedrive/api/clouditem.cpp'
--- src/onedrive/api/clouditem.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/clouditem.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,166 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include <onedrive/api/clouditem.h>
20#include <json/json.h>
21
22#include <iostream>
23
24namespace json = Json;
25
26using namespace onedrive::api;
27using namespace std;
28
29extern std::time_t string_to_time(const std::string dt);
30
31class CloudItem::Priv {
32public:
33 Priv(const json::Value &root) {
34 id_ = root["id"].asString();
35 updated_date_ = string_to_time(root["lastModifiedDateTime"].asString());
36 created_date_ = string_to_time(root["createdDateTime"].asString());
37 etag_ = root["eTag"].asString();
38 name_ = root["name"].asString();
39 owner_ = root["createdBy"]["user"]["displayName"].asString();
40 folder_id_ = root["parentReference"]["id"].asString();
41 mimetype_ = root["file"].isMember("mimeType") ? root["file"]["mimeType"].asString() : "";
42 content_size_ = root["size"].asInt64();
43 download_url_ = root["@content.downloadUrl"].asString();
44 folder_path_ = root["parentReference"]["path"].asString();
45
46 if (!mimetype_.empty()) {
47 if (mimetype_.find("video/") != string::npos) {
48 if (root.isMember("photo") && root["photo"].isMember("takenDateTime")) {
49 metadata_["takenDateTime"] = root["photo"]["takenDateTime"].asString();
50 }
51 metadata_["width"] = root["video"]["width"].asInt();
52 metadata_["height"] = root["video"]["height"].asInt();
53 metadata_["bitrate"] = root["video"]["bitrate"].asInt();
54 metadata_["duration"] = root["video"]["duration"].asInt();
55 } else if (mimetype_.find("audio/") != string::npos) {
56 metadata_["duration"] = root["duration"]["duration"].asUInt();
57 } else if (mimetype_.find("image/") != string::npos) {
58 metadata_["width"] = root["image"]["width"].asInt();
59 metadata_["height"] = root["image"]["height"].asInt();
60
61 if (root.isMember("photo")) {
62 if (root["photo"].isMember("cameraMake"))
63 metadata_["cameraMake"] = root["photo"]["cameraMake"].asString();
64 if (root["photo"].isMember("cameraModel"))
65 metadata_["cameraModel"] = root["photo"]["cameraModel"].asString();
66 if (root["photo"].isMember("exposureDenominator"))
67 metadata_["exposureDenominator"] = root["photo"]["exposureDenominator"].asInt();
68 if (root["photo"].isMember("exposureNumerator"))
69 metadata_["exposureNumerator"] = root["photo"]["exposureNumerator"].asInt();
70 if (root["photo"].isMember("fNumber"))
71 metadata_["fNumber"] = root["photo"]["fNumber"].asFloat();
72 if (root["photo"].isMember("iso"))
73 metadata_["iso"] = root["photo"]["iso"].asInt();
74 }
75 }
76 }
77 #ifndef NDEBUG
78 cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl;
79 #endif
80 }
81
82 std::string id_;
83
84 std::string name_;
85
86 std::time_t created_date_;
87
88 std::time_t updated_date_;
89
90 std::string etag_;
91
92 std::string owner_;
93
94 std::string folder_path_;
95
96 std::string suffix_;
97
98 int64_t content_size_;
99
100 std::string download_url_;
101
102 std::string mimetype_;
103
104 std::string folder_id_;
105
106 std::unordered_map<std::string, std::string> metadata_;
107};
108
109CloudItem::CloudItem(const json::Value &root)
110 : p(std::make_shared<Priv>(root)){
111}
112
113const string &CloudItem::id() const {
114 return p->id_;
115}
116
117const string &CloudItem::name() const {
118 return p->name_;
119}
120
121const time_t &CloudItem::created_date() const {
122 return p->created_date_;
123}
124
125const time_t &CloudItem::updated_date() const {
126 return p->updated_date_;
127}
128
129const string &CloudItem::download_url() const {
130 return p->download_url_;
131}
132
133const string &CloudItem::folder_id() const {
134 return p->folder_id_;
135}
136
137const string &CloudItem::etag() const {
138 return p->etag_;
139}
140
141const string &CloudItem::owner() const {
142 return p->owner_;
143}
144
145CloudResource::Property CloudItem::property() const {
146 return CloudResource::Property::Content;
147}
148
149int64_t CloudItem::size() const {
150 return p->content_size_;
151}
152
153const string &CloudItem::folder_path() const
154{
155 return p->folder_path_;
156}
157
158const string &CloudItem::mimetype() const
159{
160 return p->mimetype_;
161}
162
163std::unordered_map<string, string> &CloudItem::metadata() const
164{
165 return p->metadata_;
166}
0167
=== added file 'src/onedrive/api/config.h'
--- src/onedrive/api/config.h 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/config.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_CONFIG_H_
20#define ONEDRIVE_API_CONFIG_H_
21
22#include <memory>
23#include <string>
24
25namespace onedrive {
26namespace api {
27
28struct Config {
29 typedef std::shared_ptr<Config> Ptr;
30
31 /*
32 * The access token assigned by onedrive after authenticated.
33 */
34 std::string access_token { };
35
36 /*
37 * The root of all API request URLs
38 */
39 std::string apiroot {"https://api.onedrive.com/v1.0"};
40
41 /*
42 * The custom HTTP user agent string for this library
43 */
44 std::string user_agent {"ubuntu-onedrive-lib"};
45
46 /*
47 * request timeout for onedrive restful api
48 */
49 int request_timeout = 1;
50};
51
52}
53}
54
55#endif /* ONEDRIVE_API_CONFIG_H_ */
056
=== added file 'src/onedrive/api/downloadtask.cpp'
--- src/onedrive/api/downloadtask.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/downloadtask.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,65 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include <onedrive/api/downloadtask.h>
20
21#include "downloadtask_priv.h"
22#include "taskhandler.h"
23
24using namespace onedrive::api;
25using namespace std;
26
27DownloadTask::DownloadTask(std::shared_ptr<DownloadTaskPriv> p)
28 :p_(p){
29}
30
31const string & DownloadTask::task_url() const {
32 return p_->task_url();
33}
34
35const string &DownloadTask::error_code() const {
36 return p_->error_code();
37}
38
39Task::Status DownloadTask::status() const {
40 return p_->task_handler()->status();
41}
42
43const string & DownloadTask::content_name() const {
44 return p_->content_name();
45}
46
47const string & DownloadTask::file_path() const {
48 return p_->file_path();
49}
50
51Task::ProgressHandler & DownloadTask::progress_changed() {
52 return p_->progress_changed();
53}
54
55Task::StatusHandler & DownloadTask::status_changed() {
56 return p_->status_changed();
57}
58
59const string & DownloadTask::error_message() const {
60 return p_->error_string();
61}
62
63void DownloadTask::cancel() {
64 p_->task_handler()->cancel();
65}
066
=== added file 'src/onedrive/api/downloadtask_priv.cpp'
--- src/onedrive/api/downloadtask_priv.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/downloadtask_priv.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,193 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include "downloadtask_priv.h"
20#include "taskhandler.h"
21
22#include <boost/filesystem.hpp>
23#include <json/json.h>
24
25#include <iostream>
26
27namespace json = Json;
28namespace fs = boost::filesystem;
29
30using namespace onedrive::api;
31using namespace std;
32
33namespace {
34static const std::string public_download_dir = std::string(getenv("HOME")) + "/Downloads";
35}
36
37DownloadTaskPriv::DownloadTaskPriv(const CloudItem::Ptr &root,
38 Task::Buffer_Callback write_cb)
39 :progress_handler_(nullptr),
40 status_handler_(nullptr),
41 buffer_callback_(write_cb),
42 task_handler_(std::make_shared<TaskHandler>())
43{
44 content_id_ = root->id();
45 content_name_ = root->name();
46 task_url_ = root->download_url();
47
48 if (!buffer_callback_) {
49 // create temp file path in temp path for writing
50 file_path_ = fs::path(fs::temp_directory_path() / fs::unique_path())
51 .string();
52 }
53
54 task_handler_->on_prepare() = [this](){
55 if (!buffer_callback_) {
56 if (ofs_.is_open())
57 ofs_.close();
58
59 ofs_.open(file_path_, std::ofstream::out | std::ofstream::trunc);
60 if (ofs_.fail()) {
61 throw runtime_error("failed to open file" + file_path_ + " error: " + strerror(errno));
62 }
63 }
64
65 //change status
66 task_handler_->set_status(Task::Status::Running);
67 };
68
69 task_handler_->on_progress() = [this](float percent){
70 if (progress_handler_) {
71 progress_handler_(percent);
72 }
73 };
74
75 task_handler_->on_status() = [this](Task::Status status){
76 if (status_handler_) {
77 status_handler_(status);
78 }
79 };
80
81 task_handler_->on_finished() = [this](const std::string &/*response*/) -> bool {
82 ofs_.close();
83
84 if (!buffer_callback_) {
85 std::string download_dir;
86 if (getenv("ONEDRIVE_DOWNLOAD_FOLDER")) {
87 download_dir = string(getenv("ONEDRIVE_DOWNLOAD_FOLDER"));
88 } else {
89 download_dir = public_download_dir;
90 }
91
92 if (!fs::exists(fs::path(download_dir))) {
93 try {
94 fs::create_directory(fs::path(download_dir));
95 } catch(boost::filesystem::filesystem_error& e) {
96 cerr << "create download directory failed"<< download_dir
97 << "error: " << e.what() << endl;
98 }
99 return false;
100 }
101
102 //check if there is a duplicate one
103 std::string stem = fs::path(content_name_).stem().string();
104 fs::path dest = download_dir + "/" + content_name_;
105 int dup_count = 0;
106 while (fs::exists(dest)) {
107 dest = fs::path(download_dir) / fs::path(stem
108 + "_"
109 + std::to_string(++dup_count)
110 + dest.extension().string());
111 }
112
113 try {
114 // rename in final when download is complete.
115 fs::rename(file_path_, dest);
116 file_path_ = dest.string();
117 } catch (boost::filesystem::filesystem_error& e) {
118 cerr << "create download directory failed"<< download_dir
119 << "error: " << e.what() << endl;
120 return false;
121 }
122 }
123
124 //change status
125 task_handler_->reset_broken_counter();
126 task_handler_->set_status(Task::Status::Complete);
127
128 return true;
129 };
130
131 task_handler_->on_ready_read() = [this](const string &data){
132 if (buffer_callback_) {
133 buffer_callback_((void *)data.c_str(), data.size());
134 } else {
135 ofs_.write(data.c_str(), data.size());
136 }
137 };
138}
139
140const string & DownloadTaskPriv::task_url() const {
141 return task_url_;
142}
143
144Task::Status DownloadTaskPriv::status() const {
145 return task_handler_->status();
146}
147
148const string & DownloadTaskPriv::content_name() const {
149 return content_name_;
150}
151
152const string & DownloadTaskPriv::file_path() const {
153 return file_path_;
154}
155
156const string &DownloadTaskPriv::error_code() const {
157 return error_code_;
158}
159
160Task::ProgressHandler & DownloadTaskPriv::progress_changed() {
161 return progress_handler_;
162}
163
164Task::StatusHandler &DownloadTaskPriv::status_changed() {
165 return status_handler_;
166}
167
168Task::Buffer_Callback &DownloadTaskPriv::buffer_callback() {
169 return buffer_callback_;
170}
171
172const string & DownloadTaskPriv::error_string() const {
173 return error_string_;
174}
175
176void DownloadTaskPriv::set_error_info(const std::string & err) {
177 json::Reader reader;
178 json::Value root;
179 if (reader.parse(err, root)) {
180 error_code_ = root["error"]["code"].asString();
181 error_string_ = root["error"]["message"].asString();
182 } else {
183 error_string_ = err;
184 }
185}
186
187void DownloadTaskPriv::cancel() {
188 task_handler_->cancel();
189}
190
191std::shared_ptr<TaskHandler> DownloadTaskPriv::task_handler() const {
192 return task_handler_;
193}
0194
=== added file 'src/onedrive/api/downloadtask_priv.h'
--- src/onedrive/api/downloadtask_priv.h 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/downloadtask_priv.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,95 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_DOWNLOADTASKPRIV_H_
20#define ONEDRIVE_API_DOWNLOADTASKPRIV_H_
21
22#include <onedrive/api/task.h>
23#include <onedrive/api/clouditem.h>
24
25#include <memory>
26#include <fstream>
27
28namespace onedrive {
29namespace api {
30
31class TaskHandler;
32
33class DownloadTaskPriv {
34public:
35 typedef std::shared_ptr<DownloadTaskPriv> Ptr;
36
37 DownloadTaskPriv(const CloudItem::Ptr &root,
38 Task::Buffer_Callback write_cb = nullptr);
39
40 virtual ~DownloadTaskPriv() = default;
41
42 const std::string & task_url() const;
43
44 Task::Status status() const;
45
46 const std::string & content_id() const;
47
48 const std::string & content_name() const;
49
50 const std::string & file_path() const;
51
52 const std::string & error_code() const;
53
54 const std::string & error_string() const;
55
56 void set_error_info(const std::string & err);
57
58 Task::ProgressHandler & progress_changed();
59
60 Task::StatusHandler & status_changed();
61
62 Task::Buffer_Callback & buffer_callback();
63
64 void cancel();
65
66 std::shared_ptr<TaskHandler> task_handler() const;
67
68private:
69 std::string content_id_;
70
71 std::string content_name_;
72
73 std::string file_path_;
74
75 std::string task_url_;
76
77 std::string error_code_;
78
79 std::string error_string_;
80
81 std::ofstream ofs_;
82
83 Task::ProgressHandler progress_handler_;
84
85 Task::StatusHandler status_handler_;
86
87 Task::Buffer_Callback buffer_callback_;
88
89 std::shared_ptr<TaskHandler> task_handler_;
90};
91
92}
93}
94
95#endif // ONEDRIVE_API_DOWNLOADTASKPRIV_H_
096
=== added file 'src/onedrive/api/storageinfo.cpp'
--- src/onedrive/api/storageinfo.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/storageinfo.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,64 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include <onedrive/api/storageinfo.h>
20
21#include <json/json.h>
22
23using namespace onedrive::api;
24using namespace std;
25
26namespace json = Json;
27
28class StorageInfo::Priv {
29public:
30 Priv(const json::Value &root) {
31 id_ = root["owner"]["user"]["id"].asString();
32 name_ = root["owner"]["user"]["displayName"].asString();
33 disk_size_ = root["quota"]["total"].asUInt64();
34 used_disk_size_ = root["quota"]["used"].asUInt64();
35 }
36
37 string id_;
38
39 string name_;
40
41 int64_t used_disk_size_;
42
43 int64_t disk_size_;
44};
45
46StorageInfo::StorageInfo(const json::Value &root)
47 : p(std::make_shared<Priv>(root)){
48}
49
50int64_t StorageInfo::used_disk_size() const {
51 return p->used_disk_size_;
52}
53
54int64_t StorageInfo::total_disk_size() const {
55 return p->disk_size_;
56}
57
58const string & StorageInfo::id() const {
59 return p->id_;
60}
61
62const string & StorageInfo::name() const {
63 return p->name_;
64}
065
=== added file 'src/onedrive/api/syncmanager.cpp'
--- src/onedrive/api/syncmanager.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/syncmanager.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,70 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19
20#include <onedrive/api/syncmanager.h>
21#include <onedrive/api/taskqueue.h>
22
23#include "syncthread.h"
24#include "client_priv.h"
25#include "syncmanager_priv.h"
26
27#include <iostream>
28
29using namespace onedrive::api;
30using namespace std;
31
32SyncManager::SyncManager(ClientPriv* client_priv)
33 :p_(std::make_shared<SyncManagerPriv>(client_priv)) {
34}
35
36void SyncManager::start() {
37 p_->start();
38}
39
40void SyncManager::cancel() {
41 p_->cancel();
42}
43
44void SyncManager::pause() {
45 p_->pause();
46}
47
48UploadTask::Ptr SyncManager::add_upload_task(const UploadRequest &request_item) {
49 return p_->add_upload_task(request_item);
50}
51
52UploadTask::Ptr SyncManager::add_upload_task(const UploadBufferCb &buffer_cb) {
53 return p_->add_upload_task(buffer_cb);
54}
55
56DownloadTask::Ptr SyncManager::add_download_task(const string &content_id) {
57 return p_->add_download_task(content_id);
58}
59
60DownloadTask::Ptr SyncManager::add_download_task(const DownloadBufferCb &buffer_cb) {
61 return p_->add_download_task(buffer_cb);
62}
63
64TaskQueue<std::shared_ptr<DownloadTask>> SyncManager::download_queue() {
65 return p_->download_queue();
66}
67
68TaskQueue<std::shared_ptr<UploadTask>> SyncManager::upload_queue() {
69 return p_->upload_queue();
70}
071
=== added file 'src/onedrive/api/syncmanager_priv.cpp'
--- src/onedrive/api/syncmanager_priv.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/syncmanager_priv.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,111 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include <onedrive/api/syncmanager.h>
20#include <onedrive/api/taskqueue.h>
21
22#include "syncmanager_priv.h"
23#include "client_priv.h"
24#include "syncthread.h"
25
26#include <iostream>
27
28using namespace onedrive::api;
29using namespace std;
30
31SyncManagerPriv::SyncManagerPriv(ClientPriv *client)
32 : download_thread_()
33 , upload_thread_()
34 , client_(client){
35 start();
36}
37
38SyncManagerPriv::~SyncManagerPriv() {
39 download_thread_.stop();
40 upload_thread_.stop();
41}
42
43void SyncManagerPriv::set_access_token(const std::string &token) {
44 download_thread_.set_access_token(token);
45 upload_thread_.set_access_token(token);
46}
47
48DownloadTask::Ptr SyncManagerPriv::add_download_task(const string &content_id) {
49 auto res = client_->metadata(content_id);
50 auto item = std::static_pointer_cast<CloudItem>(res);
51 auto task_p = std::shared_ptr<DownloadTaskPriv>(new DownloadTaskPriv(item));
52 download_thread_.add_task(task_p);
53
54 auto task = std::shared_ptr<DownloadTask>(new DownloadTask(task_p));
55 download_queue_.push(task);
56 return task;
57}
58
59DownloadTask::Ptr SyncManagerPriv::add_download_task(const DownloadBufferCb &buf_item) {
60 auto res = client_->metadata(buf_item.content_id);
61 auto item = std::static_pointer_cast<CloudItem>(res);
62 auto task_p = std::shared_ptr<DownloadTaskPriv>(new DownloadTaskPriv(item, buf_item.write_cb));
63 download_thread_.add_task(task_p);
64
65 auto task = std::shared_ptr<DownloadTask>(new DownloadTask(task_p));
66 download_queue_.push(task);
67 return task;
68}
69
70UploadTask::Ptr SyncManagerPriv::add_upload_task(const UploadRequest &request) {
71 auto item_p = std::shared_ptr<UploadTaskPriv>(new UploadTaskPriv(request));
72 cout << "push upload link url in queue : " + item_p->task_url() << endl;
73 upload_thread_.add_task(item_p);
74
75 auto item = std::shared_ptr<UploadTask>(new UploadTask(item_p));
76 upload_queue_.push(item);
77 return item;
78}
79
80UploadTask::Ptr SyncManagerPriv::add_upload_task(const UploadBufferCb &buffer_cb) {
81 auto item_p = std::shared_ptr<UploadTaskPriv>(new UploadTaskPriv(buffer_cb));
82 cout << "push upload link url in queue : " + item_p->task_url() << endl;
83 upload_thread_.add_task(item_p);
84
85 auto item = std::shared_ptr<UploadTask>(new UploadTask(item_p));
86 upload_queue_.push(item);
87 return item;
88}
89
90TaskQueue<DownloadTask::Ptr> SyncManagerPriv::download_queue() {
91 return download_queue_;
92}
93
94TaskQueue<UploadTask::Ptr> SyncManagerPriv::upload_queue() {
95 return upload_queue_;
96}
97
98void SyncManagerPriv::start() {
99 download_thread_.start();
100 upload_thread_.start();
101}
102
103void SyncManagerPriv::cancel() {
104 download_thread_.cancel();
105 upload_thread_.cancel();
106}
107
108void SyncManagerPriv::pause() {
109 download_thread_.pause();
110 upload_thread_.pause();
111}
0112
=== added file 'src/onedrive/api/syncmanager_priv.h'
--- src/onedrive/api/syncmanager_priv.h 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/syncmanager_priv.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,76 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_SYNCMANAGERPRIV_H_
20#define ONEDRIVE_API_SYNCMANAGERPRIV_H_
21
22#include <onedrive/api/taskqueue.h>
23#include <onedrive/api/downloadtask.h>
24#include <onedrive/api/uploadtask.h>
25#include <onedrive/api/visibility.h>
26
27#include "syncthread.h"
28
29#include <memory>
30
31namespace onedrive {
32namespace api {
33
34class ClientPriv;
35
36class SyncManagerPriv {
37public:
38 SyncManagerPriv(ClientPriv *client);
39
40 ~SyncManagerPriv();
41
42 void set_access_token(const std::string &token);
43
44 DownloadTask::Ptr add_download_task(const std::string &content_id);
45
46 DownloadTask::Ptr add_download_task(const DownloadBufferCb &buf_item);
47
48 UploadTask::Ptr add_upload_task(const UploadRequest &request);
49
50 UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb);
51
52 TaskQueue<DownloadTask::Ptr> download_queue();
53
54 TaskQueue<UploadTask::Ptr> upload_queue();
55
56 void start();
57
58 void cancel();
59
60 void pause();
61
62private:
63 SyncThread<DownloadTaskPriv> download_thread_;
64 SyncThread<UploadTaskPriv> upload_thread_;
65
66 TaskQueue<DownloadTask::Ptr> download_queue_;
67 TaskQueue<UploadTask::Ptr> upload_queue_;
68
69 ClientPriv* client_;
70};
71
72
73}
74}
75
76#endif // ONEDRIVE_API_SYNCMANAGERPRIV_H_
077
=== added file 'src/onedrive/api/syncthread.cpp'
--- src/onedrive/api/syncthread.cpp 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/syncthread.cpp 2016-09-30 08:26:58 +0000
@@ -0,0 +1,447 @@
1/*
2 * Copyright © 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Gary Wang <gary.wang@canonical.com>
17 */
18
19#include "syncthread.h"
20#include "taskhandler.h"
21#include "uploadtask_priv.h"
22#include "downloadtask_priv.h"
23
24#include <boost/algorithm/string.hpp>
25#include <core/net/http/streaming_client.h>
26#include <core/net/http/streaming_request.h>
27#include <core/net/http/response.h>
28#include <core/net/http/status.h>
29
30#include <fstream>
31#include <future>
32#include <iostream>
33
34namespace http = core::net::http;
35namespace net = core::net;
36
37using namespace onedrive::api;
38using namespace std;
39
40template <typename T>
41class SyncThread<T>::HttpStreamClient {
42public:
43 HttpStreamClient(int request_timeout) :
44 request_timeout_(request_timeout),
45 client_(http::make_streaming_client()),
46 worker_ { [this]() {client_->run();} }{
47 }
48
49 ~HttpStreamClient() {
50 client_->stop();
51 if (worker_.joinable()) {
52 worker_.join();
53 }
54 }
55
56 void async_get(shared_ptr<T> ptr,
57 const http::Header &headers) {
58 auto prom = make_shared<promise<bool>>();
59
60 auto task_handler = ptr->task_handler();
61 http::Request::Handler handler;
62 handler.on_progress([task_handler](const http::Request::Progress& progress)
63 {
64 if (task_handler->status() == Task::Status::Canceled) {
65 return http::Request::Progress::Next::abort_operation;
66 }
67
68 if (progress.download.current > 0.0 && progress.download.total > 0.0) {
69 double percent = progress.download.current / progress.download.total;
70 task_handler->on_progress()(percent);
71 }
72
73 return http::Request::Progress::Next::continue_operation;
74 }
75 );
76 handler.on_error([prom](const net::Error& e)
77 {
78 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
79 });
80 handler.on_response([prom, task_handler](const http::Response& response)
81 {
82 if (response.status != http::Status::ok) {
83 prom->set_exception(make_exception_ptr(runtime_error(response.body)));
84 } else {
85 prom->set_value(task_handler->on_finished()(response.body));
86 }
87 }
88 );
89
90 auto http_config = http::Request::Configuration::from_uri_as_string(
91 ptr->task_url());
92 http_config.header = headers;
93
94 std::shared_future<bool> future = prom->get_future();
95 auto request = client_->streaming_get(http_config);
96 request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time});
97 request->set_timeout(std::chrono::milliseconds{request_timeout_});
98 request->async_execute(handler, task_handler->on_ready_read());
99
100 task_handler->attach_request(request, future);
101 }
102
103 void async_put(shared_ptr<T> ptr,
104 const http::Header &headers,
105 std::istream &payload,
106 std::size_t size) {
107 auto prom = make_shared<promise<bool>>();
108
109 auto task_handler = ptr->task_handler();
110 http::Request::Handler handler;
111 handler.on_progress([task_handler](const http::Request::Progress& progress)
112 {
113 if (task_handler->status() == Task::Status::Canceled) {
114 return http::Request::Progress::Next::abort_operation;
115 }
116
117 if (progress.upload.current > 0.0 && progress.upload.total > 0.0) {
118 double percent = (progress.upload.current / progress.upload.total);
119 task_handler->on_progress()(percent);
120 }
121
122 return http::Request::Progress::Next::continue_operation;
123 }
124 );
125 handler.on_error([prom](const net::Error& e)
126 {
127 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
128 });
129 handler.on_response([prom, task_handler](const http::Response& response)
130 {
131 if (response.status != http::Status::ok &&
132 response.status != http::Status::created) {
133 prom->set_exception(make_exception_ptr(runtime_error(response.body)));
134 } else {
135 prom->set_value(task_handler->on_finished()(response.body));
136 }
137 }
138 );
139
140 auto http_config = http::Request::Configuration::from_uri_as_string(
141 ptr->task_url());
142 http_config.header = headers;
143
144 std::shared_future<bool> future = prom->get_future();
145 auto request = client_->streaming_put(http_config, payload, size);
146 request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time});
147 request->set_timeout(std::chrono::milliseconds{request_timeout_});
148 request->async_execute(handler, task_handler->on_ready_read());
149
150 task_handler->attach_request(request, future);
151 }
152
153 void async_put(shared_ptr<T> ptr,
154 const http::Header &headers,
155 std::function<size_t(void *dest, size_t buf_size)> read_cb,
156 std::size_t size) {
157 auto prom = make_shared<promise<bool>>();
158
159 auto task_handler = ptr->task_handler();
160 http::Request::Handler handler;
161 handler.on_progress([task_handler](const http::Request::Progress& progress)
162 {
163 if (task_handler->status() == Task::Status::Canceled) {
164 return http::Request::Progress::Next::abort_operation;
165 }
166
167 if (progress.upload.current > 0.0 && progress.upload.total > 0.0) {
168 double percent = (progress.upload.current / progress.upload.total);
169 task_handler->on_progress()(percent);
170 }
171
172 return http::Request::Progress::Next::continue_operation;
173 }
174 );
175 handler.on_error([prom](const net::Error& e)
176 {
177 prom->set_exception(make_exception_ptr(runtime_error(e.what())));
178 });
179 handler.on_response([prom, task_handler](const http::Response& response)
180 {
181 if (response.status != http::Status::ok &&
182 response.status != http::Status::created) {
183 prom->set_exception(make_exception_ptr(runtime_error(response.body)));
184 } else {
185 prom->set_value(task_handler->on_finished()(response.body));
186 }
187 }
188 );
189
190 auto http_config = http::Request::Configuration::from_uri_as_string(
191 ptr->task_url());
192 http_config.header = headers;
193
194 std::shared_future<bool> future = prom->get_future();
195 auto request = client_->streaming_put(http_config, read_cb, size);
196 request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time});
197 request->set_timeout(std::chrono::milliseconds{request_timeout_});
198 request->async_execute(handler, task_handler->on_ready_read());
199
200 task_handler->attach_request(request, future);
201 }
202
203 const int low_speed_limit = 1;
204
205 const chrono::seconds low_speed_time{chrono::seconds{10}};
206
207 int request_timeout_;
208
209 std::shared_ptr<core::net::http::StreamingClient> client_;
210
211 std::thread worker_;
212};
213
214template<typename T>
215SyncThread<T>::SyncThread()
216 : client_(std::make_shared<SyncThread::HttpStreamClient>(sync_timeout_ * 500)),
217 stop_(true){
218}
219
220template <typename T>
221SyncThread<T>::~SyncThread() {
222 stop();
223}
224
225template <typename T>
226void SyncThread<T>::start() {
227 pause_ = false;
228
229 if (stop_ == true) {
230 stop_ = false;
231 thread_ = std::thread(&SyncThread::run, this);
232 } else {
233 //if it's running, then resume
234 for (auto & item_ptr : task_queue_) {
235 if (item_ptr->status() == Task::Status::Paused) {
236 item_ptr->task_handler()->resume();
237 }
238 }
239 }
240}
241
242template <typename T>
243void SyncThread<T>::cancel() {
244 stop();
245}
246
247template <typename T>
248void SyncThread<T>::pause() {
249 std::unique_lock<std::mutex> lock(mutex_);
250
251 //pause task if it's running
252 for (auto & item_ptr : task_queue_) {
253 if (item_ptr->status() == Task::Status::Running) {
254 item_ptr->task_handler()->pause();
255 }
256 }
257
258 pause_ = true;
259}
260
261template <typename T>
262void SyncThread<T>::stop() {
263 //cancel task if it's running or prepared in the queue.
264 for (auto & item_ptr : task_queue_) {
265 if (item_ptr->status() == Task::Status::Running
266 || item_ptr->status() == Task::Status::Paused
267 || item_ptr->status() == Task::Status::Unstart) {
268 item_ptr->task_handler()->cancel();
269 }
270 }
271
272 {
273 std::unique_lock<std::mutex> lock(mutex_);
274 if (stop_)
275 return;
276
277 //terminate thread
278 stop_ = true;
279 con_.notify_all();
280 }
281
282 if (thread_.joinable())
283 thread_.join();
284}
285
286template <typename T>
287void SyncThread<T>::set_access_token(const std::string &token) {
288 access_token_ = token;
289}
290
291template <typename T>
292void SyncThread<T>::add_task(std::shared_ptr<T> task_ptr) {
293 task_queue_.push(task_ptr);
294}
295
296template <typename T>
297void SyncThread<T>::run() {
298 std::unique_lock<std::mutex> lock(mutex_);
299
300 std::future_status status = std::future_status::ready;
301 std::shared_ptr<DownloadTaskPriv> task_ptr = nullptr;
302
303 while(!stop_) {
304 con_.wait_for(lock, std::chrono::seconds(sync_timeout_));
305 if (!stop_ && !pause_) {
306 if (status == std::future_status::ready) {
307 //check if there is unstared task item in task queue
308 typename TaskQueue<std::shared_ptr<T>>::const_iterator it = std::find_if(
309 task_queue_.begin(),
310 task_queue_.end(),
311 [](std::shared_ptr<T> task){
312 return (task->status() == Task::Status::Unstart);
313 });
314
315 if (it == task_queue_.end())
316 continue;
317
318 http::Header header;
319 header.add("Authorization", "bearer " + access_token_);
320 task_ptr = (*it);
321 try {
322 task_ptr->task_handler()->on_prepare()();
323 } catch (std::runtime_error e) {
324 cerr << "error: " << e.what() << endl;
325 continue;
326 }
327 client_->async_get(task_ptr, header);
328 }
329
330 if (task_ptr) {
331 auto task_handler = task_ptr->task_handler();
332 //do not wait block here forever until download is finished,
333 //that gives a chance to pause/resume download from sync thread.
334 status = task_handler->wait_for(std::chrono::seconds(sync_timeout_));
335 try {
336 if (status == std::future_status::ready &&
337 task_handler->get_result()) {
338 cout << "download content successfully:" <<
339 task_ptr->file_path() << endl;
340 task_handler->detach_request();
341 task_ptr.reset();
342 }
343 } catch(std::runtime_error &e) {
344 // if error is caused by net issue,not manually(application callback)
345 // increase broken counter and try it again. Once broken counter exceeds broken limit,
346 // it's regarded as the "broken" one and drop it
347 if (task_handler->status() != Task::Status::Canceled) {
348 if (!task_handler->is_broken()) {
349 task_handler->add_broken_counter();
350 task_handler->set_status(Task::Status::Unstart);
351 } else {
352 task_ptr->set_error_info(e.what());
353 task_handler->set_status(Task::Status::Broken);
354 }
355 }
356
357 cerr << "download content: "<< task_ptr->content_name()
358 << " error: " << e.what() << endl;
359 task_ptr.reset();
360 }
361 }
362 }
363 }
364}
365
366namespace onedrive {
367namespace api {
368
369template <>
370void SyncThread<UploadTaskPriv>::run() {
371 std::unique_lock<std::mutex> lock(mutex_);
372
373 std::future_status status = std::future_status::ready;
374 UploadTaskPriv::Ptr task_ptr = nullptr;
375 while(!stop_) {
376 con_.wait_for(lock, std::chrono::seconds(sync_timeout_));
377
378 if (!stop_ && !pause_) {
379 if (status == std::future_status::ready) {
380 //check if there is unstared task item in task queue
381 typename TaskQueue<UploadTaskPriv::Ptr>::const_iterator it = std::find_if(
382 task_queue_.begin(),
383 task_queue_.end(),
384 [](UploadTaskPriv::Ptr task){
385 return (task->status() == Task::Status::Unstart);
386 });
387
388 if (it == task_queue_.end())
389 continue;
390
391 http::Header header;
392 header.add("Authorization", "bearer " + access_token_);
393 task_ptr = (*it);
394 task_ptr->task_handler()->on_prepare()();
395 if (task_ptr->buffer_callback()) {
396 client_->async_put(task_ptr, header, task_ptr->buffer_callback(), task_ptr->file_size());
397 } else {
398 client_->async_put(task_ptr, header, task_ptr->ifstream(), task_ptr->file_size());
399 }
400 }
401
402 if (task_ptr) {
403 auto task_handler = task_ptr->task_handler();
404 //do not wait block here forever until upload is finished,
405 //that gives a chance to pause/resume upload from sync thread.
406 status = task_handler->wait_for(std::chrono::seconds(sync_timeout_));
407 try {
408 if (status == std::future_status::ready &&
409 task_handler->get_result()) {
410 cout << "upload content successfully:" << task_ptr->content_name() << endl;
411 task_handler->detach_request();
412 task_ptr.reset();
413 }
414 }catch (std::runtime_error &e) {
415 //if content data is fetched chunk by chunk(buffering), set it broken once failed
416 //as we didn't cache buffer locally.
417 if (task_ptr->buffer_callback()) {
418 task_ptr->set_error_info(e.what());
419 task_handler->set_status(Task::Status::Broken);
420 } else if (task_handler->status() != Task::Status::Canceled) {
421 // if content data is local file, when error is caused by net issue,
422 //increase broken counter and try it again. Once broken counter exceeds broken limit,
423 //it's regarded as the "broken" one and we drop it.
424
425 if (!task_handler->is_broken()) {
426 task_handler->add_broken_counter();
427 task_handler->set_status(Task::Status::Unstart);
428 } else {
429 task_ptr->set_error_info(e.what());
430 task_handler->set_status(Task::Status::Broken);
431 }
432 }
433
434 cerr << "upload content: "<< task_ptr->content_name()
435 << " error: " << e.what() << endl;
436 task_ptr.reset();
437 }
438 }
439 }
440 }
441}
442
443}
444}
445
446template class SyncThread<DownloadTaskPriv>;
447template class SyncThread<UploadTaskPriv>;
0448
=== added file 'src/onedrive/api/syncthread.h'
--- src/onedrive/api/syncthread.h 1970-01-01 00:00:00 +0000
+++ src/onedrive/api/syncthread.h 2016-09-30 08:26:58 +0000
@@ -0,0 +1,81 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Gary Wang <gary.wang@canonical.com>
17 */
18
19#ifndef ONEDRIVE_API_SYNCTHREAD_H_
20#define ONEDRIVE_API_SYNCTHREAD_H_
21
22#include <onedrive/api/taskqueue.h>
23#include <onedrive/api/visibility.h>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: