Merge lp:~gary-wzl77/storage-provider-onedrive/upload into lp:storage-provider-onedrive/devel
- upload
- Merge into devel
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 |
Related bugs: |
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.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:9
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:11
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:12
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:13
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:14
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:15
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === added directory '.bzr-builddeb' | |||
2 | === added file '.bzr-builddeb/default.conf' | |||
3 | --- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000 | |||
4 | +++ .bzr-builddeb/default.conf 2016-09-30 08:26:58 +0000 | |||
5 | @@ -0,0 +1,2 @@ | |||
6 | 1 | [BUILDDEB] | ||
7 | 2 | split = True | ||
8 | 0 | 3 | ||
9 | === modified file 'CMakeLists.txt' | |||
10 | --- CMakeLists.txt 2016-09-26 04:27:03 +0000 | |||
11 | +++ CMakeLists.txt 2016-09-30 08:26:58 +0000 | |||
12 | @@ -16,7 +16,7 @@ | |||
13 | 16 | 16 | ||
14 | 17 | cmake_minimum_required(VERSION 2.8) | 17 | cmake_minimum_required(VERSION 2.8) |
15 | 18 | 18 | ||
17 | 19 | project(onedrive) | 19 | project(onedrive-provider) |
18 | 20 | 20 | ||
19 | 21 | include(GNUInstallDirs) | 21 | include(GNUInstallDirs) |
20 | 22 | 22 | ||
21 | @@ -26,9 +26,9 @@ | |||
22 | 26 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra") | 26 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra") |
23 | 27 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") | 27 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") |
24 | 28 | 28 | ||
28 | 29 | set(ONEDRIVE_LIB_VERSION_MAJOR 0) | 29 | set(ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR 0) |
29 | 30 | set(ONEDRIVE_LIB_VERSION_MINOR 0) | 30 | set(ONEDRIVE_PROVIDER_LIB_VERSION_MINOR 0) |
30 | 31 | set(ONEDRIVE_LIB_VERSION_PATCH 1) | 31 | set(ONEDRIVE_PROVIDER_LIB_VERSION_PATCH 1) |
31 | 32 | 32 | ||
32 | 33 | include(CTest) | 33 | include(CTest) |
33 | 34 | 34 | ||
34 | @@ -36,7 +36,7 @@ | |||
35 | 36 | include/ | 36 | include/ |
36 | 37 | ) | 37 | ) |
37 | 38 | 38 | ||
39 | 39 | file(GLOB_RECURSE ONEDRIVE_LIB_INTERFACE_HEADERS include/*.h) | 39 | file(GLOB_RECURSE ONEDRIVE_PROVIDER_LIB_INTERFACE_HEADERS include/*.h) |
40 | 40 | 40 | ||
41 | 41 | include(EnableCoverageReport) | 41 | include(EnableCoverageReport) |
42 | 42 | 42 | ||
43 | @@ -45,11 +45,12 @@ | |||
44 | 45 | add_subdirectory(include) | 45 | add_subdirectory(include) |
45 | 46 | add_subdirectory(src) | 46 | add_subdirectory(src) |
46 | 47 | add_subdirectory(tests) | 47 | add_subdirectory(tests) |
48 | 48 | add_subdirectory(provider) | 48 | #add_subdirectory(provider) |
49 | 49 | 49 | ||
50 | 50 | enable_coverage_report( | 50 | enable_coverage_report( |
51 | 51 | TARGETS | 51 | TARGETS |
53 | 52 | onedrive | 52 | onedrive-provider |
54 | 53 | #onedrive-provider-bin | ||
55 | 53 | FILTER | 54 | FILTER |
56 | 54 | ${CMAKE_SOURCE_DIR}/test/* | 55 | ${CMAKE_SOURCE_DIR}/test/* |
57 | 55 | ${CMAKE_BINARY_DIR}/* | 56 | ${CMAKE_BINARY_DIR}/* |
58 | 56 | 57 | ||
59 | === modified file 'data/CMakeLists.txt' | |||
60 | --- data/CMakeLists.txt 2016-09-26 04:27:03 +0000 | |||
61 | +++ data/CMakeLists.txt 2016-09-30 08:26:58 +0000 | |||
62 | @@ -15,10 +15,10 @@ | |||
63 | 15 | # Authored by: Gary Wang <gary.wang@canonical.com> | 15 | # Authored by: Gary Wang <gary.wang@canonical.com> |
64 | 16 | 16 | ||
65 | 17 | configure_file( | 17 | configure_file( |
67 | 18 | onedrive.pc.in onedrive.pc @ONLY | 18 | onedrive-provider.pc.in onedrive-provider.pc @ONLY |
68 | 19 | ) | 19 | ) |
69 | 20 | 20 | ||
70 | 21 | install( | 21 | install( |
72 | 22 | FILES ${CMAKE_CURRENT_BINARY_DIR}/onedrive.pc | 22 | FILES ${CMAKE_CURRENT_BINARY_DIR}/onedrive-provider.pc |
73 | 23 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig | 23 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig |
74 | 24 | ) | 24 | ) |
75 | 25 | 25 | ||
76 | === added file 'data/onedrive-provider.pc.in' | |||
77 | --- data/onedrive-provider.pc.in 1970-01-01 00:00:00 +0000 | |||
78 | +++ data/onedrive-provider.pc.in 2016-09-30 08:26:58 +0000 | |||
79 | @@ -0,0 +1,10 @@ | |||
80 | 1 | prefix=@CMAKE_INSTALL_PREFIX@ | ||
81 | 2 | exec_prefix=${prefix} | ||
82 | 3 | libdir=${exec_prefix}/lib | ||
83 | 4 | includedir=${exec_prefix}/include | ||
84 | 5 | |||
85 | 6 | Name: @CMAKE_PROJECT_NAME@ | ||
86 | 7 | Description: Cloud based content sharing library for Microsoft Onedrive service | ||
87 | 8 | Version: @ONEDRIVE_LIB_VERSION_MAJOR@.@ONEDRIVE_LIB_VERSION_MINOR@.@ONEDRIVE_LIB_VERSION_PATCH@ | ||
88 | 9 | Libs: -L${libdir} -lonedrive | ||
89 | 10 | Cflags: -I${includedir} | ||
90 | 0 | 11 | ||
91 | === removed file 'data/onedrive.pc.in' | |||
92 | --- data/onedrive.pc.in 2016-09-26 04:27:03 +0000 | |||
93 | +++ data/onedrive.pc.in 1970-01-01 00:00:00 +0000 | |||
94 | @@ -1,10 +0,0 @@ | |||
95 | 1 | prefix=@CMAKE_INSTALL_PREFIX@ | ||
96 | 2 | exec_prefix=${prefix} | ||
97 | 3 | libdir=${exec_prefix}/lib | ||
98 | 4 | includedir=${exec_prefix}/include | ||
99 | 5 | |||
100 | 6 | Name: @CMAKE_PROJECT_NAME@ | ||
101 | 7 | Description: Cloud based content sharing library for Microsoft Onedrive service | ||
102 | 8 | Version: @ONEDRIVE_LIB_VERSION_MAJOR@.@ONEDRIVE_LIB_VERSION_MINOR@.@ONEDRIVE_LIB_VERSION_PATCH@ | ||
103 | 9 | Libs: -L${libdir} -lonedrive | ||
104 | 10 | Cflags: -I${includedir} | ||
105 | 11 | 0 | ||
106 | === modified file 'debian/control' | |||
107 | --- debian/control 2016-09-30 05:26:58 +0000 | |||
108 | +++ debian/control 2016-09-30 08:26:58 +0000 | |||
109 | @@ -2,11 +2,12 @@ | |||
110 | 2 | Priority: optional | 2 | Priority: optional |
111 | 3 | Maintainer: Gary Wang <gary.wang@canonical.com> | 3 | Maintainer: Gary Wang <gary.wang@canonical.com> |
112 | 4 | Build-Depends: cmake, | 4 | Build-Depends: cmake, |
113 | 5 | cmake-extras (>= 0.4), | ||
114 | 5 | debhelper (>= 9), | 6 | debhelper (>= 9), |
115 | 6 | doxygen, | 7 | doxygen, |
116 | 7 | google-mock, | 8 | google-mock, |
117 | 8 | graphviz, | 9 | graphviz, |
119 | 9 | libnet-cpp-dev, | 10 | libnet-cpp-dev (>= 2.0.0), |
120 | 10 | libboost-dev (>= 1.58) | libboost1.58-dev, | 11 | libboost-dev (>= 1.58) | libboost1.58-dev, |
121 | 11 | libboost-filesystem-dev (>= 1.58) | libboost-filesystem1.58-dev, | 12 | libboost-filesystem-dev (>= 1.58) | libboost-filesystem1.58-dev, |
122 | 12 | libboost-system-dev (>= 1.58) | libboost-system1.58-dev, | 13 | libboost-system-dev (>= 1.58) | libboost-system1.58-dev, |
123 | 13 | 14 | ||
124 | === modified file 'debian/onedrive-provider0.install' | |||
125 | --- debian/onedrive-provider0.install 2016-09-30 05:26:58 +0000 | |||
126 | +++ debian/onedrive-provider0.install 2016-09-30 08:26:58 +0000 | |||
127 | @@ -1,3 +1,1 @@ | |||
128 | 1 | usr/lib/*/lib*.so.* | 1 | usr/lib/*/lib*.so.* |
129 | 2 | usr/bin/* | ||
130 | 3 | usr/share/dbus-1/services/* | ||
131 | 4 | 2 | ||
132 | === modified file 'doc/Doxyfile.in' | |||
133 | --- doc/Doxyfile.in 2016-09-26 04:27:03 +0000 | |||
134 | +++ doc/Doxyfile.in 2016-09-30 08:26:58 +0000 | |||
135 | @@ -32,13 +32,13 @@ | |||
136 | 32 | # This could be handy for archiving the generated documentation or | 32 | # This could be handy for archiving the generated documentation or |
137 | 33 | # if some version control system is used. | 33 | # if some version control system is used. |
138 | 34 | 34 | ||
140 | 35 | PROJECT_NUMBER = @ONEDIRVE_LIB_VERSION_MAJOR@.@ONEDIRVE_LIB_VERSION_MINOR@.@ONEDIRVE_LIB_VERSION_PATCH@ | 35 | PROJECT_NUMBER = @ONEDIRVE_PROVIDER_LIB_VERSION_MAJOR@.@ONEDIRVE_PROVIDER_LIB_VERSION_MINOR@.@ONEDIRVE_PROVIDER_LIB_VERSION_PATCH@ |
141 | 36 | 36 | ||
142 | 37 | # Using the PROJECT_BRIEF tag one can provide an optional one line description | 37 | # Using the PROJECT_BRIEF tag one can provide an optional one line description |
143 | 38 | # for a project that appears at the top of each page and should give viewer | 38 | # for a project that appears at the top of each page and should give viewer |
144 | 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. |
145 | 40 | 40 | ||
147 | 41 | PROJECT_BRIEF = "Onedrive API library For Microsoft OneDrive Service" | 41 | PROJECT_BRIEF = "Onedrive API library For Microsoft OneDrive Service and a Storage Provider." |
148 | 42 | 42 | ||
149 | 43 | # With the PROJECT_LOGO tag one can specify an logo or icon that is | 43 | # With the PROJECT_LOGO tag one can specify an logo or icon that is |
150 | 44 | # included in the documentation. The maximum height of the logo should not | 44 | # included in the documentation. The maximum height of the logo should not |
151 | 45 | 45 | ||
152 | === added file 'include/onedrive/api/client.h' | |||
153 | --- include/onedrive/api/client.h 1970-01-01 00:00:00 +0000 | |||
154 | +++ include/onedrive/api/client.h 2016-09-30 08:26:58 +0000 | |||
155 | @@ -0,0 +1,203 @@ | |||
156 | 1 | /* | ||
157 | 2 | * Copyright © 2016 Canonical Ltd. | ||
158 | 3 | * | ||
159 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
160 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
161 | 6 | * as published by the Free Software Foundation. | ||
162 | 7 | * | ||
163 | 8 | * This program is distributed in the hope that it will be useful, | ||
164 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
165 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
166 | 11 | * GNU Lesser General Public License for more details. | ||
167 | 12 | * | ||
168 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
169 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
170 | 15 | * | ||
171 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
172 | 17 | */ | ||
173 | 18 | |||
174 | 19 | #ifndef ONEDRIVE_API_CLIENT_H_ | ||
175 | 20 | #define ONEDRIVE_API_CLIENT_H_ | ||
176 | 21 | |||
177 | 22 | #include <onedrive/api/visibility.h> | ||
178 | 23 | #include <onedrive/api/taskqueue.h> | ||
179 | 24 | #include <onedrive/api/storageinfo.h> | ||
180 | 25 | #include <onedrive/api/cloudresource.h> | ||
181 | 26 | #include <onedrive/api/clouditem.h> | ||
182 | 27 | #include <onedrive/api/cloudfolder.h> | ||
183 | 28 | #include <onedrive/api/downloadtask.h> | ||
184 | 29 | #include <onedrive/api/uploadtask.h> | ||
185 | 30 | #include <onedrive/api/syncmanager.h> | ||
186 | 31 | |||
187 | 32 | #include <deque> | ||
188 | 33 | |||
189 | 34 | namespace onedrive { | ||
190 | 35 | namespace api { | ||
191 | 36 | |||
192 | 37 | class ClientPriv; | ||
193 | 38 | |||
194 | 39 | /*! | ||
195 | 40 | \class Client | ||
196 | 41 | \brief Onedrive API provides developer to easily access login user's cloud contents stored on microsoft onedrive service, | ||
197 | 42 | such as musics, movie, docs, images, and so on. | ||
198 | 43 | |||
199 | 44 | The API enable developers to | ||
200 | 45 | <list type="bullet"> | ||
201 | 46 | <item>retrieve authorized user cloud content list.</item> | ||
202 | 47 | <item>create, delete, move and update cloud resources.</item> | ||
203 | 48 | <item>query content infomation.</item> | ||
204 | 49 | <item>create an extranet link to share.</item> | ||
205 | 50 | <item>upload a local content to onedrive.</item> | ||
206 | 51 | <item>download a content from onedrive.</item> | ||
207 | 52 | </list> | ||
208 | 53 | |||
209 | 54 | Also sync up manager will be running on the background when client is constructed. It handles over | ||
210 | 55 | local content upload and cloud item download. \sa syncmanager. | ||
211 | 56 | |||
212 | 57 | \note Onedrive API covers cloud resourece access and content sync-up between local and cloud. It does not take | ||
213 | 58 | responsibility of account authentication. So before using onedrive APIs, developers need to call \sa set_access_token to | ||
214 | 59 | manually set a valid access_token or \sa refresh_token to fetch access token, | ||
215 | 60 | which is used to call onedrive APIs internally to pass through authentication. | ||
216 | 61 | */ | ||
217 | 62 | |||
218 | 63 | class ONEDRIVE_API_DLL_PUBLIC Client { | ||
219 | 64 | |||
220 | 65 | public: | ||
221 | 66 | typedef std::shared_ptr<Client> Ptr; | ||
222 | 67 | |||
223 | 68 | typedef std::deque<CloudResource::Ptr> ResourceList; | ||
224 | 69 | |||
225 | 70 | typedef std::vector<std::string> Stringlist; | ||
226 | 71 | |||
227 | 72 | /*! | ||
228 | 73 | * \brief Constructs a onedrive Client object with \a request_timeout seconds. | ||
229 | 74 | * Meanwhile client launches sync-up manager to deal with task download and upload by default. | ||
230 | 75 | */ | ||
231 | 76 | Client(int request_timeout = 10); | ||
232 | 77 | |||
233 | 78 | Client(const Client&) = delete; | ||
234 | 79 | |||
235 | 80 | Client& operator=(const Client&) = delete; | ||
236 | 81 | |||
237 | 82 | virtual ~Client(); | ||
238 | 83 | |||
239 | 84 | /*! | ||
240 | 85 | * \brief Set \a access_token to authenticate all onedrive API calls with the bearer HTTP authorization scheme. | ||
241 | 86 | * The access token can be fetched through ubuntu sso services. | ||
242 | 87 | */ | ||
243 | 88 | void set_access_token(const std::string &access_token); | ||
244 | 89 | |||
245 | 90 | /*! | ||
246 | 91 | * \brief Retrieves and refreshes access token by using \a refresh_token. | ||
247 | 92 | * The refresh token can be fetched through ubuntu sso services. | ||
248 | 93 | * \throw std::runtime_error if error occurs. | ||
249 | 94 | * \returns true if access token is refreshed, otherwise returns false. | ||
250 | 95 | */ | ||
251 | 96 | // bool refresh_token(const std::string &refresh_token); | ||
252 | 97 | |||
253 | 98 | /*! | ||
254 | 99 | * \brief Returns login user's onedrive cloud storage information. | ||
255 | 100 | * \throw std::runtime_error if error occurs. | ||
256 | 101 | * @sa UserInfo | ||
257 | 102 | */ | ||
258 | 103 | StorageInfo storage_info(); | ||
259 | 104 | |||
260 | 105 | /*! | ||
261 | 106 | * \brief Returns root folder object on onedrive. | ||
262 | 107 | * \throw std::runtime_error if error occurs. | ||
263 | 108 | * \sa cloud_content_list(), storage_info() | ||
264 | 109 | */ | ||
265 | 110 | CloudFolder::Ptr root_folder(); | ||
266 | 111 | |||
267 | 112 | /*! | ||
268 | 113 | * \brief Returns cloud item list and next page token when querying one specific folder \a folder_id. | ||
269 | 114 | * if \a folder_id is empty, returns item list under root directory of onedrive. | ||
270 | 115 | * if \a page_token is empty, queries contents from the first page. | ||
271 | 116 | * The fetched content count is 200 at most per call. | ||
272 | 117 | * \a page_token indicates the specific page index on the onedrive. | ||
273 | 118 | * \throw std::runtime_error if error occurs. | ||
274 | 119 | * \sa root_folder(), metadata(), search() | ||
275 | 120 | */ | ||
276 | 121 | std::tuple<ResourceList, std::string> cloud_content_list(const std::string &folder_id = std::string(), | ||
277 | 122 | const std::string &page_token = std::string()); | ||
278 | 123 | |||
279 | 124 | /*! | ||
280 | 125 | * \brief Returns a resouce item object if content with a given \a content_id can be found on onedrive. | ||
281 | 126 | * otherwise return nullptr. | ||
282 | 127 | * \throw std::runtime_error if error occurs. | ||
283 | 128 | * \sa cloud_content_list() | ||
284 | 129 | */ | ||
285 | 130 | CloudResource::Ptr metadata(const std::string & content_id); | ||
286 | 131 | |||
287 | 132 | /*! | ||
288 | 133 | * \brief Returns a folder item object if a folder \a folder_name is created under a given \a folder_id folder, | ||
289 | 134 | * otherwise return nullptr. | ||
290 | 135 | * if \a folder_id is empty, creates a folder item under root folder of onedrive. | ||
291 | 136 | * \throw std::runtime_error if error occurs. | ||
292 | 137 | * \sa delete_item(), move_item(), copy_item() | ||
293 | 138 | */ | ||
294 | 139 | CloudFolder::Ptr create_folder(const std::string &folder_name, | ||
295 | 140 | const std::string &folder_id = std::string()); | ||
296 | 141 | |||
297 | 142 | /*! | ||
298 | 143 | * \brief Returns a cloud item list if there are available items that matches with \a name under a given \a folder_id folder. | ||
299 | 144 | * if \a folder_id is empty, searches items under root folder of onedrive. | ||
300 | 145 | * \throw std::runtime_error if error occurs. | ||
301 | 146 | * \sa delete_item(), metadata() | ||
302 | 147 | */ | ||
303 | 148 | Client::ResourceList search(const std::string &name, | ||
304 | 149 | const std::string &folder_id = std::string()); | ||
305 | 150 | |||
306 | 151 | /*! | ||
307 | 152 | * \brief Returns true if content \a content_id is deleted, otherwise return false. | ||
308 | 153 | * \throw std::runtime_error if error occurs. | ||
309 | 154 | * \sa move_item(), metadata(), copy_item() | ||
310 | 155 | */ | ||
311 | 156 | bool delete_item(const std::string &content_id); | ||
312 | 157 | |||
313 | 158 | /*! | ||
314 | 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. | ||
315 | 160 | * otherwise return nullptr. | ||
316 | 161 | * \throw std::runtime_error if error occurs. | ||
317 | 162 | * \sa move_item(), update_folder(), delete_item() | ||
318 | 163 | CloudResource::Ptr copy_item(const std::string &item_id, | ||
319 | 164 | const std::string &name, | ||
320 | 165 | const std::string &folder_id); | ||
321 | 166 | */ | ||
322 | 167 | |||
323 | 168 | /*! | ||
324 | 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 . | ||
325 | 170 | * otherwise return nullptr. | ||
326 | 171 | * if item_name is empty, name will not changed after moving to a new folder. | ||
327 | 172 | * \throw std::runtime_error if error occurs. | ||
328 | 173 | * \sa move_item(), update_folder(), delete_item() | ||
329 | 174 | */ | ||
330 | 175 | CloudResource::Ptr move_item(const std::string &item_id, | ||
331 | 176 | const std::string &folder_id, | ||
332 | 177 | const std::string &item_name = std::string()); | ||
333 | 178 | |||
334 | 179 | /*! | ||
335 | 180 | * \brief Returns a resource item object if an item \a item_id is updated with \a new name, otherwise return false. | ||
336 | 181 | * otherwise return nullptr. | ||
337 | 182 | * \throw std::runtime_error if error occurs. | ||
338 | 183 | * \sa delete_contents(), copy_folders(), | ||
339 | 184 | */ | ||
340 | 185 | CloudResource::Ptr rename_item(const std::string &folder_id, | ||
341 | 186 | const std::string &new_folder_name); | ||
342 | 187 | |||
343 | 188 | |||
344 | 189 | /*! | ||
345 | 190 | * \brief Returns a sync-up manager running on the background. | ||
346 | 191 | * sync-up manager scheduled tasks \sa start, pause, cancel for content upload and download. | ||
347 | 192 | */ | ||
348 | 193 | SyncManager::Ptr syncmanager() const; | ||
349 | 194 | |||
350 | 195 | private: | ||
351 | 196 | std::shared_ptr<ClientPriv> p; | ||
352 | 197 | |||
353 | 198 | }; | ||
354 | 199 | |||
355 | 200 | } | ||
356 | 201 | } | ||
357 | 202 | |||
358 | 203 | #endif // ONEDRIVE_API_CLIENT_H_ | ||
359 | 0 | 204 | ||
360 | === added file 'include/onedrive/api/cloudfolder.h' | |||
361 | --- include/onedrive/api/cloudfolder.h 1970-01-01 00:00:00 +0000 | |||
362 | +++ include/onedrive/api/cloudfolder.h 2016-09-30 08:26:58 +0000 | |||
363 | @@ -0,0 +1,111 @@ | |||
364 | 1 | /* | ||
365 | 2 | * Copyright © 2016 Canonical Ltd. | ||
366 | 3 | * | ||
367 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
368 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
369 | 6 | * as published by the Free Software Foundation. | ||
370 | 7 | * | ||
371 | 8 | * This program is distributed in the hope that it will be useful, | ||
372 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
373 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
374 | 11 | * GNU Lesser General Public License for more details. | ||
375 | 12 | * | ||
376 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
377 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
378 | 15 | * | ||
379 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
380 | 17 | */ | ||
381 | 18 | |||
382 | 19 | #ifndef ONEDRIVE_API_CLOUDFOLDER_H_ | ||
383 | 20 | #define ONEDRIVE_API_CLOUDFOLDER_H_ | ||
384 | 21 | |||
385 | 22 | #include <onedrive/api/cloudresource.h> | ||
386 | 23 | #include <onedrive/api/visibility.h> | ||
387 | 24 | |||
388 | 25 | namespace Json { | ||
389 | 26 | class Value; | ||
390 | 27 | } | ||
391 | 28 | |||
392 | 29 | namespace onedrive { | ||
393 | 30 | namespace api { | ||
394 | 31 | |||
395 | 32 | /*! | ||
396 | 33 | \class CloudFolder | ||
397 | 34 | \brief CloudFolder represents a folder object on onedrive. | ||
398 | 35 | */ | ||
399 | 36 | |||
400 | 37 | class ONEDRIVE_API_DLL_PUBLIC CloudFolder : public CloudResource { | ||
401 | 38 | public: | ||
402 | 39 | typedef std::shared_ptr<CloudFolder> Ptr; | ||
403 | 40 | |||
404 | 41 | virtual ~CloudFolder() = default; | ||
405 | 42 | |||
406 | 43 | /*! | ||
407 | 44 | * \brief Returns a unique id of cloud folder object. | ||
408 | 45 | */ | ||
409 | 46 | const std::string &id() const override; | ||
410 | 47 | |||
411 | 48 | /*! | ||
412 | 49 | * \brief Returns the name of cloud folder object. | ||
413 | 50 | */ | ||
414 | 51 | const std::string &name() const override; | ||
415 | 52 | |||
416 | 53 | /*! | ||
417 | 54 | * \brief Returns the datetime when folder was created. | ||
418 | 55 | */ | ||
419 | 56 | const std::time_t &created_date() const override; | ||
420 | 57 | |||
421 | 58 | /*! | ||
422 | 59 | * \brief Returns the datetime when folder was updated. | ||
423 | 60 | */ | ||
424 | 61 | const std::time_t &updated_date() const override; | ||
425 | 62 | |||
426 | 63 | /*! | ||
427 | 64 | * \brief Returns a shared link on onedriver for a folder . | ||
428 | 65 | */ | ||
429 | 66 | const std::string &download_url() const override; | ||
430 | 67 | |||
431 | 68 | /*! | ||
432 | 69 | * \brief Returns a unique id of the parent folder. | ||
433 | 70 | */ | ||
434 | 71 | const std::string &folder_id() const override; | ||
435 | 72 | |||
436 | 73 | /*! | ||
437 | 74 | * \brief Returns etag of a folder object. | ||
438 | 75 | */ | ||
439 | 76 | const std::string &etag() const override; | ||
440 | 77 | |||
441 | 78 | /*! | ||
442 | 79 | * \brief Returns owner id of a folder object. | ||
443 | 80 | */ | ||
444 | 81 | const std::string &owner() const override; | ||
445 | 82 | |||
446 | 83 | /*! | ||
447 | 84 | * \brief Returns resource property of an object. | ||
448 | 85 | * \sa CloudResource::Property | ||
449 | 86 | */ | ||
450 | 87 | CloudResource::Property property() const override; | ||
451 | 88 | |||
452 | 89 | /*! | ||
453 | 90 | * \brief Returns a item' parent folder path on onedrive. | ||
454 | 91 | */ | ||
455 | 92 | const std::string &folder_path() const override; | ||
456 | 93 | |||
457 | 94 | /*! | ||
458 | 95 | * \brief Returns the number of children items under this folder. | ||
459 | 96 | */ | ||
460 | 97 | int children_count() const; | ||
461 | 98 | |||
462 | 99 | private: | ||
463 | 100 | CloudFolder(const Json::Value &root); | ||
464 | 101 | |||
465 | 102 | friend class ClientPriv; | ||
466 | 103 | |||
467 | 104 | class Priv; | ||
468 | 105 | std::shared_ptr<Priv> p; | ||
469 | 106 | }; | ||
470 | 107 | |||
471 | 108 | } | ||
472 | 109 | } | ||
473 | 110 | |||
474 | 111 | #endif // ONEDRIVE_API_CLOUDFOLDER_H_ | ||
475 | 0 | 112 | ||
476 | === added file 'include/onedrive/api/clouditem.h' | |||
477 | --- include/onedrive/api/clouditem.h 1970-01-01 00:00:00 +0000 | |||
478 | +++ include/onedrive/api/clouditem.h 2016-09-30 08:26:58 +0000 | |||
479 | @@ -0,0 +1,123 @@ | |||
480 | 1 | /* | ||
481 | 2 | * Copyright © 2016 Canonical Ltd. | ||
482 | 3 | * | ||
483 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
484 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
485 | 6 | * as published by the Free Software Foundation. | ||
486 | 7 | * | ||
487 | 8 | * This program is distributed in the hope that it will be useful, | ||
488 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
489 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
490 | 11 | * GNU Lesser General Public License for more details. | ||
491 | 12 | * | ||
492 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
493 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
494 | 15 | * | ||
495 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
496 | 17 | */ | ||
497 | 18 | |||
498 | 19 | #ifndef ONEDRIVE_API_CloudItem_H_ | ||
499 | 20 | #define ONEDRIVE_API_CloudItem_H_ | ||
500 | 21 | |||
501 | 22 | #include <onedrive/api/cloudresource.h> | ||
502 | 23 | #include <onedrive/api/visibility.h> | ||
503 | 24 | |||
504 | 25 | #include <unordered_map> | ||
505 | 26 | |||
506 | 27 | namespace Json { | ||
507 | 28 | class Value; | ||
508 | 29 | } | ||
509 | 30 | |||
510 | 31 | namespace onedrive { | ||
511 | 32 | namespace api { | ||
512 | 33 | |||
513 | 34 | /*! | ||
514 | 35 | \class CloudItem | ||
515 | 36 | \brief CloudItem represents a item object on onedrive. | ||
516 | 37 | */ | ||
517 | 38 | |||
518 | 39 | class ONEDRIVE_API_DLL_PUBLIC CloudItem: public CloudResource { | ||
519 | 40 | public: | ||
520 | 41 | typedef std::shared_ptr<CloudItem> Ptr; | ||
521 | 42 | |||
522 | 43 | virtual ~CloudItem() = default; | ||
523 | 44 | |||
524 | 45 | /*! | ||
525 | 46 | * \brief Returns a unique id of cloud item object. | ||
526 | 47 | */ | ||
527 | 48 | const std::string &id() const override; | ||
528 | 49 | |||
529 | 50 | /*! | ||
530 | 51 | * \brief Returns the name of cloud item object. | ||
531 | 52 | */ | ||
532 | 53 | const std::string &name() const override; | ||
533 | 54 | |||
534 | 55 | /*! | ||
535 | 56 | * \brief Returns the datetime when item was created. | ||
536 | 57 | */ | ||
537 | 58 | const std::time_t &created_date() const override; | ||
538 | 59 | |||
539 | 60 | /*! | ||
540 | 61 | * \brief Returns the datetime when item was updated. | ||
541 | 62 | */ | ||
542 | 63 | const std::time_t &updated_date() const override; | ||
543 | 64 | |||
544 | 65 | /*! | ||
545 | 66 | * \brief Returns a download link on onedriver for a item . | ||
546 | 67 | */ | ||
547 | 68 | const std::string &download_url() const override; | ||
548 | 69 | |||
549 | 70 | /*! | ||
550 | 71 | * \brief Returns a item' parent folder id on onedrive. | ||
551 | 72 | */ | ||
552 | 73 | const std::string &folder_id() const override; | ||
553 | 74 | |||
554 | 75 | /*! | ||
555 | 76 | * \brief Returns a item' parent folder path on onedrive. | ||
556 | 77 | */ | ||
557 | 78 | const std::string &folder_path() const override; | ||
558 | 79 | |||
559 | 80 | /*! | ||
560 | 81 | * \brief Returns etag of a item object. | ||
561 | 82 | */ | ||
562 | 83 | const std::string &etag() const override; | ||
563 | 84 | |||
564 | 85 | /*! | ||
565 | 86 | * \brief Returns owner id of a item object. | ||
566 | 87 | */ | ||
567 | 88 | const std::string &owner() const override; | ||
568 | 89 | |||
569 | 90 | /*! | ||
570 | 91 | * \brief Returns resource type of an object. | ||
571 | 92 | */ | ||
572 | 93 | CloudResource::Property property() const override; | ||
573 | 94 | |||
574 | 95 | /*! | ||
575 | 96 | * \brief Returns content size of an object in bytes. | ||
576 | 97 | */ | ||
577 | 98 | int64_t size() const; | ||
578 | 99 | |||
579 | 100 | /*! | ||
580 | 101 | * \brief Returns item's mimetype. | ||
581 | 102 | */ | ||
582 | 103 | const std::string &mimetype() const; | ||
583 | 104 | |||
584 | 105 | /*! | ||
585 | 106 | * \brief content specific metadata info. | ||
586 | 107 | */ | ||
587 | 108 | std::unordered_map<std::string, std::string> &metadata() const; | ||
588 | 109 | |||
589 | 110 | private: | ||
590 | 111 | CloudItem(const Json::Value &root); | ||
591 | 112 | |||
592 | 113 | friend class UploadTaskPriv; | ||
593 | 114 | friend class ClientPriv; | ||
594 | 115 | |||
595 | 116 | class Priv; | ||
596 | 117 | std::shared_ptr<Priv> p; | ||
597 | 118 | }; | ||
598 | 119 | |||
599 | 120 | } | ||
600 | 121 | } | ||
601 | 122 | |||
602 | 123 | #endif // ONEDRIVE_API_CloudItem_H_ | ||
603 | 0 | 124 | ||
604 | === added file 'include/onedrive/api/cloudresource.h' | |||
605 | --- include/onedrive/api/cloudresource.h 1970-01-01 00:00:00 +0000 | |||
606 | +++ include/onedrive/api/cloudresource.h 2016-09-30 08:26:58 +0000 | |||
607 | @@ -0,0 +1,69 @@ | |||
608 | 1 | /* | ||
609 | 2 | * Copyright © 2016 Canonical Ltd. | ||
610 | 3 | * | ||
611 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
612 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
613 | 6 | * as published by the Free Software Foundation. | ||
614 | 7 | * | ||
615 | 8 | * This program is distributed in the hope that it will be useful, | ||
616 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
617 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
618 | 11 | * GNU Lesser General Public License for more details. | ||
619 | 12 | * | ||
620 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
621 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
622 | 15 | * | ||
623 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
624 | 17 | */ | ||
625 | 18 | |||
626 | 19 | #ifndef ONEDRIVE_API_CLOUDRESOURCE_H_ | ||
627 | 20 | #define ONEDRIVE_API_CLOUDRESOURCE_H_ | ||
628 | 21 | |||
629 | 22 | #include <memory> | ||
630 | 23 | #include <string> | ||
631 | 24 | #include <ctime> | ||
632 | 25 | |||
633 | 26 | namespace onedrive { | ||
634 | 27 | namespace api { | ||
635 | 28 | |||
636 | 29 | /*! | ||
637 | 30 | \class CloudResource | ||
638 | 31 | \brief CloudResource is an abstract object that provides common interfaces for CloudItem and CloudFolder. | ||
639 | 32 | */ | ||
640 | 33 | |||
641 | 34 | class CloudResource { | ||
642 | 35 | public: | ||
643 | 36 | typedef std::shared_ptr<CloudResource> Ptr; | ||
644 | 37 | |||
645 | 38 | enum class Property { | ||
646 | 39 | Content, ///< content resource | ||
647 | 40 | Folder ///< folder resource | ||
648 | 41 | }; | ||
649 | 42 | |||
650 | 43 | virtual ~CloudResource() = default; | ||
651 | 44 | |||
652 | 45 | virtual const std::string &id() const = 0; | ||
653 | 46 | |||
654 | 47 | virtual const std::string &name() const = 0; | ||
655 | 48 | |||
656 | 49 | virtual const std::time_t &created_date() const = 0; | ||
657 | 50 | |||
658 | 51 | virtual const std::time_t &updated_date() const = 0; | ||
659 | 52 | |||
660 | 53 | virtual const std::string &download_url() const = 0; | ||
661 | 54 | |||
662 | 55 | virtual const std::string &folder_id() const = 0; | ||
663 | 56 | |||
664 | 57 | virtual const std::string &folder_path() const = 0; | ||
665 | 58 | |||
666 | 59 | virtual const std::string &etag() const = 0; | ||
667 | 60 | |||
668 | 61 | virtual const std::string &owner() const = 0; | ||
669 | 62 | |||
670 | 63 | virtual Property property() const = 0; | ||
671 | 64 | }; | ||
672 | 65 | |||
673 | 66 | } | ||
674 | 67 | } | ||
675 | 68 | |||
676 | 69 | #endif // ONEDRIVE_API_CLOUDRESOURCE_H_ | ||
677 | 0 | 70 | ||
678 | === added file 'include/onedrive/api/downloadtask.h' | |||
679 | --- include/onedrive/api/downloadtask.h 1970-01-01 00:00:00 +0000 | |||
680 | +++ include/onedrive/api/downloadtask.h 2016-09-30 08:26:58 +0000 | |||
681 | @@ -0,0 +1,119 @@ | |||
682 | 1 | /* | ||
683 | 2 | * Copyright © 2016 Canonical Ltd. | ||
684 | 3 | * | ||
685 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
686 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
687 | 6 | * as published by the Free Software Foundation. | ||
688 | 7 | * | ||
689 | 8 | * This program is distributed in the hope that it will be useful, | ||
690 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
691 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
692 | 11 | * GNU Lesser General Public License for more details. | ||
693 | 12 | * | ||
694 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
695 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
696 | 15 | * | ||
697 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
698 | 17 | */ | ||
699 | 18 | |||
700 | 19 | #ifndef ONEDRIVE_API_DOWNLOADTASK_H_ | ||
701 | 20 | #define ONEDRIVE_API_DOWNLOADTASK_H_ | ||
702 | 21 | |||
703 | 22 | #include <onedrive/api/visibility.h> | ||
704 | 23 | #include <onedrive/api/cloudresource.h> | ||
705 | 24 | #include <onedrive/api/task.h> | ||
706 | 25 | |||
707 | 26 | namespace onedrive { | ||
708 | 27 | namespace api { | ||
709 | 28 | |||
710 | 29 | class TaskHandler; | ||
711 | 30 | |||
712 | 31 | /*! | ||
713 | 32 | \struct DownloadBufferCb | ||
714 | 33 | \brief DownloadBufferCb is a download request object which consists of a content id and | ||
715 | 34 | writing callback function allows content data can be received in buffering via callback function. | ||
716 | 35 | */ | ||
717 | 36 | struct ONEDRIVE_API_DLL_PUBLIC DownloadBufferCb | ||
718 | 37 | { | ||
719 | 38 | std::string content_id; | ||
720 | 39 | Task::Buffer_Callback write_cb; | ||
721 | 40 | }; | ||
722 | 41 | |||
723 | 42 | class DownloadTaskPriv; | ||
724 | 43 | class SyncManagerPriv; | ||
725 | 44 | |||
726 | 45 | /*! | ||
727 | 46 | \class DownloadTask | ||
728 | 47 | \brief DownloadTask is a task item that can be accessed from application layer to fetch | ||
729 | 48 | basic download item information, also it's used for content download by sync manager. | ||
730 | 49 | */ | ||
731 | 50 | class ONEDRIVE_API_DLL_PUBLIC DownloadTask : public Task { | ||
732 | 51 | public: | ||
733 | 52 | typedef std::shared_ptr<DownloadTask> Ptr; | ||
734 | 53 | |||
735 | 54 | virtual ~DownloadTask() = default; | ||
736 | 55 | |||
737 | 56 | DownloadTask& operator=(const DownloadTask& ) = delete; | ||
738 | 57 | |||
739 | 58 | /*! | ||
740 | 59 | * \brief Returns a display name of cloud content on onedrive. | ||
741 | 60 | */ | ||
742 | 61 | const std::string & content_name() const override; | ||
743 | 62 | |||
744 | 63 | /*! | ||
745 | 64 | * \brief Returns cloud content local storage file path. | ||
746 | 65 | */ | ||
747 | 66 | const std::string & file_path() const override; | ||
748 | 67 | |||
749 | 68 | /*! | ||
750 | 69 | * \brief Returns download url assigned by onedrive for this task. | ||
751 | 70 | * \note this url will be expried after a period of time. | ||
752 | 71 | */ | ||
753 | 72 | const std::string & task_url() const override; | ||
754 | 73 | |||
755 | 74 | /*! | ||
756 | 75 | * \brief Contains the error code if an error occurs during content download. | ||
757 | 76 | */ | ||
758 | 77 | const std::string & error_code() const override; | ||
759 | 78 | |||
760 | 79 | /*! | ||
761 | 80 | * \brief Contains the error string if an error occurs during content download. | ||
762 | 81 | */ | ||
763 | 82 | const std::string & error_message() const override; | ||
764 | 83 | |||
765 | 84 | /*! | ||
766 | 85 | * \brief Returns current sync-up status for this task. | ||
767 | 86 | * \sa Task::TaskStatus | ||
768 | 87 | */ | ||
769 | 88 | Task::Status status() const override; | ||
770 | 89 | |||
771 | 90 | /*! | ||
772 | 91 | * \brief Handler for download progress of a task. | ||
773 | 92 | * \sa Task::ProgressHandler | ||
774 | 93 | */ | ||
775 | 94 | Task::ProgressHandler & progress_changed() override; | ||
776 | 95 | |||
777 | 96 | /*! | ||
778 | 97 | * \brief Handler for download status of a task. | ||
779 | 98 | * \sa Task::StatusHandler | ||
780 | 99 | */ | ||
781 | 100 | Task::StatusHandler & status_changed() override; | ||
782 | 101 | |||
783 | 102 | /*! | ||
784 | 103 | * \brief cancel the task. | ||
785 | 104 | * \sa Task::StatusHandler | ||
786 | 105 | */ | ||
787 | 106 | void cancel() override; | ||
788 | 107 | |||
789 | 108 | private: | ||
790 | 109 | DownloadTask(std::shared_ptr<DownloadTaskPriv> p); | ||
791 | 110 | |||
792 | 111 | friend class SyncManagerPriv; | ||
793 | 112 | |||
794 | 113 | std::shared_ptr<DownloadTaskPriv> p_; | ||
795 | 114 | }; | ||
796 | 115 | |||
797 | 116 | } | ||
798 | 117 | } | ||
799 | 118 | |||
800 | 119 | #endif // ONEDRIVE_API_DOWNLOADTASK_H_ | ||
801 | 0 | 120 | ||
802 | === added file 'include/onedrive/api/exceptions.h' | |||
803 | --- include/onedrive/api/exceptions.h 1970-01-01 00:00:00 +0000 | |||
804 | +++ include/onedrive/api/exceptions.h 2016-09-30 08:26:58 +0000 | |||
805 | @@ -0,0 +1,87 @@ | |||
806 | 1 | /* | ||
807 | 2 | * Copyright © 2016 Canonical Ltd. | ||
808 | 3 | * | ||
809 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
810 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
811 | 6 | * as published by the Free Software Foundation. | ||
812 | 7 | * | ||
813 | 8 | * This program is distributed in the hope that it will be useful, | ||
814 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
815 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
816 | 11 | * GNU Lesser General Public License for more details. | ||
817 | 12 | * | ||
818 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
819 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
820 | 15 | * | ||
821 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
822 | 17 | */ | ||
823 | 18 | |||
824 | 19 | #ifndef ONEDRIVE_API_EXCEPTIONS_H_ | ||
825 | 20 | #define ONEDRIVE_API_EXCEPTIONS_H_ | ||
826 | 21 | |||
827 | 22 | #include <onedrive/api/visibility.h> | ||
828 | 23 | |||
829 | 24 | #include <exception> | ||
830 | 25 | |||
831 | 26 | namespace onedrive { | ||
832 | 27 | namespace api { | ||
833 | 28 | |||
834 | 29 | /** | ||
835 | 30 | * \brief Indicates a content or folder can not be found on onedrive. | ||
836 | 31 | */ | ||
837 | 32 | class ONEDRIVE_API_DLL_PUBLIC NonExistentException : public std::runtime_error { | ||
838 | 33 | public: | ||
839 | 34 | using runtime_error::runtime_error; | ||
840 | 35 | }; | ||
841 | 36 | |||
842 | 37 | /** | ||
843 | 38 | * \brief User ran out of space on onedrive storage. | ||
844 | 39 | */ | ||
845 | 40 | class ONEDRIVE_API_DLL_PUBLIC OutofSpaceException : public std::runtime_error { | ||
846 | 41 | public: | ||
847 | 42 | using runtime_error::runtime_error; | ||
848 | 43 | }; | ||
849 | 44 | |||
850 | 45 | /** | ||
851 | 46 | * \brief Indicates a timeout on HTTP requests. | ||
852 | 47 | */ | ||
853 | 48 | class ONEDRIVE_API_DLL_PUBLIC HttpTimeoutException : public std::runtime_error { | ||
854 | 49 | public: | ||
855 | 50 | using runtime_error::runtime_error; | ||
856 | 51 | }; | ||
857 | 52 | |||
858 | 53 | /** | ||
859 | 54 | * \brief Indicates one or more http request parameters are invalid. | ||
860 | 55 | */ | ||
861 | 56 | class ONEDRIVE_API_DLL_PUBLIC ParameterInvalidException : public std::runtime_error { | ||
862 | 57 | public: | ||
863 | 58 | using runtime_error::runtime_error; | ||
864 | 59 | }; | ||
865 | 60 | |||
866 | 61 | /** | ||
867 | 62 | * \brief Indicates access token is invalid or expired. | ||
868 | 63 | */ | ||
869 | 64 | class ONEDRIVE_API_DLL_PUBLIC CredentialException : public std::runtime_error { | ||
870 | 65 | public: | ||
871 | 66 | using runtime_error::runtime_error; | ||
872 | 67 | }; | ||
873 | 68 | |||
874 | 69 | /** | ||
875 | 70 | * \brief Indicates The service is not available. Try the request again after a delay. | ||
876 | 71 | */ | ||
877 | 72 | class ONEDRIVE_API_DLL_PUBLIC ServiceNotAvailableException : public std::runtime_error { | ||
878 | 73 | public: | ||
879 | 74 | using runtime_error::runtime_error; | ||
880 | 75 | }; | ||
881 | 76 | |||
882 | 77 | /** | ||
883 | 78 | * \brief Unknown exception. | ||
884 | 79 | */ | ||
885 | 80 | class ONEDRIVE_API_DLL_PUBLIC UnknownException : public std::runtime_error { | ||
886 | 81 | public: | ||
887 | 82 | using runtime_error::runtime_error; | ||
888 | 83 | }; | ||
889 | 84 | } | ||
890 | 85 | } | ||
891 | 86 | |||
892 | 87 | #endif // ONEDRIVE_API_EXCEPTIONS_H_ | ||
893 | 0 | 88 | ||
894 | === added file 'include/onedrive/api/storageinfo.h' | |||
895 | --- include/onedrive/api/storageinfo.h 1970-01-01 00:00:00 +0000 | |||
896 | +++ include/onedrive/api/storageinfo.h 2016-09-30 08:26:58 +0000 | |||
897 | @@ -0,0 +1,74 @@ | |||
898 | 1 | /* | ||
899 | 2 | * Copyright © 2016 Canonical Ltd. | ||
900 | 3 | * | ||
901 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
902 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
903 | 6 | * as published by the Free Software Foundation. | ||
904 | 7 | * | ||
905 | 8 | * This program is distributed in the hope that it will be useful, | ||
906 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
907 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
908 | 11 | * GNU Lesser General Public License for more details. | ||
909 | 12 | * | ||
910 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
911 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
912 | 15 | * | ||
913 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
914 | 17 | */ | ||
915 | 18 | |||
916 | 19 | #ifndef ONEDRIVE_API_STORAGEINFO_H_ | ||
917 | 20 | #define ONEDRIVE_API_STORAGEINFO_H_ | ||
918 | 21 | |||
919 | 22 | #include <onedrive/api/visibility.h> | ||
920 | 23 | |||
921 | 24 | #include <memory> | ||
922 | 25 | #include <string> | ||
923 | 26 | |||
924 | 27 | namespace Json { | ||
925 | 28 | class Value; | ||
926 | 29 | } | ||
927 | 30 | |||
928 | 31 | namespace onedrive { | ||
929 | 32 | namespace api { | ||
930 | 33 | |||
931 | 34 | /*! | ||
932 | 35 | \class StorageInfo | ||
933 | 36 | \brief StorageInfo is a class that provides basic user's account and storage usage information on onedrive. | ||
934 | 37 | */ | ||
935 | 38 | |||
936 | 39 | class ONEDRIVE_API_DLL_PUBLIC StorageInfo { | ||
937 | 40 | public: | ||
938 | 41 | virtual ~StorageInfo() = default; | ||
939 | 42 | |||
940 | 43 | /*! | ||
941 | 44 | * \brief Returns authorized user's id. | ||
942 | 45 | */ | ||
943 | 46 | const std::string &id() const; | ||
944 | 47 | |||
945 | 48 | /*! | ||
946 | 49 | * \brief Returns authorized user's name. | ||
947 | 50 | */ | ||
948 | 51 | const std::string &name() const; | ||
949 | 52 | |||
950 | 53 | /*! | ||
951 | 54 | * \brief Returns used disk size of user cloud storage in Bytes. | ||
952 | 55 | */ | ||
953 | 56 | int64_t used_disk_size() const; | ||
954 | 57 | |||
955 | 58 | /*! | ||
956 | 59 | * \brief Returns total disk size assigned by onedrive in Bytes. | ||
957 | 60 | */ | ||
958 | 61 | int64_t total_disk_size() const; | ||
959 | 62 | private: | ||
960 | 63 | StorageInfo(const Json::Value &root); | ||
961 | 64 | |||
962 | 65 | friend class ClientPriv; | ||
963 | 66 | class Priv; | ||
964 | 67 | |||
965 | 68 | std::shared_ptr<Priv> p; | ||
966 | 69 | }; | ||
967 | 70 | |||
968 | 71 | } | ||
969 | 72 | } | ||
970 | 73 | |||
971 | 74 | #endif // ONEDRIVE_API_STORAGEINFO_H_ | ||
972 | 0 | 75 | ||
973 | === added file 'include/onedrive/api/syncmanager.h' | |||
974 | --- include/onedrive/api/syncmanager.h 1970-01-01 00:00:00 +0000 | |||
975 | +++ include/onedrive/api/syncmanager.h 2016-09-30 08:26:58 +0000 | |||
976 | @@ -0,0 +1,171 @@ | |||
977 | 1 | /* | ||
978 | 2 | * Copyright © 2016 Canonical Ltd. | ||
979 | 3 | * | ||
980 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
981 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
982 | 6 | * as published by the Free Software Foundation. | ||
983 | 7 | * | ||
984 | 8 | * This program is distributed in the hope that it will be useful, | ||
985 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
986 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
987 | 11 | * GNU Lesser General Public License for more details. | ||
988 | 12 | * | ||
989 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
990 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
991 | 15 | * | ||
992 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
993 | 17 | */ | ||
994 | 18 | |||
995 | 19 | #ifndef ONEDRIVE_API_SYNCMANAGER_H_ | ||
996 | 20 | #define ONEDRIVE_API_SYNCMANAGER_H_ | ||
997 | 21 | |||
998 | 22 | #include <onedrive/api/taskqueue.h> | ||
999 | 23 | #include <onedrive/api/downloadtask.h> | ||
1000 | 24 | #include <onedrive/api/uploadtask.h> | ||
1001 | 25 | #include <onedrive/api/visibility.h> | ||
1002 | 26 | |||
1003 | 27 | #include <memory> | ||
1004 | 28 | #include <vector> | ||
1005 | 29 | |||
1006 | 30 | namespace onedrive { | ||
1007 | 31 | namespace api { | ||
1008 | 32 | |||
1009 | 33 | class ClientPriv; | ||
1010 | 34 | class SyncManagerPriv; | ||
1011 | 35 | |||
1012 | 36 | /*! | ||
1013 | 37 | \class SyncManager | ||
1014 | 38 | \brief SyncManager handles all the requests to upload and download. | ||
1015 | 39 | It's constructed around two threads for content synchronization. One for content upload to cloud, another for cloud item download to local. | ||
1016 | 40 | Both thread are running asynchronously. | ||
1017 | 41 | Calls \sa add_download_task() by passing a content id list for cloud content download, | ||
1018 | 42 | Calls \sa add_upload_tasks() by passing a local file path for local content upload. | ||
1019 | 43 | */ | ||
1020 | 44 | |||
1021 | 45 | class ONEDRIVE_API_DLL_PUBLIC SyncManager { | ||
1022 | 46 | public: | ||
1023 | 47 | typedef std::shared_ptr<SyncManager> Ptr; | ||
1024 | 48 | |||
1025 | 49 | typedef TaskQueue<DownloadTask::Ptr> DownloadList; | ||
1026 | 50 | |||
1027 | 51 | typedef TaskQueue<UploadTask::Ptr> UploadList; | ||
1028 | 52 | |||
1029 | 53 | typedef std::vector<std::string> Stringlist; | ||
1030 | 54 | |||
1031 | 55 | virtual ~SyncManager() = default; | ||
1032 | 56 | |||
1033 | 57 | SyncManager(const SyncManager&) = delete; | ||
1034 | 58 | |||
1035 | 59 | SyncManager& operator=(const SyncManager &) = delete; | ||
1036 | 60 | |||
1037 | 61 | /*! | ||
1038 | 62 | * \brief Starts to run download or upload tasks from sync-up thread. | ||
1039 | 63 | * The tasks can be resumed by sync-up thread if sync manager is paused or canceled before. | ||
1040 | 64 | * \sa pause(), cancel() | ||
1041 | 65 | */ | ||
1042 | 66 | void start(); | ||
1043 | 67 | |||
1044 | 68 | /*! | ||
1045 | 69 | * \brief Cancels all download or upload tasks from sync-up thread if sync manager is running. | ||
1046 | 70 | * \note A canceled download or upload task has no chance to run again by sync-up thread. | ||
1047 | 71 | * \sa start(), pause() | ||
1048 | 72 | */ | ||
1049 | 73 | void cancel(); | ||
1050 | 74 | |||
1051 | 75 | /*! | ||
1052 | 76 | * \brief Pauses download or upload task from sync-up thread if sync manager is running. | ||
1053 | 77 | * Sync-up thread can continue to run previous paused task by calling \sa start() | ||
1054 | 78 | * \sa start(), cancel() | ||
1055 | 79 | */ | ||
1056 | 80 | void pause(); | ||
1057 | 81 | |||
1058 | 82 | /*! | ||
1059 | 83 | * \brief Pushes a content id \a contentid_list into download queue. | ||
1060 | 84 | * \return download task item that is pushed in sync-up manager. | ||
1061 | 85 | * \throw std::runtime_error if error occurs. | ||
1062 | 86 | * \sa add_download_tasks(), DownloadTask | ||
1063 | 87 | */ | ||
1064 | 88 | DownloadTask::Ptr add_download_task(const std::string &content_id); | ||
1065 | 89 | |||
1066 | 90 | /*! | ||
1067 | 91 | * \brief Pushes a download buffer callback item \a buffer_cb_item into download queue. | ||
1068 | 92 | * Each download buffer consists of the following fields | ||
1069 | 93 | * - `write_cb` (std::function<size_t(void *dest, size_t buf_size)>) | ||
1070 | 94 | * buffer reading callback function. | ||
1071 | 95 | * The buffer area pointed at by the pointer \a dest should be filled up with at most \a buf_size number of bytes. | ||
1072 | 96 | * - `content_id` (string) | ||
1073 | 97 | * The id of content on onedrive. | ||
1074 | 98 | * \return download task item that is pushed in sync-up manager. | ||
1075 | 99 | * \throw std::runtime_error if error occurs. | ||
1076 | 100 | * \sa add_download_tasks(), DownloadTask | ||
1077 | 101 | */ | ||
1078 | 102 | DownloadTask::Ptr add_download_task(const DownloadBufferCb &buffer_cb_item); | ||
1079 | 103 | |||
1080 | 104 | /*! | ||
1081 | 105 | * \brief Pushes a upload request item \a reqeust_item to sync manager and add regarding upload task into upload queue. | ||
1082 | 106 | * A upload request consists of the following fields | ||
1083 | 107 | * - `file_path` (string) | ||
1084 | 108 | * local file path. | ||
1085 | 109 | * - `folder_id` (string) | ||
1086 | 110 | * onedrive folder id which stores content in uploads folder. | ||
1087 | 111 | * - `content_name` (string) | ||
1088 | 112 | * uploaded content name. | ||
1089 | 113 | * If content_name is empty, local file name will be used as a content name displayed on onedrive. | ||
1090 | 114 | * If folder_id is empty, content will be uploaded into root folder. | ||
1091 | 115 | * \return upload task item that is pushed in sync-up manager. | ||
1092 | 116 | * \throw std::runtime_error if error occurs. | ||
1093 | 117 | * \note A file name can not contain any of following characters: | ||
1094 | 118 | * '\', '/', ':', '*', '?', '"', '<', '>', '|' | ||
1095 | 119 | * \note Sync manager will detect if the uploading file is already existing on cloud, | ||
1096 | 120 | * if so, it simply sets the status of upload task completed to avoid duplicate upload. | ||
1097 | 121 | * \sa add_download_tasks(), UploadRequest, UploadTask, | ||
1098 | 122 | */ | ||
1099 | 123 | UploadTask::Ptr add_upload_task(const UploadRequest &reqeust_item); | ||
1100 | 124 | |||
1101 | 125 | /*! | ||
1102 | 126 | * \brief Pushes a upload callback item \a buffer_cb to sync manager and add regarding upload task into upload queue. | ||
1103 | 127 | * A upload buffer consists of the following fields | ||
1104 | 128 | * - `read_cb` (std::function<size_t(void *dest, size_t buf_size)>) | ||
1105 | 129 | * buffer reading callback function. | ||
1106 | 130 | * The buffer area pointed at by the pointer \a dest should be filled up with at most \a buf_size number of bytes. | ||
1107 | 131 | * - `buffer_size` (size_t) | ||
1108 | 132 | * total size of data buffers. | ||
1109 | 133 | * - `folder_id` (string) | ||
1110 | 134 | * onedrive folder id which stores content in uploads folder. | ||
1111 | 135 | * - `content_name` (string) | ||
1112 | 136 | * uploaded content name, should not be empty. | ||
1113 | 137 | * If folder_id is empty, content will be uploaded into root folder. | ||
1114 | 138 | * \return upload task item that are pushed in sync-up manager. | ||
1115 | 139 | * \throw std::runtime_error if error occurs. | ||
1116 | 140 | * \note A file name can not contain any of following characters: | ||
1117 | 141 | * '\', '/', ':', '*', '?', '"', '<', '>', '|' | ||
1118 | 142 | * \sa add_download_tasks(), UploadRequest, UploadTask, | ||
1119 | 143 | */ | ||
1120 | 144 | UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb); | ||
1121 | 145 | |||
1122 | 146 | /*! | ||
1123 | 147 | * \brief Returns a download task list hold by sync up manager. | ||
1124 | 148 | * Each item in the list contains basic information of associated task. | ||
1125 | 149 | * \sa upload_queue(), DownloadTask | ||
1126 | 150 | */ | ||
1127 | 151 | DownloadList download_queue(); | ||
1128 | 152 | |||
1129 | 153 | /*! | ||
1130 | 154 | * \brief Returns a upload task list hold by sync up manager. | ||
1131 | 155 | * Each item in the list contains basic information of associated task. | ||
1132 | 156 | * \sa download_queue(), UploadTask | ||
1133 | 157 | */ | ||
1134 | 158 | UploadList upload_queue(); | ||
1135 | 159 | |||
1136 | 160 | private: | ||
1137 | 161 | SyncManager(ClientPriv* client_priv); | ||
1138 | 162 | |||
1139 | 163 | friend class ClientPriv; | ||
1140 | 164 | |||
1141 | 165 | std::shared_ptr<SyncManagerPriv> p_; | ||
1142 | 166 | }; | ||
1143 | 167 | |||
1144 | 168 | } | ||
1145 | 169 | } | ||
1146 | 170 | |||
1147 | 171 | #endif // ONEDRIVE_API_SYNCMANAGER_H_ | ||
1148 | 0 | 172 | ||
1149 | === added file 'include/onedrive/api/task.h' | |||
1150 | --- include/onedrive/api/task.h 1970-01-01 00:00:00 +0000 | |||
1151 | +++ include/onedrive/api/task.h 2016-09-30 08:26:58 +0000 | |||
1152 | @@ -0,0 +1,119 @@ | |||
1153 | 1 | /* | ||
1154 | 2 | * Copyright © 2016 Canonical Ltd. | ||
1155 | 3 | * | ||
1156 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1157 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
1158 | 6 | * as published by the Free Software Foundation. | ||
1159 | 7 | * | ||
1160 | 8 | * This program is distributed in the hope that it will be useful, | ||
1161 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1162 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1163 | 11 | * GNU Lesser General Public License for more details. | ||
1164 | 12 | * | ||
1165 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1166 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1167 | 15 | * | ||
1168 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
1169 | 17 | */ | ||
1170 | 18 | |||
1171 | 19 | #ifndef ONEDRIVE_API_TASK_H_ | ||
1172 | 20 | #define ONEDRIVE_API_TASK_H_ | ||
1173 | 21 | |||
1174 | 22 | #include <onedrive/api/visibility.h> | ||
1175 | 23 | #include <functional> | ||
1176 | 24 | #include <string> | ||
1177 | 25 | |||
1178 | 26 | namespace onedrive { | ||
1179 | 27 | namespace api { | ||
1180 | 28 | |||
1181 | 29 | /*! | ||
1182 | 30 | \class Task | ||
1183 | 31 | \brief Task is an abstract class that defines common interfaces for upload and download task. | ||
1184 | 32 | */ | ||
1185 | 33 | |||
1186 | 34 | class ONEDRIVE_API_DLL_PUBLIC Task { | ||
1187 | 35 | public: | ||
1188 | 36 | /*! | ||
1189 | 37 | * \brief The Status enum indicates current status of this task. | ||
1190 | 38 | */ | ||
1191 | 39 | enum class Status { | ||
1192 | 40 | Unstart, ///< Task is in queue and sync manager does not run this task yet. | ||
1193 | 41 | Running, ///< Task is being processed by sync manager. | ||
1194 | 42 | Canceled, ///< Task is in canceled status, it is caused by the call from Client::cancel_sync(). | ||
1195 | 43 | Paused, ///< Task is in paused status, it is caused by the call from Client::pause_sync(). | ||
1196 | 44 | Broken, ///< Task is broken when sync manager failed to download/upload a task after several times trying. | ||
1197 | 45 | Complete, ///< Task is completed. | ||
1198 | 46 | }; | ||
1199 | 47 | |||
1200 | 48 | /*! | ||
1201 | 49 | * \brief The name conflict enum which can be specified the behavior to use if the file already exists. | ||
1202 | 50 | * The default for PUT is replace. | ||
1203 | 51 | */ | ||
1204 | 52 | enum class NameConflictBehavior { | ||
1205 | 53 | Fail, ///<Failed if the file already exists. | ||
1206 | 54 | Replace, ///<Replace current content if the file already exists. | ||
1207 | 55 | Rename ///<Automatically renamed by onedrive if the file already exists. | ||
1208 | 56 | }; | ||
1209 | 57 | |||
1210 | 58 | typedef std::function<void(float)> ProgressHandler; | ||
1211 | 59 | |||
1212 | 60 | typedef std::function<void(Status)> StatusHandler; | ||
1213 | 61 | |||
1214 | 62 | typedef std::function<size_t(void *dest, size_t buf_size)> Buffer_Callback; | ||
1215 | 63 | |||
1216 | 64 | virtual ~Task() = default; | ||
1217 | 65 | |||
1218 | 66 | /*! | ||
1219 | 67 | * \brief Returns a display name of cloud content on onedrive. | ||
1220 | 68 | */ | ||
1221 | 69 | virtual const std::string & content_name() const = 0; | ||
1222 | 70 | |||
1223 | 71 | /*! | ||
1224 | 72 | * \brief Returns cloud content local storage file path. | ||
1225 | 73 | */ | ||
1226 | 74 | virtual const std::string & file_path() const = 0; | ||
1227 | 75 | |||
1228 | 76 | /*! | ||
1229 | 77 | * \brief Contains the error code if an error occurs during task running. | ||
1230 | 78 | */ | ||
1231 | 79 | virtual const std::string & error_code() const = 0; | ||
1232 | 80 | |||
1233 | 81 | /*! | ||
1234 | 82 | * \brief Contains the error string if an error occurs during task running. | ||
1235 | 83 | */ | ||
1236 | 84 | virtual const std::string & error_message() const = 0; | ||
1237 | 85 | |||
1238 | 86 | /*! | ||
1239 | 87 | * \brief Returns a item task url. | ||
1240 | 88 | * \note the url will be expried after a period of time. | ||
1241 | 89 | */ | ||
1242 | 90 | virtual const std::string & task_url() const = 0; | ||
1243 | 91 | |||
1244 | 92 | /*! | ||
1245 | 93 | * \brief Returns current download or upload item sync-up status. | ||
1246 | 94 | */ | ||
1247 | 95 | virtual Task::Status status() const = 0; | ||
1248 | 96 | |||
1249 | 97 | /*! | ||
1250 | 98 | * \brief Handler for download or upload progress of a task. | ||
1251 | 99 | * \sa Task::ProgressHandler | ||
1252 | 100 | */ | ||
1253 | 101 | virtual Task::ProgressHandler & progress_changed() = 0; | ||
1254 | 102 | |||
1255 | 103 | /*! | ||
1256 | 104 | * \brief Handler for download or upload progress of a task. | ||
1257 | 105 | * \sa Task::StatusHandler | ||
1258 | 106 | */ | ||
1259 | 107 | virtual Task::StatusHandler & status_changed() = 0; | ||
1260 | 108 | |||
1261 | 109 | /*! | ||
1262 | 110 | * \brief Cancel the task. | ||
1263 | 111 | * \sa Task::StatusHandler | ||
1264 | 112 | */ | ||
1265 | 113 | virtual void cancel() = 0; | ||
1266 | 114 | }; | ||
1267 | 115 | |||
1268 | 116 | } | ||
1269 | 117 | } | ||
1270 | 118 | |||
1271 | 119 | #endif // ONEDRIVE_API_TASK_H_ | ||
1272 | 0 | 120 | ||
1273 | === added file 'include/onedrive/api/taskqueue.h' | |||
1274 | --- include/onedrive/api/taskqueue.h 1970-01-01 00:00:00 +0000 | |||
1275 | +++ include/onedrive/api/taskqueue.h 2016-09-30 08:26:58 +0000 | |||
1276 | @@ -0,0 +1,131 @@ | |||
1277 | 1 | /* | ||
1278 | 2 | * Copyright © 2016 Canonical Ltd. | ||
1279 | 3 | * | ||
1280 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1281 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
1282 | 6 | * as published by the Free Software Foundation. | ||
1283 | 7 | * | ||
1284 | 8 | * This program is distributed in the hope that it will be useful, | ||
1285 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1286 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1287 | 11 | * GNU Lesser General Public License for more details. | ||
1288 | 12 | * | ||
1289 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1290 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1291 | 15 | * | ||
1292 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
1293 | 17 | */ | ||
1294 | 18 | |||
1295 | 19 | #ifndef ONEDRIVE_API_TASKQUEUE_H_ | ||
1296 | 20 | #define ONEDRIVE_API_TASKQUEUE_H_ | ||
1297 | 21 | |||
1298 | 22 | #include <memory> | ||
1299 | 23 | #include <deque> | ||
1300 | 24 | #include <mutex> | ||
1301 | 25 | |||
1302 | 26 | namespace onedrive { | ||
1303 | 27 | namespace api { | ||
1304 | 28 | |||
1305 | 29 | /*! | ||
1306 | 30 | \class TaskQueue | ||
1307 | 31 | \brief A thread-safe deque template. | ||
1308 | 32 | */ | ||
1309 | 33 | template<typename T, typename Container = std::deque<T>> | ||
1310 | 34 | class TaskQueue { | ||
1311 | 35 | public: | ||
1312 | 36 | typedef std::shared_ptr<TaskQueue> Ptr; | ||
1313 | 37 | typedef typename Container::size_type size_type; | ||
1314 | 38 | typedef typename Container::const_iterator const_iterator; | ||
1315 | 39 | |||
1316 | 40 | TaskQueue() = default; | ||
1317 | 41 | |||
1318 | 42 | virtual ~TaskQueue() = default; | ||
1319 | 43 | |||
1320 | 44 | TaskQueue(TaskQueue &&queue) { | ||
1321 | 45 | std::lock_guard<std::mutex> lock(mutex_); | ||
1322 | 46 | tasks_ = std::move(queue.tasks_); | ||
1323 | 47 | } | ||
1324 | 48 | |||
1325 | 49 | TaskQueue(const TaskQueue &queue) { | ||
1326 | 50 | std::lock_guard<std::mutex> lock(mutex_); | ||
1327 | 51 | tasks_ = queue.tasks_; | ||
1328 | 52 | } | ||
1329 | 53 | |||
1330 | 54 | TaskQueue &operator= (const TaskQueue &queue) { | ||
1331 | 55 | if (this != &queue) { | ||
1332 | 56 | std::lock_guard<std::mutex> lock1(mutex_); | ||
1333 | 57 | std::lock_guard<std::mutex> lock2(queue.mutex_); | ||
1334 | 58 | tasks_ = queue.tasks_; | ||
1335 | 59 | } | ||
1336 | 60 | |||
1337 | 61 | return *this; | ||
1338 | 62 | } | ||
1339 | 63 | |||
1340 | 64 | typename Container::iterator begin() { | ||
1341 | 65 | std::lock_guard<std::mutex> lock(mutex_); | ||
1342 | 66 | return tasks_.begin(); | ||
1343 | 67 | } | ||
1344 | 68 | |||
1345 | 69 | typename Container::iterator end() { | ||
1346 | 70 | std::lock_guard<std::mutex> lock(mutex_); | ||
1347 | 71 | return tasks_.end(); | ||
1348 | 72 | } | ||
1349 | 73 | |||
1350 | 74 | typename Container::iterator cbegin() const { | ||
1351 | 75 | std::lock_guard<std::mutex> lock(mutex_); | ||
1352 | 76 | return tasks_.cbegin(); | ||
1353 | 77 | } | ||
1354 | 78 | |||
1355 | 79 | typename Container::iterator cend() const { | ||
1356 | 80 | std::lock_guard<std::mutex> lock(mutex_); | ||
1357 | 81 | return tasks_.cend(); | ||
1358 | 82 | } | ||
1359 | 83 | |||
1360 | 84 | size_type size() const { | ||
1361 | 85 | std::lock_guard<std::mutex> lock(mutex_); | ||
1362 | 86 | return tasks_.size(); | ||
1363 | 87 | } | ||
1364 | 88 | |||
1365 | 89 | bool empty() const { | ||
1366 | 90 | std::lock_guard<std::mutex> lock(mutex_); | ||
1367 | 91 | return tasks_.empty(); | ||
1368 | 92 | } | ||
1369 | 93 | |||
1370 | 94 | void push(const T &task) { | ||
1371 | 95 | std::lock_guard<std::mutex> lock(mutex_); | ||
1372 | 96 | tasks_.push_back(task); | ||
1373 | 97 | } | ||
1374 | 98 | |||
1375 | 99 | void push(const TaskQueue & queue) { | ||
1376 | 100 | std::lock_guard<std::mutex> lock(mutex_); | ||
1377 | 101 | for (const T & task: queue.tasks_){ | ||
1378 | 102 | tasks_.push_back(task); | ||
1379 | 103 | } | ||
1380 | 104 | } | ||
1381 | 105 | |||
1382 | 106 | bool try_pop(T &task) { | ||
1383 | 107 | std::lock_guard<std::mutex> lock(mutex_); | ||
1384 | 108 | |||
1385 | 109 | if (tasks_.empty()) | ||
1386 | 110 | return false; | ||
1387 | 111 | |||
1388 | 112 | task = tasks_.front(); | ||
1389 | 113 | tasks_.pop_front(); | ||
1390 | 114 | return true; | ||
1391 | 115 | } | ||
1392 | 116 | |||
1393 | 117 | const T & operator[](int index) const { | ||
1394 | 118 | std::lock_guard<std::mutex> lock(mutex_); | ||
1395 | 119 | return tasks_[index]; | ||
1396 | 120 | } | ||
1397 | 121 | |||
1398 | 122 | private: | ||
1399 | 123 | Container tasks_; | ||
1400 | 124 | |||
1401 | 125 | mutable std::mutex mutex_; | ||
1402 | 126 | }; | ||
1403 | 127 | |||
1404 | 128 | } | ||
1405 | 129 | } | ||
1406 | 130 | |||
1407 | 131 | #endif // ONEDRIVE_API_TASKQUEUE_H_ | ||
1408 | 0 | 132 | ||
1409 | === added file 'include/onedrive/api/uploadtask.h' | |||
1410 | --- include/onedrive/api/uploadtask.h 1970-01-01 00:00:00 +0000 | |||
1411 | +++ include/onedrive/api/uploadtask.h 2016-09-30 08:26:58 +0000 | |||
1412 | @@ -0,0 +1,176 @@ | |||
1413 | 1 | /* | ||
1414 | 2 | * Copyright © 2016 Canonical Ltd. | ||
1415 | 3 | * | ||
1416 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1417 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
1418 | 6 | * as published by the Free Software Foundation. | ||
1419 | 7 | * | ||
1420 | 8 | * This program is distributed in the hope that it will be useful, | ||
1421 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1422 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1423 | 11 | * GNU Lesser General Public License for more details. | ||
1424 | 12 | * | ||
1425 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1426 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1427 | 15 | * | ||
1428 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
1429 | 17 | */ | ||
1430 | 18 | |||
1431 | 19 | #ifndef ONEDRIVE_API_UPLOADTASK_H_ | ||
1432 | 20 | #define ONEDRIVE_API_UPLOADTASK_H_ | ||
1433 | 21 | |||
1434 | 22 | #include <onedrive/api/task.h> | ||
1435 | 23 | #include <onedrive/api/visibility.h> | ||
1436 | 24 | |||
1437 | 25 | #include <memory> | ||
1438 | 26 | #include <vector> | ||
1439 | 27 | |||
1440 | 28 | namespace Json { | ||
1441 | 29 | class Value; | ||
1442 | 30 | } | ||
1443 | 31 | |||
1444 | 32 | namespace onedrive { | ||
1445 | 33 | namespace api { | ||
1446 | 34 | |||
1447 | 35 | class TaskHandler; | ||
1448 | 36 | |||
1449 | 37 | /*! | ||
1450 | 38 | \struct UploadRequest | ||
1451 | 39 | \brief UploadRequest is a upload request item which consists of a upload folder id, up-front buffer size, | ||
1452 | 40 | upload content name | ||
1453 | 41 | */ | ||
1454 | 42 | struct ONEDRIVE_API_DLL_PUBLIC UploadRequest | ||
1455 | 43 | { | ||
1456 | 44 | UploadRequest(std::string local_file_path, | ||
1457 | 45 | std::string parent_folder_id, | ||
1458 | 46 | std::string upload_file_name, | ||
1459 | 47 | Task::NameConflictBehavior conflict_name_behavior = Task::NameConflictBehavior::Replace) | ||
1460 | 48 | :file_path(local_file_path), | ||
1461 | 49 | folder_id(parent_folder_id), | ||
1462 | 50 | content_name(upload_file_name), | ||
1463 | 51 | conflict_behavior(conflict_name_behavior){ | ||
1464 | 52 | } | ||
1465 | 53 | |||
1466 | 54 | std::string file_path; | ||
1467 | 55 | std::string folder_id; | ||
1468 | 56 | std::string content_name; | ||
1469 | 57 | Task::NameConflictBehavior conflict_behavior; | ||
1470 | 58 | }; | ||
1471 | 59 | typedef std::vector<UploadRequest> UploadRequestList; | ||
1472 | 60 | |||
1473 | 61 | /*! | ||
1474 | 62 | \struct UploadBufferCb | ||
1475 | 63 | \brief UploadBufferCb is a upload request item which consists of a upload folder id, upload buffer size, | ||
1476 | 64 | upload content name and reading callback function allows content data can be received in buffering via call | ||
1477 | 65 | back function. | ||
1478 | 66 | */ | ||
1479 | 67 | struct ONEDRIVE_API_DLL_PUBLIC UploadBufferCb | ||
1480 | 68 | { | ||
1481 | 69 | UploadBufferCb(Task::Buffer_Callback read_callback, | ||
1482 | 70 | size_t upload_buf_size, | ||
1483 | 71 | std::string parent_folder_id, | ||
1484 | 72 | std::string upload_file_name, | ||
1485 | 73 | Task::NameConflictBehavior conflict_name_behavior = Task::NameConflictBehavior::Replace) | ||
1486 | 74 | :read_cb(read_callback), | ||
1487 | 75 | buffer_size(upload_buf_size), | ||
1488 | 76 | folder_id(parent_folder_id), | ||
1489 | 77 | content_name(upload_file_name), | ||
1490 | 78 | conflict_behavior(conflict_name_behavior){ | ||
1491 | 79 | } | ||
1492 | 80 | |||
1493 | 81 | Task::Buffer_Callback read_cb; | ||
1494 | 82 | size_t buffer_size; | ||
1495 | 83 | std::string folder_id; | ||
1496 | 84 | std::string content_name; | ||
1497 | 85 | Task::NameConflictBehavior conflict_behavior = Task::NameConflictBehavior::Replace; | ||
1498 | 86 | }; | ||
1499 | 87 | typedef std::vector<UploadBufferCb> UploadBufferCbList; | ||
1500 | 88 | |||
1501 | 89 | class UploadTaskPriv; | ||
1502 | 90 | class CloudItem; | ||
1503 | 91 | |||
1504 | 92 | /*! | ||
1505 | 93 | \class UploadTask | ||
1506 | 94 | \brief UploadTask is a task item that can be accessed from application layer to fetch | ||
1507 | 95 | basic upload item information, also it's used for content upload by sync manager. | ||
1508 | 96 | */ | ||
1509 | 97 | class ONEDRIVE_API_DLL_PUBLIC UploadTask : public Task { | ||
1510 | 98 | public: | ||
1511 | 99 | typedef std::shared_ptr<UploadTask> Ptr; | ||
1512 | 100 | |||
1513 | 101 | virtual ~UploadTask() = default; | ||
1514 | 102 | |||
1515 | 103 | UploadTask& operator=(const UploadTask& ) = delete; | ||
1516 | 104 | |||
1517 | 105 | /*! | ||
1518 | 106 | * \brief Returns a display name of local content. | ||
1519 | 107 | */ | ||
1520 | 108 | const std::string & content_name() const override; | ||
1521 | 109 | |||
1522 | 110 | /*! | ||
1523 | 111 | * \brief Returns uploaded local content file path. | ||
1524 | 112 | */ | ||
1525 | 113 | const std::string & file_path() const override; | ||
1526 | 114 | |||
1527 | 115 | /*! | ||
1528 | 116 | * \brief Returns download url assigned by onedrive for this task. | ||
1529 | 117 | * \note this url will be expried after a period of time. | ||
1530 | 118 | */ | ||
1531 | 119 | const std::string & task_url() const override; | ||
1532 | 120 | |||
1533 | 121 | /*! | ||
1534 | 122 | * \brief Contains the error code if an error occurs during content uploading. | ||
1535 | 123 | */ | ||
1536 | 124 | const std::string & error_code() const override; | ||
1537 | 125 | |||
1538 | 126 | /*! | ||
1539 | 127 | * \brief Contains the error string if an error occurs during content uploading. | ||
1540 | 128 | */ | ||
1541 | 129 | const std::string & error_message() const override; | ||
1542 | 130 | |||
1543 | 131 | /*! | ||
1544 | 132 | * \brief Returns current sync-up status for this task. | ||
1545 | 133 | */ | ||
1546 | 134 | Task::Status status() const override; | ||
1547 | 135 | |||
1548 | 136 | /*! | ||
1549 | 137 | * \brief Handler for upload progress of a task. | ||
1550 | 138 | * \sa Task::ProgressHandler | ||
1551 | 139 | */ | ||
1552 | 140 | Task::ProgressHandler & progress_changed() override; | ||
1553 | 141 | |||
1554 | 142 | /*! | ||
1555 | 143 | * \brief Handler for upload status of a task. | ||
1556 | 144 | * \sa Task::StatusHandler | ||
1557 | 145 | */ | ||
1558 | 146 | Task::StatusHandler & status_changed() override; | ||
1559 | 147 | |||
1560 | 148 | /*! | ||
1561 | 149 | * \brief Returns a cloud item object associated with the uploaded content. | ||
1562 | 150 | * \note Returns nullptr if task failed to upload regarding content on onedrive. | ||
1563 | 151 | */ | ||
1564 | 152 | std::shared_ptr<CloudItem> upload_item() const; | ||
1565 | 153 | |||
1566 | 154 | /*! | ||
1567 | 155 | * \brief cancel the task. | ||
1568 | 156 | * \sa Task::StatusHandler | ||
1569 | 157 | */ | ||
1570 | 158 | void cancel() override; | ||
1571 | 159 | |||
1572 | 160 | /*! | ||
1573 | 161 | * \brief Returns file size of upload content. | ||
1574 | 162 | */ | ||
1575 | 163 | size_t file_size() const; | ||
1576 | 164 | |||
1577 | 165 | private: | ||
1578 | 166 | UploadTask(std::shared_ptr<UploadTaskPriv> p); | ||
1579 | 167 | |||
1580 | 168 | friend class SyncManagerPriv; | ||
1581 | 169 | |||
1582 | 170 | std::shared_ptr<UploadTaskPriv> p_; | ||
1583 | 171 | }; | ||
1584 | 172 | |||
1585 | 173 | } | ||
1586 | 174 | } | ||
1587 | 175 | |||
1588 | 176 | #endif // ONEDRIVE_API_UPLOADTASK_H_ | ||
1589 | 0 | 177 | ||
1590 | === added file 'include/onedrive/api/visibility.h' | |||
1591 | --- include/onedrive/api/visibility.h 1970-01-01 00:00:00 +0000 | |||
1592 | +++ include/onedrive/api/visibility.h 2016-09-30 08:26:58 +0000 | |||
1593 | @@ -0,0 +1,30 @@ | |||
1594 | 1 | /* | ||
1595 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1596 | 3 | * | ||
1597 | 4 | * This library is free software; you can redistribute it and/or modify it under | ||
1598 | 5 | * the terms of version 3 of the GNU Lesser General Public License as published | ||
1599 | 6 | * by the Free Software Foundation. | ||
1600 | 7 | * | ||
1601 | 8 | * This library is distributed in the hope that it will be useful, but WITHOUT | ||
1602 | 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
1603 | 10 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
1604 | 11 | * details. | ||
1605 | 12 | * | ||
1606 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1607 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1608 | 15 | * | ||
1609 | 16 | * Author: Gary Wang <gary.wang@canonical.com> | ||
1610 | 17 | */ | ||
1611 | 18 | |||
1612 | 19 | #ifndef ONEDRIVE_API_VISIBILITY_H_ | ||
1613 | 20 | #define ONEDRIVE_API_VISIBILITY_H_ | ||
1614 | 21 | |||
1615 | 22 | #if __GNUC__ >= 4 | ||
1616 | 23 | #define ONEDRIVE_API_DLL_PUBLIC __attribute__ ((visibility ("default"))) | ||
1617 | 24 | #define ONEDRIVE_API_DLL_LOCAL __attribute__ ((visibility ("hidden"))) | ||
1618 | 25 | #else | ||
1619 | 26 | #define ONEDRIVE_API_DLL_PUBLIC | ||
1620 | 27 | #define ONEDRIVE_API_DLL_LOCAL | ||
1621 | 28 | #endif | ||
1622 | 29 | |||
1623 | 30 | #endif // ONEDRIVE_API_VISIBILITY_H_ | ||
1624 | 0 | 31 | ||
1625 | === modified file 'provider/CMakeLists.txt' | |||
1626 | --- provider/CMakeLists.txt 2016-09-26 04:27:03 +0000 | |||
1627 | +++ provider/CMakeLists.txt 2016-09-30 08:26:58 +0000 | |||
1628 | @@ -0,0 +1,32 @@ | |||
1629 | 1 | find_package(PkgConfig REQUIRED) | ||
1630 | 2 | find_package(Boost COMPONENTS filesystem system thread REQUIRED) | ||
1631 | 3 | |||
1632 | 4 | pkg_check_modules(STORAGE_FRAMEWORK_PROVIDER storage-framework-provider-1 REQUIRED) | ||
1633 | 5 | |||
1634 | 6 | include_directories(${CMAKE_CURRENT_BINARY_DIR} ${STORAGE_FRAMEWORK_PROVIDER_INCLUDE_DIRS}) | ||
1635 | 7 | |||
1636 | 8 | add_definitions(-DBOOST_THREAD_VERSION=4) | ||
1637 | 9 | |||
1638 | 10 | add_executable(onedrive-provider-bin OnedriveProvider.cpp) | ||
1639 | 11 | |||
1640 | 12 | target_link_libraries( | ||
1641 | 13 | onedrive-provider-bin | ||
1642 | 14 | onedrive-provider | ||
1643 | 15 | |||
1644 | 16 | ${Boost_LIBRARIES} | ||
1645 | 17 | ${STORAGE_FRAMEWORK_PROVIDER_LDFLAGS} | ||
1646 | 18 | ) | ||
1647 | 19 | |||
1648 | 20 | SET_TARGET_PROPERTIES(onedrive-provider-bin | ||
1649 | 21 | PROPERTIES OUTPUT_NAME onedrive-provider | ||
1650 | 22 | ) | ||
1651 | 23 | |||
1652 | 24 | install( | ||
1653 | 25 | TARGETS onedrive-provider-bin | ||
1654 | 26 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | ||
1655 | 27 | ) | ||
1656 | 28 | |||
1657 | 29 | install( | ||
1658 | 30 | FILES ${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.StorageFramework.Provider.OnedriveProvider.service | ||
1659 | 31 | DESTINATION /usr/share/dbus-1/services | ||
1660 | 32 | ) | ||
1661 | 0 | 33 | ||
1662 | === added file 'provider/OnedriveProvider.cpp' | |||
1663 | --- provider/OnedriveProvider.cpp 1970-01-01 00:00:00 +0000 | |||
1664 | +++ provider/OnedriveProvider.cpp 2016-09-30 08:26:58 +0000 | |||
1665 | @@ -0,0 +1,634 @@ | |||
1666 | 1 | /* | ||
1667 | 2 | * Copyright (C) 2016 Canonical Ltd | ||
1668 | 3 | * | ||
1669 | 4 | * This program is free software: you can redistribute it and/or modify | ||
1670 | 5 | * it under the terms of the GNU Lesser General Public License version 3 as | ||
1671 | 6 | * published by the Free Software Foundation. | ||
1672 | 7 | * | ||
1673 | 8 | * This program is distributed in the hope that it will be useful, | ||
1674 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1675 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1676 | 11 | * GNU Lesser General Public License for more details. | ||
1677 | 12 | * | ||
1678 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1679 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1680 | 15 | * | ||
1681 | 16 | * Authors: Gary Wang <gary.wang@canonical.com> | ||
1682 | 17 | */ | ||
1683 | 18 | |||
1684 | 19 | #include "OnedriveProvider.h" | ||
1685 | 20 | #include <unity/storage/provider/ProviderBase.h> | ||
1686 | 21 | #include <unity/storage/provider/Server.h> | ||
1687 | 22 | #include <unity/storage/provider/TempfileUploadJob.h> | ||
1688 | 23 | #include <unity/storage/provider/UploadJob.h> | ||
1689 | 24 | #include <unity/storage/provider/DownloadJob.h> | ||
1690 | 25 | #include <unity/storage/provider/metadata_keys.h> | ||
1691 | 26 | #include <unity/storage/provider/Exceptions.h> | ||
1692 | 27 | |||
1693 | 28 | #include <boost/thread.hpp> | ||
1694 | 29 | #include <boost/thread/future.hpp> | ||
1695 | 30 | #include <boost/filesystem.hpp> | ||
1696 | 31 | #include <boost/make_shared.hpp> | ||
1697 | 32 | |||
1698 | 33 | #include <unistd.h> | ||
1699 | 34 | #include <sys/socket.h> | ||
1700 | 35 | #include <inttypes.h> | ||
1701 | 36 | #include <unistd.h> | ||
1702 | 37 | #include <iostream> | ||
1703 | 38 | #include <memory> | ||
1704 | 39 | #include <mutex> | ||
1705 | 40 | #include <stdexcept> | ||
1706 | 41 | #include <condition_variable> | ||
1707 | 42 | |||
1708 | 43 | #include <onedrive/api/client.h> | ||
1709 | 44 | #include <onedrive/api/uploadtask.h> | ||
1710 | 45 | #include <onedrive/api/syncmanager.h> | ||
1711 | 46 | #include <onedrive/api/cloudresource.h> | ||
1712 | 47 | #include <onedrive/api/cloudcontent.h> | ||
1713 | 48 | #include <onedrive/api/cloudfolder.h> | ||
1714 | 49 | #include <onedrive/api/exceptions.h> | ||
1715 | 50 | |||
1716 | 51 | using namespace std; | ||
1717 | 52 | using namespace unity::storage; | ||
1718 | 53 | using namespace unity::storage::provider; | ||
1719 | 54 | using namespace onedrive::api; | ||
1720 | 55 | |||
1721 | 56 | using boost::make_ready_future; | ||
1722 | 57 | using boost::make_exceptional_future; | ||
1723 | 58 | |||
1724 | 59 | namespace { | ||
1725 | 60 | static const int TIME_OUT = 10; | ||
1726 | 61 | |||
1727 | 62 | static const char *FOLDER_TYPE[] = {"normal", "pictures", "music", "videos", "message", "docs", "app", "sync"}; | ||
1728 | 63 | static const char *CONTENT_TYPE[] = {"all", "image", "audio", "video", "other", "doc", "spreadsheet", "ppt"}; | ||
1729 | 64 | static const char *STATUS[] = {"unstart", "running", "canceled", "paused", "broken", "complete"}; | ||
1730 | 65 | static char constexpr SIZE_IN_BYTES[] = "size_in_bytes"; | ||
1731 | 66 | |||
1732 | 67 | string make_job_id() | ||
1733 | 68 | { | ||
1734 | 69 | static int last_upload_id = 0; | ||
1735 | 70 | return to_string(++last_upload_id); | ||
1736 | 71 | } | ||
1737 | 72 | |||
1738 | 73 | string status_to_string(Task::Status status) | ||
1739 | 74 | { | ||
1740 | 75 | return STATUS[int(status)]; | ||
1741 | 76 | } | ||
1742 | 77 | |||
1743 | 78 | string folder_type_to_string(CloudFolder::Type type) | ||
1744 | 79 | { | ||
1745 | 80 | return FOLDER_TYPE[int(type)]; | ||
1746 | 81 | } | ||
1747 | 82 | |||
1748 | 83 | string content_type_to_string(CloudContent::Type type) | ||
1749 | 84 | { | ||
1750 | 85 | return CONTENT_TYPE[int(type)]; | ||
1751 | 86 | } | ||
1752 | 87 | |||
1753 | 88 | string time_to_iso(time_t t) | ||
1754 | 89 | { | ||
1755 | 90 | char buf[sizeof "2016-08-11T15:10:07"]; | ||
1756 | 91 | strftime(buf, sizeof buf, "%FT%T", gmtime(&t)); | ||
1757 | 92 | return buf; | ||
1758 | 93 | } | ||
1759 | 94 | |||
1760 | 95 | Item content_to_item(CloudResource::Ptr resource) | ||
1761 | 96 | { | ||
1762 | 97 | Item item; | ||
1763 | 98 | item.item_id = resource->id(); | ||
1764 | 99 | item.parent_ids = {resource->folder_id()}; | ||
1765 | 100 | item.name = resource->name(); | ||
1766 | 101 | item.etag = resource->etag(); | ||
1767 | 102 | item.metadata["owner"] = resource->owner(); | ||
1768 | 103 | item.metadata[provider::CREATION_TIME] = time_to_iso(resource->created_date()); | ||
1769 | 104 | item.metadata[provider::LAST_MODIFIED_TIME] = time_to_iso(resource->updated_date()); | ||
1770 | 105 | if (resource->property() == CloudResource::Property::Folder) { | ||
1771 | 106 | item.type = ItemType::folder; | ||
1772 | 107 | auto folder = std::static_pointer_cast<onedrive::api::CloudFolder>(resource); | ||
1773 | 108 | item.metadata["folder_type"] = folder_type_to_string(folder->folder_type()); | ||
1774 | 109 | item.metadata["folder_path"] = folder->folder_path(); | ||
1775 | 110 | } else if (resource->property() == CloudResource::Property::Content){ | ||
1776 | 111 | item.type = ItemType::file; | ||
1777 | 112 | auto file = std::static_pointer_cast<onedrive::api::CloudContent>(resource); | ||
1778 | 113 | item.metadata["suffix"] = file->suffix(); | ||
1779 | 114 | item.metadata["content_type"] = content_type_to_string(file->type()); | ||
1780 | 115 | |||
1781 | 116 | item.metadata[provider::SIZE_IN_BYTES] = file->content_size(); | ||
1782 | 117 | item.metadata["description"] = file->description(); | ||
1783 | 118 | item.metadata["thumbnail_url"] = file->thumbnail_url(); | ||
1784 | 119 | item.metadata["big_thumbnail_url"] = file->big_thumbnail_url(); | ||
1785 | 120 | item.metadata["present_url"] = file->big_thumbnail_url(); | ||
1786 | 121 | } | ||
1787 | 122 | |||
1788 | 123 | return item; | ||
1789 | 124 | } | ||
1790 | 125 | } | ||
1791 | 126 | |||
1792 | 127 | class OnedriveUploadJob : public UploadJob | ||
1793 | 128 | { | ||
1794 | 129 | public: | ||
1795 | 130 | OnedriveUploadJob(string const& upload_id, | ||
1796 | 131 | Client::Ptr client, | ||
1797 | 132 | string const& parent_id, | ||
1798 | 133 | string const& file_name, | ||
1799 | 134 | int64_t size, | ||
1800 | 135 | bool allow_overwrite); | ||
1801 | 136 | |||
1802 | 137 | boost::future<void> cancel() override; | ||
1803 | 138 | boost::future<Item> finish() override; | ||
1804 | 139 | private: | ||
1805 | 140 | boost::future<tuple<bool, string>> upload_data(); | ||
1806 | 141 | void stop_and_cancel(); | ||
1807 | 142 | private: | ||
1808 | 143 | ssize_t feed_size; | ||
1809 | 144 | string parent_id_; | ||
1810 | 145 | string file_name_; | ||
1811 | 146 | int64_t upload_size_; | ||
1812 | 147 | bool allow_overwrite_; | ||
1813 | 148 | |||
1814 | 149 | boost::future<tuple<bool, string>> upload_future_; | ||
1815 | 150 | |||
1816 | 151 | std::mutex mutex_; | ||
1817 | 152 | |||
1818 | 153 | UploadTask::Ptr task_; | ||
1819 | 154 | Client::Ptr client_; | ||
1820 | 155 | }; | ||
1821 | 156 | |||
1822 | 157 | class OnedriveDownloadJob : public DownloadJob | ||
1823 | 158 | { | ||
1824 | 159 | public: | ||
1825 | 160 | using DownloadJob::DownloadJob; | ||
1826 | 161 | |||
1827 | 162 | OnedriveDownloadJob(string const& download_id, | ||
1828 | 163 | string const& item_id, | ||
1829 | 164 | Client::Ptr client); | ||
1830 | 165 | |||
1831 | 166 | boost::future<void> cancel() override; | ||
1832 | 167 | boost::future<void> finish() override; | ||
1833 | 168 | private: | ||
1834 | 169 | boost::future<tuple<bool, string>> download_data(); | ||
1835 | 170 | void send_data(); | ||
1836 | 171 | void stop_and_cancel(); | ||
1837 | 172 | private: | ||
1838 | 173 | string item_id_; | ||
1839 | 174 | boost::future<tuple<bool, string>> download_future_; | ||
1840 | 175 | |||
1841 | 176 | std::mutex mutex_; | ||
1842 | 177 | |||
1843 | 178 | DownloadTask::Ptr task_; | ||
1844 | 179 | Client::Ptr client_; | ||
1845 | 180 | }; | ||
1846 | 181 | |||
1847 | 182 | OnedriveProvider::OnedriveProvider() | ||
1848 | 183 | : client_(std::make_shared<Client>(TIME_OUT)) | ||
1849 | 184 | { | ||
1850 | 185 | } | ||
1851 | 186 | |||
1852 | 187 | boost::future<ItemList> OnedriveProvider::roots(Context const& ctx) | ||
1853 | 188 | { | ||
1854 | 189 | set_access_token(ctx); | ||
1855 | 190 | |||
1856 | 191 | return boost::async([this](){ | ||
1857 | 192 | try { | ||
1858 | 193 | auto root_folder_id = client_->cloud_root_folder_id(); | ||
1859 | 194 | |||
1860 | 195 | ItemList roots = { | ||
1861 | 196 | {root_folder_id, {}, "root", "", ItemType::root, {}} | ||
1862 | 197 | }; | ||
1863 | 198 | |||
1864 | 199 | return make_ready_future<ItemList>(roots); | ||
1865 | 200 | } catch (runtime_error &e) { | ||
1866 | 201 | return make_exceptional_future<ItemList>( | ||
1867 | 202 | RemoteCommsException(string("OnedriveProvider::roots(): failed: ") + e.what())); | ||
1868 | 203 | } | ||
1869 | 204 | }); | ||
1870 | 205 | } | ||
1871 | 206 | |||
1872 | 207 | boost::future<tuple<ItemList,string>> OnedriveProvider::list( | ||
1873 | 208 | string const& item_id, string const& page_token, | ||
1874 | 209 | Context const& ctx) | ||
1875 | 210 | { | ||
1876 | 211 | set_access_token(ctx); | ||
1877 | 212 | |||
1878 | 213 | int page_token_index = 0; | ||
1879 | 214 | if (!page_token.empty()) { | ||
1880 | 215 | try { | ||
1881 | 216 | page_token_index = stoi(page_token); | ||
1882 | 217 | } catch (invalid_argument &e) { | ||
1883 | 218 | return make_exceptional_future<tuple<ItemList,string>>( | ||
1884 | 219 | InvalidArgumentException(string("OnedriveProvider::list(): invalid page token: ") + e.what())); | ||
1885 | 220 | } | ||
1886 | 221 | } | ||
1887 | 222 | |||
1888 | 223 | return boost::async([this, item_id, page_token_index](){ | ||
1889 | 224 | try { | ||
1890 | 225 | const int count_per_page = 50; | ||
1891 | 226 | int start_index = 1 + page_token_index * count_per_page; | ||
1892 | 227 | auto content_list = client_->cloud_content_list(start_index, count_per_page, | ||
1893 | 228 | CloudContent::Type::All, item_id); | ||
1894 | 229 | |||
1895 | 230 | ItemList roots; | ||
1896 | 231 | for (const auto & content: content_list) { | ||
1897 | 232 | roots.push_back(content_to_item(content)); | ||
1898 | 233 | } | ||
1899 | 234 | |||
1900 | 235 | int offset = 0; | ||
1901 | 236 | boost::promise<tuple<ItemList,string>> prom; | ||
1902 | 237 | if (content_list.size() >= count_per_page) { | ||
1903 | 238 | offset++; | ||
1904 | 239 | } | ||
1905 | 240 | prom.set_value(make_tuple(roots, std::to_string(page_token_index + offset))); | ||
1906 | 241 | |||
1907 | 242 | return prom.get_future(); | ||
1908 | 243 | } catch (InvalidIDException &e) { | ||
1909 | 244 | return make_exceptional_future<tuple<ItemList,string>>( | ||
1910 | 245 | NotExistsException(string("OnedriveProvider::list(): failed: ") + e.what(), item_id)); | ||
1911 | 246 | } catch (runtime_error &e) { | ||
1912 | 247 | return make_exceptional_future<tuple<ItemList,string>>( | ||
1913 | 248 | RemoteCommsException(string("OnedriveProvider::list(): failed: ") + e.what())); | ||
1914 | 249 | } | ||
1915 | 250 | }); | ||
1916 | 251 | } | ||
1917 | 252 | |||
1918 | 253 | boost::future<ItemList> OnedriveProvider::lookup( | ||
1919 | 254 | string const& parent_id, string const& name, | ||
1920 | 255 | Context const& ctx) | ||
1921 | 256 | { | ||
1922 | 257 | set_access_token(ctx); | ||
1923 | 258 | |||
1924 | 259 | return boost::async([this, parent_id, name](){ | ||
1925 | 260 | try { | ||
1926 | 261 | const int count_per_page = 50; | ||
1927 | 262 | int page_token_index = 0; | ||
1928 | 263 | int start_index = 0; | ||
1929 | 264 | |||
1930 | 265 | ItemList roots; | ||
1931 | 266 | do { | ||
1932 | 267 | page_token_index++; | ||
1933 | 268 | start_index = 1 + (page_token_index - 1) * count_per_page; | ||
1934 | 269 | auto content_list = client_->cloud_content_list(start_index, count_per_page, | ||
1935 | 270 | CloudContent::Type::All, parent_id); | ||
1936 | 271 | |||
1937 | 272 | for (const auto & content: content_list) { | ||
1938 | 273 | if (content->name().find(name) != string::npos) { | ||
1939 | 274 | roots.push_back(content_to_item(content)); | ||
1940 | 275 | } | ||
1941 | 276 | } | ||
1942 | 277 | |||
1943 | 278 | if (content_list.size() < count_per_page) | ||
1944 | 279 | break; | ||
1945 | 280 | } while (true); | ||
1946 | 281 | |||
1947 | 282 | return make_ready_future<ItemList>(roots); | ||
1948 | 283 | } catch (InvalidIDException &e) { | ||
1949 | 284 | return make_exceptional_future<ItemList>( | ||
1950 | 285 | NotExistsException(string("OnedriveProvider::lookup(): folder not exists: ") + e.what(), parent_id)); | ||
1951 | 286 | } catch (runtime_error &e) { | ||
1952 | 287 | return make_exceptional_future<ItemList>( | ||
1953 | 288 | RemoteCommsException(string("OnedriveProvider::lookup(): failed: ") + e.what())); | ||
1954 | 289 | } | ||
1955 | 290 | }); | ||
1956 | 291 | } | ||
1957 | 292 | |||
1958 | 293 | boost::future<Item> OnedriveProvider::metadata(string const& item_id, | ||
1959 | 294 | Context const& ctx) | ||
1960 | 295 | { | ||
1961 | 296 | set_access_token(ctx); | ||
1962 | 297 | |||
1963 | 298 | return boost::async([this, item_id](){ | ||
1964 | 299 | try { | ||
1965 | 300 | auto content = client_->metadata(item_id); | ||
1966 | 301 | return make_ready_future<Item>(content_to_item(content)); | ||
1967 | 302 | } catch (NonExistentException &e) { | ||
1968 | 303 | return make_exceptional_future<Item>( | ||
1969 | 304 | NotExistsException(string("OnedriveProvider::metadata(): content not exists: ") + e.what(), item_id)); | ||
1970 | 305 | } catch (runtime_error &e) { | ||
1971 | 306 | return make_exceptional_future<Item>( | ||
1972 | 307 | RemoteCommsException(string("OnedriveProvider::metadata(): failed: ") + e.what())); | ||
1973 | 308 | } | ||
1974 | 309 | }); | ||
1975 | 310 | } | ||
1976 | 311 | |||
1977 | 312 | boost::future<Item> OnedriveProvider::create_folder( | ||
1978 | 313 | string const& parent_id, string const& name, | ||
1979 | 314 | Context const& ctx) | ||
1980 | 315 | { | ||
1981 | 316 | set_access_token(ctx); | ||
1982 | 317 | |||
1983 | 318 | return boost::async([this, parent_id, name](){ | ||
1984 | 319 | try { | ||
1985 | 320 | auto content = client_->create_folder(name, parent_id); | ||
1986 | 321 | return make_ready_future<Item>(content_to_item(content)); | ||
1987 | 322 | } catch (NonExistentException &e) { | ||
1988 | 323 | return make_exceptional_future<Item>( | ||
1989 | 324 | NotExistsException(string("OnedriveProvider::create_folder(): name: ") + e.what(), name)); | ||
1990 | 325 | } catch (runtime_error &e) { | ||
1991 | 326 | return make_exceptional_future<Item>( | ||
1992 | 327 | RemoteCommsException(string("OnedriveProvider::create_folder(): failed: ") + e.what())); | ||
1993 | 328 | } | ||
1994 | 329 | }); | ||
1995 | 330 | } | ||
1996 | 331 | |||
1997 | 332 | boost::future<unique_ptr<UploadJob>> OnedriveProvider::create_file( | ||
1998 | 333 | string const& parent_id, string const& name, | ||
1999 | 334 | int64_t size, string const& /*content_type*/, bool allow_overwrite, | ||
2000 | 335 | Context const& ctx) | ||
2001 | 336 | { | ||
2002 | 337 | set_access_token(ctx); | ||
2003 | 338 | |||
2004 | 339 | return make_ready_future(unique_ptr<UploadJob>(new OnedriveUploadJob(make_job_id(), client_, parent_id, name, size, allow_overwrite))); | ||
2005 | 340 | } | ||
2006 | 341 | |||
2007 | 342 | boost::future<unique_ptr<UploadJob>> OnedriveProvider::update( | ||
2008 | 343 | string const& item_id, int64_t size, string const& /*old_etag*/, | ||
2009 | 344 | Context const& ctx) | ||
2010 | 345 | { | ||
2011 | 346 | set_access_token(ctx); | ||
2012 | 347 | |||
2013 | 348 | return boost::async([this, item_id, size, ctx](){ | ||
2014 | 349 | try { | ||
2015 | 350 | auto content = client_->metadata(item_id); | ||
2016 | 351 | auto file_name = content->name(); | ||
2017 | 352 | auto parent_id = content->folder_id(); | ||
2018 | 353 | |||
2019 | 354 | delete_item(item_id, ctx); | ||
2020 | 355 | |||
2021 | 356 | return create_file(parent_id, file_name, size, "", true, ctx); | ||
2022 | 357 | } catch (runtime_error &e) { | ||
2023 | 358 | return make_exceptional_future<unique_ptr<UploadJob>>( | ||
2024 | 359 | RemoteCommsException(string("OnedriveProvider::update(): failed: ") + e.what())); | ||
2025 | 360 | } | ||
2026 | 361 | }); | ||
2027 | 362 | } | ||
2028 | 363 | |||
2029 | 364 | boost::future<unique_ptr<DownloadJob>> OnedriveProvider::download( | ||
2030 | 365 | string const& item_id, Context const& ctx) | ||
2031 | 366 | { | ||
2032 | 367 | set_access_token(ctx); | ||
2033 | 368 | |||
2034 | 369 | return make_ready_future(unique_ptr<DownloadJob>(new OnedriveDownloadJob(make_job_id(), item_id, client_))); | ||
2035 | 370 | } | ||
2036 | 371 | |||
2037 | 372 | boost::future<void> OnedriveProvider::delete_item( | ||
2038 | 373 | string const& item_id, Context const& ctx) | ||
2039 | 374 | { | ||
2040 | 375 | set_access_token(ctx); | ||
2041 | 376 | |||
2042 | 377 | return boost::async([this, item_id](){ | ||
2043 | 378 | try { | ||
2044 | 379 | Client::Stringlist content_id_list{{item_id}}; | ||
2045 | 380 | client_->delete_contents(content_id_list); | ||
2046 | 381 | return make_ready_future(); | ||
2047 | 382 | } catch (ParameterInvalidException &e) { | ||
2048 | 383 | return make_exceptional_future<void>( | ||
2049 | 384 | NotExistsException(string("OnedriveProvider::delete_item(): failed: ") + e.what(), item_id)); | ||
2050 | 385 | } catch (runtime_error &e) { | ||
2051 | 386 | return make_exceptional_future<void>( | ||
2052 | 387 | RemoteCommsException(string("OnedriveProvider::delete_item(): failed: ") + e.what())); | ||
2053 | 388 | } | ||
2054 | 389 | }); | ||
2055 | 390 | } | ||
2056 | 391 | |||
2057 | 392 | boost::future<Item> OnedriveProvider::move( | ||
2058 | 393 | string const& item_id, string const& new_parent_id, | ||
2059 | 394 | string const& /*new_name*/, Context const& ctx) | ||
2060 | 395 | { | ||
2061 | 396 | set_access_token(ctx); | ||
2062 | 397 | |||
2063 | 398 | return boost::async([this, item_id, new_parent_id](){ | ||
2064 | 399 | try { | ||
2065 | 400 | Client::Stringlist folderlist; | ||
2066 | 401 | Client::Stringlist contentlist{{item_id}}; | ||
2067 | 402 | client_->move_items(folderlist, contentlist, new_parent_id); | ||
2068 | 403 | auto content = client_->metadata(item_id); | ||
2069 | 404 | return make_ready_future<Item>(content_to_item(content)); | ||
2070 | 405 | } catch (NonExistentException &e) { | ||
2071 | 406 | return make_exceptional_future<Item>( | ||
2072 | 407 | NotExistsException(string("OnedriveProvider::move(): content or folder not exist: ") + e.what(), "")); | ||
2073 | 408 | } catch (runtime_error &e) { | ||
2074 | 409 | return make_exceptional_future<Item>( | ||
2075 | 410 | RemoteCommsException(string("OnedriveProvider::move(): failed: ") + e.what())); | ||
2076 | 411 | } | ||
2077 | 412 | }); | ||
2078 | 413 | } | ||
2079 | 414 | |||
2080 | 415 | boost::future<Item> OnedriveProvider::copy( | ||
2081 | 416 | string const& item_id, string const& new_parent_id, | ||
2082 | 417 | string const& /*new_name*/, Context const& ctx) | ||
2083 | 418 | { | ||
2084 | 419 | set_access_token(ctx); | ||
2085 | 420 | |||
2086 | 421 | return boost::async([this, item_id, new_parent_id](){ | ||
2087 | 422 | try { | ||
2088 | 423 | Client::Stringlist content_list{{item_id}}; | ||
2089 | 424 | auto content_id = client_->copy_contents(content_list, new_parent_id)[0]; | ||
2090 | 425 | auto content = client_->metadata(content_id); | ||
2091 | 426 | return make_ready_future<Item>(content_to_item(content)); | ||
2092 | 427 | } catch (NonExistentException &e) { | ||
2093 | 428 | return make_exceptional_future<Item>( | ||
2094 | 429 | NotExistsException(string("OnedriveProvider::copy(): content or folder not exist: ") + e.what(), item_id)); | ||
2095 | 430 | } catch (runtime_error &e) { | ||
2096 | 431 | return make_exceptional_future<Item>( | ||
2097 | 432 | RemoteCommsException(string("OnedriveProvider::copy(): failed: ") + e.what())); | ||
2098 | 433 | } | ||
2099 | 434 | }); | ||
2100 | 435 | } | ||
2101 | 436 | |||
2102 | 437 | void OnedriveProvider::set_access_token(Context const& ctx) { | ||
2103 | 438 | auto access_token = boost::get<OAuth2Credentials>(ctx.credentials).access_token; | ||
2104 | 439 | std::cout <<"onedrive access_token: " << access_token << std::endl; | ||
2105 | 440 | client_->set_access_token(access_token); | ||
2106 | 441 | } | ||
2107 | 442 | |||
2108 | 443 | OnedriveUploadJob::OnedriveUploadJob(string const &upload_id, | ||
2109 | 444 | Client::Ptr client, | ||
2110 | 445 | string const& parent_id, | ||
2111 | 446 | string const& file_name, | ||
2112 | 447 | int64_t size, | ||
2113 | 448 | bool allow_overwrite) | ||
2114 | 449 | : UploadJob(upload_id) | ||
2115 | 450 | , parent_id_(parent_id) | ||
2116 | 451 | , file_name_(file_name) | ||
2117 | 452 | , upload_size_(size) | ||
2118 | 453 | , allow_overwrite_(allow_overwrite) | ||
2119 | 454 | , task_(nullptr) | ||
2120 | 455 | , client_(client) | ||
2121 | 456 | { | ||
2122 | 457 | upload_future_ = upload_data(); | ||
2123 | 458 | } | ||
2124 | 459 | |||
2125 | 460 | boost::future<void> OnedriveUploadJob::cancel() | ||
2126 | 461 | { | ||
2127 | 462 | printf("cancel_upload('%s')\n", upload_id().c_str()); | ||
2128 | 463 | stop_and_cancel(); | ||
2129 | 464 | |||
2130 | 465 | return make_ready_future(); | ||
2131 | 466 | } | ||
2132 | 467 | |||
2133 | 468 | boost::future<Item> OnedriveUploadJob::finish() | ||
2134 | 469 | { | ||
2135 | 470 | printf("finish_upload('%s')\n", upload_id().c_str()); | ||
2136 | 471 | return boost::async([this](){ | ||
2137 | 472 | try { | ||
2138 | 473 | auto upload_ctx = upload_future_.get(); | ||
2139 | 474 | auto upload_ok = get<0>(upload_ctx); | ||
2140 | 475 | auto error_str = get<1>(upload_ctx); | ||
2141 | 476 | if (upload_ok){ | ||
2142 | 477 | auto content = client_->metadata(task_->content_id()); | ||
2143 | 478 | return make_ready_future<Item>(content_to_item(content)); | ||
2144 | 479 | } | ||
2145 | 480 | |||
2146 | 481 | return make_exceptional_future<Item>( | ||
2147 | 482 | RemoteCommsException(string("OnedriveUploadJob::finish(): failed: ") + error_str)); | ||
2148 | 483 | } catch (runtime_error &e) { | ||
2149 | 484 | return make_exceptional_future<Item>( | ||
2150 | 485 | RemoteCommsException(string("OnedriveUploadJob::finish(): failed: ") + e.what())); | ||
2151 | 486 | } | ||
2152 | 487 | }); | ||
2153 | 488 | } | ||
2154 | 489 | |||
2155 | 490 | boost::future<tuple<bool, string>> OnedriveUploadJob::upload_data() | ||
2156 | 491 | { | ||
2157 | 492 | auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>(); | ||
2158 | 493 | |||
2159 | 494 | return boost::async([this, prom](){ | ||
2160 | 495 | std::lock_guard<std::mutex> guard(mutex_); | ||
2161 | 496 | |||
2162 | 497 | int socket_fd = read_socket(); | ||
2163 | 498 | UploadBufferList buffer_item_list{{[socket_fd](void *dest, size_t buf_size) -> size_t { | ||
2164 | 499 | //data reading callback. | ||
2165 | 500 | size_t read_size = read(socket_fd, dest, buf_size); | ||
2166 | 501 | if (read_size == 0) | ||
2167 | 502 | return -1; | ||
2168 | 503 | return read_size; | ||
2169 | 504 | }, (size_t)upload_size_, parent_id_, file_name_}}; | ||
2170 | 505 | |||
2171 | 506 | try { | ||
2172 | 507 | task_ = client_->syncmanager()->add_upload_tasks(buffer_item_list)[0]; | ||
2173 | 508 | task_->status_changed() = [this, prom](Task::Status status) { | ||
2174 | 509 | std::cout << " status: " << status_to_string(status) << std::endl; | ||
2175 | 510 | if (status == Task::Status::Complete){ | ||
2176 | 511 | prom->set_value(make_tuple(true, string())); | ||
2177 | 512 | } else if (status == Task::Status::Canceled || | ||
2178 | 513 | status == Task::Status::Broken) { | ||
2179 | 514 | prom->set_value(make_tuple(false, task_->error_string())); | ||
2180 | 515 | } | ||
2181 | 516 | }; | ||
2182 | 517 | task_->progress_changed() = [this](float percent) { | ||
2183 | 518 | cout<< "uploading: " << task_->content_name() << " " << percent << endl; | ||
2184 | 519 | }; | ||
2185 | 520 | } catch (runtime_error & e) { | ||
2186 | 521 | prom->set_value(make_tuple(false, e.what())); | ||
2187 | 522 | } | ||
2188 | 523 | |||
2189 | 524 | return prom->get_future(); | ||
2190 | 525 | }); | ||
2191 | 526 | } | ||
2192 | 527 | |||
2193 | 528 | void OnedriveUploadJob::stop_and_cancel() | ||
2194 | 529 | { | ||
2195 | 530 | std::lock_guard<std::mutex> guard(mutex_); | ||
2196 | 531 | |||
2197 | 532 | if (task_ != nullptr && | ||
2198 | 533 | (task_->status() != Task::Status::Broken && | ||
2199 | 534 | task_->status() != Task::Status::Complete)) { | ||
2200 | 535 | task_->cancel(); | ||
2201 | 536 | } | ||
2202 | 537 | } | ||
2203 | 538 | |||
2204 | 539 | OnedriveDownloadJob::OnedriveDownloadJob(string const &download_id, | ||
2205 | 540 | string const &item_id, | ||
2206 | 541 | Client::Ptr client) | ||
2207 | 542 | : DownloadJob(download_id) | ||
2208 | 543 | , item_id_(item_id) | ||
2209 | 544 | , task_(nullptr) | ||
2210 | 545 | , client_(client) | ||
2211 | 546 | { | ||
2212 | 547 | download_future_ = download_data(); | ||
2213 | 548 | } | ||
2214 | 549 | |||
2215 | 550 | boost::future<void> OnedriveDownloadJob::cancel() | ||
2216 | 551 | { | ||
2217 | 552 | stop_and_cancel(); | ||
2218 | 553 | |||
2219 | 554 | printf("cancel_download('%s')\n", download_id().c_str()); | ||
2220 | 555 | return make_ready_future(); | ||
2221 | 556 | } | ||
2222 | 557 | |||
2223 | 558 | boost::future<void> OnedriveDownloadJob::finish() | ||
2224 | 559 | { | ||
2225 | 560 | return boost::async([this]() { | ||
2226 | 561 | auto download_ctx = download_future_.get(); | ||
2227 | 562 | auto download_ok = get<0>(download_ctx); | ||
2228 | 563 | auto error_str = get<1>(download_ctx); | ||
2229 | 564 | if (download_ok){ | ||
2230 | 565 | return make_ready_future(); | ||
2231 | 566 | } | ||
2232 | 567 | |||
2233 | 568 | return make_exceptional_future<void>( | ||
2234 | 569 | RemoteCommsException(string("failed to download from onedrive: ") + error_str)); | ||
2235 | 570 | }); | ||
2236 | 571 | } | ||
2237 | 572 | |||
2238 | 573 | boost::future<tuple<bool, string>> OnedriveDownloadJob::download_data() | ||
2239 | 574 | { | ||
2240 | 575 | auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>(); | ||
2241 | 576 | |||
2242 | 577 | return boost::async([this, prom](){ | ||
2243 | 578 | std::lock_guard<std::mutex> guard(mutex_); | ||
2244 | 579 | |||
2245 | 580 | int socket_fd = write_socket(); | ||
2246 | 581 | DownloadBufferList buffer_item_list{{item_id_, | ||
2247 | 582 | [socket_fd](void *dest, size_t buf_size) -> size_t { | ||
2248 | 583 | //data writing callback. | ||
2249 | 584 | return write(socket_fd, dest, buf_size); | ||
2250 | 585 | } | ||
2251 | 586 | }}; | ||
2252 | 587 | |||
2253 | 588 | try { | ||
2254 | 589 | task_ = client_->syncmanager()->add_download_tasks(buffer_item_list)[0]; | ||
2255 | 590 | task_->status_changed() = [this, prom](Task::Status status) { | ||
2256 | 591 | std::cout << " status: " << status_to_string(status) << std::endl; | ||
2257 | 592 | if (status == Task::Status::Complete) { | ||
2258 | 593 | report_complete(); | ||
2259 | 594 | prom->set_value(make_tuple(true, string())); | ||
2260 | 595 | } else if (status == Task::Status::Canceled || | ||
2261 | 596 | status == Task::Status::Broken) { | ||
2262 | 597 | prom->set_value(make_tuple(false, task_->error_string())); | ||
2263 | 598 | } | ||
2264 | 599 | }; | ||
2265 | 600 | task_->progress_changed() = [this](float percent) { | ||
2266 | 601 | cout<< "downloading: " << task_->content_name() << " " << percent << endl; | ||
2267 | 602 | }; | ||
2268 | 603 | } catch (runtime_error & e) { | ||
2269 | 604 | prom->set_value(make_tuple(false, e.what())); | ||
2270 | 605 | } | ||
2271 | 606 | |||
2272 | 607 | return prom->get_future(); | ||
2273 | 608 | }); | ||
2274 | 609 | } | ||
2275 | 610 | |||
2276 | 611 | void OnedriveDownloadJob::stop_and_cancel() | ||
2277 | 612 | { | ||
2278 | 613 | std::lock_guard<std::mutex> guard(mutex_); | ||
2279 | 614 | |||
2280 | 615 | if (task_ != nullptr && | ||
2281 | 616 | (task_->status() != Task::Status::Broken && | ||
2282 | 617 | task_->status() != Task::Status::Complete)) { | ||
2283 | 618 | task_->cancel(); | ||
2284 | 619 | } | ||
2285 | 620 | } | ||
2286 | 621 | |||
2287 | 622 | int main(int argc, char **argv) | ||
2288 | 623 | { | ||
2289 | 624 | const std::string bus_name = "com.canonical.StorageFramework.Provider.OnedriveProvider"; | ||
2290 | 625 | std::string account_service_id = "com.canonical.scopes.onedrive_onedrive_onedrive"; | ||
2291 | 626 | if (argc > 1) | ||
2292 | 627 | { | ||
2293 | 628 | account_service_id = argv[1]; | ||
2294 | 629 | } | ||
2295 | 630 | |||
2296 | 631 | Server<OnedriveProvider> server(bus_name, account_service_id); | ||
2297 | 632 | server.init(argc, argv); | ||
2298 | 633 | server.run(); | ||
2299 | 634 | } | ||
2300 | 0 | 635 | ||
2301 | === added file 'provider/OnedriveProvider.h' | |||
2302 | --- provider/OnedriveProvider.h 1970-01-01 00:00:00 +0000 | |||
2303 | +++ provider/OnedriveProvider.h 2016-09-30 08:26:58 +0000 | |||
2304 | @@ -0,0 +1,74 @@ | |||
2305 | 1 | /* | ||
2306 | 2 | * Copyright (C) 2016 Canonical Ltd | ||
2307 | 3 | * | ||
2308 | 4 | * This program is free software: you can redistribute it and/or modify | ||
2309 | 5 | * it under the terms of the GNU Lesser General Public License version 3 as | ||
2310 | 6 | * published by the Free Software Foundation. | ||
2311 | 7 | * | ||
2312 | 8 | * This program is distributed in the hope that it will be useful, | ||
2313 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2314 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2315 | 11 | * GNU Lesser General Public License for more details. | ||
2316 | 12 | * | ||
2317 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2318 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2319 | 15 | * | ||
2320 | 16 | * Authors: Gary Wang <gary.wang@canonical.com> | ||
2321 | 17 | */ | ||
2322 | 18 | |||
2323 | 19 | #pragma once | ||
2324 | 20 | |||
2325 | 21 | #include <unity/storage/provider/ProviderBase.h> | ||
2326 | 22 | #include <onedrive/api/client.h> | ||
2327 | 23 | |||
2328 | 24 | using namespace std; | ||
2329 | 25 | using namespace onedrive::api; | ||
2330 | 26 | using unity::storage::provider::Context; | ||
2331 | 27 | using unity::storage::provider::DownloadJob; | ||
2332 | 28 | using unity::storage::provider::ProviderBase; | ||
2333 | 29 | using unity::storage::provider::Item; | ||
2334 | 30 | using unity::storage::provider::ItemList; | ||
2335 | 31 | using unity::storage::provider::UploadJob; | ||
2336 | 32 | |||
2337 | 33 | class OnedriveProvider : public ProviderBase { | ||
2338 | 34 | public: | ||
2339 | 35 | OnedriveProvider(); | ||
2340 | 36 | |||
2341 | 37 | boost::future<ItemList> roots(Context const& ctx) override; | ||
2342 | 38 | boost::future<tuple<ItemList,string>> list( | ||
2343 | 39 | string const& item_id, string const& page_token, | ||
2344 | 40 | Context const& ctx) override; | ||
2345 | 41 | boost::future<ItemList> lookup( | ||
2346 | 42 | string const& parent_id, string const& name, | ||
2347 | 43 | Context const& ctx) override; | ||
2348 | 44 | boost::future<Item> metadata( | ||
2349 | 45 | string const& item_id, Context const& ctx) override; | ||
2350 | 46 | boost::future<Item> create_folder( | ||
2351 | 47 | string const& parent_id, string const& name, | ||
2352 | 48 | Context const& ctx) override; | ||
2353 | 49 | |||
2354 | 50 | boost::future<unique_ptr<UploadJob>> create_file( | ||
2355 | 51 | string const& parent_id, string const& name, | ||
2356 | 52 | int64_t size, string const& content_type, bool allow_overwrite, | ||
2357 | 53 | Context const& ctx) override; | ||
2358 | 54 | boost::future<unique_ptr<UploadJob>> update( | ||
2359 | 55 | string const& item_id, int64_t size, string const& old_etag, | ||
2360 | 56 | Context const& ctx) override; | ||
2361 | 57 | |||
2362 | 58 | boost::future<unique_ptr<DownloadJob>> download( | ||
2363 | 59 | string const& item_id, Context const& ctx) override; | ||
2364 | 60 | |||
2365 | 61 | boost::future<void> delete_item( | ||
2366 | 62 | string const& item_id, Context const& ctx) override; | ||
2367 | 63 | boost::future<Item> move( | ||
2368 | 64 | string const& item_id, string const& new_parent_id, | ||
2369 | 65 | string const& new_name, Context const& ctx) override; | ||
2370 | 66 | boost::future<Item> copy( | ||
2371 | 67 | string const& item_id, string const& new_parent_id, | ||
2372 | 68 | string const& new_name, Context const& ctx) override; | ||
2373 | 69 | |||
2374 | 70 | private: | ||
2375 | 71 | void set_access_token(Context const& ctx); | ||
2376 | 72 | private: | ||
2377 | 73 | Client::Ptr client_; | ||
2378 | 74 | }; | ||
2379 | 0 | 75 | ||
2380 | === added file 'provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service' | |||
2381 | --- provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service 1970-01-01 00:00:00 +0000 | |||
2382 | +++ provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service 2016-09-30 08:26:58 +0000 | |||
2383 | @@ -0,0 +1,3 @@ | |||
2384 | 1 | [D-BUS Service] | ||
2385 | 2 | Name=com.canonical.StorageFramework.Provider.OnedriveProvider | ||
2386 | 3 | Exec=/usr/bin/onedrive-provider | ||
2387 | 0 | 4 | ||
2388 | === modified file 'src/CMakeLists.txt' | |||
2389 | --- src/CMakeLists.txt 2016-09-26 04:27:03 +0000 | |||
2390 | +++ src/CMakeLists.txt 2016-09-30 08:26:58 +0000 | |||
2391 | @@ -17,10 +17,53 @@ | |||
2392 | 17 | find_package(Boost COMPONENTS regex filesystem system REQUIRED) | 17 | find_package(Boost COMPONENTS regex filesystem system REQUIRED) |
2393 | 18 | find_package(PkgConfig REQUIRED) | 18 | find_package(PkgConfig REQUIRED) |
2394 | 19 | 19 | ||
2395 | 20 | include_directories(${Boost_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS}) | ||
2396 | 21 | |||
2397 | 22 | pkg_check_modules(JSON_CPP jsoncpp REQUIRED) | 20 | pkg_check_modules(JSON_CPP jsoncpp REQUIRED) |
2398 | 23 | pkg_check_modules(NET_CPP net-cpp>=1.3.0 REQUIRED) | 21 | pkg_check_modules(NET_CPP net-cpp>=1.3.0 REQUIRED) |
2400 | 24 | pkg_check_modules(PROCESS_CPP process-cpp REQUIRED) | 22 | |
2401 | 23 | include_directories(${Boost_INCLUDE_DIRS} ${JSON_CPP_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS}) | ||
2402 | 24 | |||
2403 | 25 | add_library( | ||
2404 | 26 | onedrive-provider SHARED | ||
2405 | 27 | |||
2406 | 28 | ${ONEDRIVE_PROVIDER_LIB_INTERFACE_HEADERS} | ||
2407 | 29 | |||
2408 | 30 | onedrive/api/client.cpp | ||
2409 | 31 | onedrive/api/client_priv.cpp | ||
2410 | 32 | onedrive/api/cloudfolder.cpp | ||
2411 | 33 | onedrive/api/clouditem.cpp | ||
2412 | 34 | onedrive/api/downloadtask.cpp | ||
2413 | 35 | onedrive/api/downloadtask_priv.cpp | ||
2414 | 36 | onedrive/api/uploadtask.cpp | ||
2415 | 37 | onedrive/api/uploadtask_priv.cpp | ||
2416 | 38 | onedrive/api/syncmanager.cpp | ||
2417 | 39 | onedrive/api/syncmanager_priv.cpp | ||
2418 | 40 | onedrive/api/syncthread.cpp | ||
2419 | 41 | onedrive/api/storageinfo.cpp | ||
2420 | 42 | onedrive/api/client.cpp | ||
2421 | 43 | ) | ||
2422 | 44 | |||
2423 | 45 | target_link_libraries( | ||
2424 | 46 | onedrive-provider | ||
2425 | 47 | |||
2426 | 48 | ${CMAKE_THREAD_LIBS_INIT} | ||
2427 | 49 | |||
2428 | 50 | ${Boost_LIBRARIES} | ||
2429 | 51 | ${JSON_CPP_LIBRARIES} | ||
2430 | 52 | ${NET_CPP_LDFLAGS} | ||
2431 | 53 | ) | ||
2432 | 25 | 54 | ||
2433 | 26 | set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map") | 55 | set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map") |
2434 | 56 | set_target_properties( | ||
2435 | 57 | onedrive-provider | ||
2436 | 58 | |||
2437 | 59 | PROPERTIES | ||
2438 | 60 | LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}" | ||
2439 | 61 | LINK_DEPENDS ${symbol_map} | ||
2440 | 62 | VERSION ${ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR}.${ONEDRIVE_PROVIDER_LIB_VERSION_MINOR}.${ONEDRIVE_PROVIDER_LIB_VERSION_PATCH} | ||
2441 | 63 | SOVERSION ${ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR} | ||
2442 | 64 | ) | ||
2443 | 65 | |||
2444 | 66 | install( | ||
2445 | 67 | TARGETS onedrive-provider | ||
2446 | 68 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | ||
2447 | 69 | ) | ||
2448 | 27 | 70 | ||
2449 | === added file 'src/onedrive/api/client.cpp' | |||
2450 | --- src/onedrive/api/client.cpp 1970-01-01 00:00:00 +0000 | |||
2451 | +++ src/onedrive/api/client.cpp 2016-09-30 08:26:58 +0000 | |||
2452 | @@ -0,0 +1,106 @@ | |||
2453 | 1 | /* | ||
2454 | 2 | * Copyright © 2016 Canonical Ltd. | ||
2455 | 3 | * | ||
2456 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2457 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
2458 | 6 | * as published by the Free Software Foundation. | ||
2459 | 7 | * | ||
2460 | 8 | * This program is distributed in the hope that it will be useful, | ||
2461 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2462 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2463 | 11 | * GNU Lesser General Public License for more details. | ||
2464 | 12 | * | ||
2465 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2466 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2467 | 15 | * | ||
2468 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
2469 | 17 | */ | ||
2470 | 18 | |||
2471 | 19 | #include <onedrive/api/client.h> | ||
2472 | 20 | #include "client_priv.h" | ||
2473 | 21 | |||
2474 | 22 | #include <core/net/error.h> | ||
2475 | 23 | #include <core/net/uri.h> | ||
2476 | 24 | #include <core/net/http/client.h> | ||
2477 | 25 | #include <core/net/http/request.h> | ||
2478 | 26 | #include <core/net/http/response.h> | ||
2479 | 27 | |||
2480 | 28 | #include <boost/filesystem.hpp> | ||
2481 | 29 | #include <boost/algorithm/string.hpp> | ||
2482 | 30 | |||
2483 | 31 | using namespace onedrive::api; | ||
2484 | 32 | using namespace std; | ||
2485 | 33 | |||
2486 | 34 | Client::Client(int request_timeout) | ||
2487 | 35 | : p(std::make_shared<ClientPriv>(request_timeout)) { | ||
2488 | 36 | |||
2489 | 37 | } | ||
2490 | 38 | |||
2491 | 39 | Client::~Client() { | ||
2492 | 40 | p->sync_manager()->cancel(); | ||
2493 | 41 | } | ||
2494 | 42 | |||
2495 | 43 | void Client::set_access_token(const string &access_token) { | ||
2496 | 44 | p->set_access_token(access_token); | ||
2497 | 45 | // p->sync_manager()- | ||
2498 | 46 | } | ||
2499 | 47 | |||
2500 | 48 | StorageInfo Client::storage_info() { | ||
2501 | 49 | return p->storage_info(); | ||
2502 | 50 | } | ||
2503 | 51 | |||
2504 | 52 | CloudFolder::Ptr Client::root_folder() { | ||
2505 | 53 | return p->root_folder(); | ||
2506 | 54 | } | ||
2507 | 55 | |||
2508 | 56 | tuple<Client::ResourceList, string> Client::cloud_content_list(const std::string &folder_id, | ||
2509 | 57 | const std::string &page_token) { | ||
2510 | 58 | return p->cloud_content_list(folder_id, page_token); | ||
2511 | 59 | } | ||
2512 | 60 | |||
2513 | 61 | CloudResource::Ptr Client::metadata(const string &content_id) { | ||
2514 | 62 | return p->metadata(content_id); | ||
2515 | 63 | } | ||
2516 | 64 | |||
2517 | 65 | CloudFolder::Ptr Client::create_folder(const string &folder_name, | ||
2518 | 66 | const string &folder_id) { | ||
2519 | 67 | return p->create_folder(folder_name, folder_id); | ||
2520 | 68 | } | ||
2521 | 69 | |||
2522 | 70 | Client::ResourceList Client::search(const string &name, | ||
2523 | 71 | const string &parent_folder_id) { | ||
2524 | 72 | return p->search(name, parent_folder_id); | ||
2525 | 73 | } | ||
2526 | 74 | |||
2527 | 75 | CloudResource::Ptr Client::move_item(const std::string &item_id, | ||
2528 | 76 | const std::string &folder_id, | ||
2529 | 77 | const std::string &item_name) { | ||
2530 | 78 | return p->move_item(item_id, folder_id, item_name); | ||
2531 | 79 | } | ||
2532 | 80 | |||
2533 | 81 | bool Client::delete_item(const string &content_id) { | ||
2534 | 82 | return p->delete_item(content_id); | ||
2535 | 83 | } | ||
2536 | 84 | |||
2537 | 85 | /* | ||
2538 | 86 | CloudResource::Ptr Client::copy_item(const string &item_id, | ||
2539 | 87 | const string &name, | ||
2540 | 88 | const string &folder_id) { | ||
2541 | 89 | return p->copy_item(item_id, name, folder_id); | ||
2542 | 90 | } | ||
2543 | 91 | */ | ||
2544 | 92 | |||
2545 | 93 | CloudResource::Ptr Client::rename_item(const string &item_id, | ||
2546 | 94 | const string &name) { | ||
2547 | 95 | return p->rename_item(item_id, name); | ||
2548 | 96 | } | ||
2549 | 97 | |||
2550 | 98 | //bool Client::refresh_token(const string &refresh_token) { | ||
2551 | 99 | // return p->refersh_token(refresh_token); | ||
2552 | 100 | //} | ||
2553 | 101 | |||
2554 | 102 | SyncManager::Ptr Client::syncmanager() const { | ||
2555 | 103 | return p->sync_manager(); | ||
2556 | 104 | } | ||
2557 | 105 | |||
2558 | 106 | |||
2559 | 0 | 107 | ||
2560 | === added file 'src/onedrive/api/client_priv.cpp' | |||
2561 | --- src/onedrive/api/client_priv.cpp 1970-01-01 00:00:00 +0000 | |||
2562 | +++ src/onedrive/api/client_priv.cpp 2016-09-30 08:26:58 +0000 | |||
2563 | @@ -0,0 +1,780 @@ | |||
2564 | 1 | /* | ||
2565 | 2 | * Copyright © 2016 Canonical Ltd. | ||
2566 | 3 | * | ||
2567 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2568 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
2569 | 6 | * as published by the Free Software Foundation. | ||
2570 | 7 | * | ||
2571 | 8 | * This program is distributed in the hope that it will be useful, | ||
2572 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2573 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2574 | 11 | * GNU Lesser General Public License for more details. | ||
2575 | 12 | * | ||
2576 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2577 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2578 | 15 | * | ||
2579 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
2580 | 17 | */ | ||
2581 | 18 | |||
2582 | 19 | #include "client_priv.h" | ||
2583 | 20 | #include "syncmanager_priv.h" | ||
2584 | 21 | #include "config.h" | ||
2585 | 22 | |||
2586 | 23 | #include <onedrive/api/cloudfolder.h> | ||
2587 | 24 | #include <onedrive/api/clouditem.h> | ||
2588 | 25 | #include <onedrive/api/storageinfo.h> | ||
2589 | 26 | #include <onedrive/api/downloadtask.h> | ||
2590 | 27 | #include <onedrive/api/uploadtask.h> | ||
2591 | 28 | #include <onedrive/api/cloudresource.h> | ||
2592 | 29 | #include <onedrive/api/syncmanager.h> | ||
2593 | 30 | #include <onedrive/api/exceptions.h> | ||
2594 | 31 | |||
2595 | 32 | #include <core/net/error.h> | ||
2596 | 33 | #include <core/net/uri.h> | ||
2597 | 34 | #include <core/net/http/client.h> | ||
2598 | 35 | #include <core/net/http/request.h> | ||
2599 | 36 | #include <core/net/http/response.h> | ||
2600 | 37 | |||
2601 | 38 | #include <boost/algorithm/string.hpp> | ||
2602 | 39 | #include <boost/algorithm/string/regex.hpp> | ||
2603 | 40 | #include <boost/filesystem.hpp> | ||
2604 | 41 | #include <boost/regex.hpp> | ||
2605 | 42 | |||
2606 | 43 | #include <json/json.h> | ||
2607 | 44 | |||
2608 | 45 | #include <iostream> | ||
2609 | 46 | #include <unordered_map> | ||
2610 | 47 | |||
2611 | 48 | namespace http = core::net::http; | ||
2612 | 49 | namespace json = Json; | ||
2613 | 50 | namespace net = core::net; | ||
2614 | 51 | |||
2615 | 52 | namespace fs = boost::filesystem; | ||
2616 | 53 | namespace alg = boost::algorithm; | ||
2617 | 54 | |||
2618 | 55 | using namespace onedrive::api; | ||
2619 | 56 | using namespace std; | ||
2620 | 57 | |||
2621 | 58 | namespace { | ||
2622 | 59 | |||
2623 | 60 | template<typename T> | ||
2624 | 61 | static void set_exception(std::shared_ptr<std::promise<T>> prom, | ||
2625 | 62 | const json::Value &root) { | ||
2626 | 63 | if (root.isMember("error")) { | ||
2627 | 64 | std::string code = root["error"]["code"].asString(); | ||
2628 | 65 | std::string msg = root["error"]["message"].asString(); | ||
2629 | 66 | if (code == "unauthenticated") { | ||
2630 | 67 | prom->set_exception(make_exception_ptr(CredentialException(msg))); | ||
2631 | 68 | } else if (code == "itemNotFound") { | ||
2632 | 69 | prom->set_exception(make_exception_ptr(NonExistentException(msg))); | ||
2633 | 70 | } else if (code == "invalidRequest") { | ||
2634 | 71 | prom->set_exception(make_exception_ptr(ParameterInvalidException(msg))); | ||
2635 | 72 | } else if (code == "quotaLimitReached") { | ||
2636 | 73 | prom->set_exception(make_exception_ptr(CredentialException(msg))); | ||
2637 | 74 | } else if (code == "serviceNotAvailable") { | ||
2638 | 75 | prom->set_exception(make_exception_ptr(ServiceNotAvailableException(msg))); | ||
2639 | 76 | } | ||
2640 | 77 | |||
2641 | 78 | return; | ||
2642 | 79 | } | ||
2643 | 80 | |||
2644 | 81 | prom->set_exception(make_exception_ptr(UnknownException(root.toStyledString()))); | ||
2645 | 82 | } | ||
2646 | 83 | |||
2647 | 84 | } | ||
2648 | 85 | |||
2649 | 86 | class ClientPriv::HttpClient { | ||
2650 | 87 | public: | ||
2651 | 88 | HttpClient(int request_timeout) : | ||
2652 | 89 | client_(http::make_client()), | ||
2653 | 90 | worker_ { [this]() {client_->run();} }, | ||
2654 | 91 | cancelled_(false) { | ||
2655 | 92 | config_.request_timeout = request_timeout; | ||
2656 | 93 | } | ||
2657 | 94 | |||
2658 | 95 | ~HttpClient() { | ||
2659 | 96 | client_->stop(); | ||
2660 | 97 | if (worker_.joinable()) { | ||
2661 | 98 | worker_.join(); | ||
2662 | 99 | } | ||
2663 | 100 | } | ||
2664 | 101 | |||
2665 | 102 | std::shared_ptr<core::net::http::Client> client_; | ||
2666 | 103 | |||
2667 | 104 | std::thread worker_; | ||
2668 | 105 | |||
2669 | 106 | Config config_; | ||
2670 | 107 | |||
2671 | 108 | std::mutex config_mutex_; | ||
2672 | 109 | |||
2673 | 110 | std::atomic<bool> cancelled_; | ||
2674 | 111 | |||
2675 | 112 | void get(const net::Uri::Path &path, | ||
2676 | 113 | const net::Uri::QueryParameters ¶meters, | ||
2677 | 114 | http::Request::Handler &handler) { | ||
2678 | 115 | auto configuration = net_config(path, parameters); | ||
2679 | 116 | configuration.header.add("User-Agent", config_.user_agent); | ||
2680 | 117 | |||
2681 | 118 | auto request = client_->head(configuration); | ||
2682 | 119 | request->async_execute(handler); | ||
2683 | 120 | } | ||
2684 | 121 | |||
2685 | 122 | void post(const net::Uri::Path &path, | ||
2686 | 123 | const net::Uri::QueryParameters ¶meters, | ||
2687 | 124 | const std::string &postbody, | ||
2688 | 125 | const std::string &content_type, | ||
2689 | 126 | http::Request::Handler &handler) { | ||
2690 | 127 | std::lock_guard<std::mutex> lock(config_mutex_); | ||
2691 | 128 | http::Request::Configuration configuration = net_config(path, parameters); | ||
2692 | 129 | configuration.header.add("User-Agent", config_.user_agent); | ||
2693 | 130 | configuration.header.add("Content-Length", std::to_string(postbody.size())); | ||
2694 | 131 | configuration.header.add("Content-Type", content_type); | ||
2695 | 132 | configuration.header.add("Prefer", "respond-async"); | ||
2696 | 133 | |||
2697 | 134 | auto request = client_->post(configuration, postbody, content_type); | ||
2698 | 135 | request->async_execute(handler); | ||
2699 | 136 | } | ||
2700 | 137 | |||
2701 | 138 | void del(const net::Uri::Path &path, | ||
2702 | 139 | const net::Uri::QueryParameters ¶meters, | ||
2703 | 140 | http::Request::Handler &handler) { | ||
2704 | 141 | std::lock_guard<std::mutex> lock(config_mutex_); | ||
2705 | 142 | http::Request::Configuration configuration = net_config(path, parameters); | ||
2706 | 143 | configuration.header.add("User-Agent", config_.user_agent); | ||
2707 | 144 | |||
2708 | 145 | auto request = client_->del(configuration); | ||
2709 | 146 | request->async_execute(handler); | ||
2710 | 147 | } | ||
2711 | 148 | |||
2712 | 149 | void patch(const net::Uri::Path &path, | ||
2713 | 150 | const net::Uri::QueryParameters ¶meters, | ||
2714 | 151 | const std::string &postbody, | ||
2715 | 152 | const std::string &content_type, | ||
2716 | 153 | http::Request::Handler &handler) { | ||
2717 | 154 | std::lock_guard<std::mutex> lock(config_mutex_); | ||
2718 | 155 | http::Request::Configuration configuration = net_config(path, parameters); | ||
2719 | 156 | configuration.header.add("User-Agent", config_.user_agent); | ||
2720 | 157 | configuration.header.add("Content-Type", content_type); | ||
2721 | 158 | //WORKAROUND: net-cpp doesn't support PATCH method. | ||
2722 | 159 | configuration.header.add("X-HTTP-Method-Override", "PATCH"); | ||
2723 | 160 | |||
2724 | 161 | auto request = client_->post(configuration, postbody, content_type); | ||
2725 | 162 | request->async_execute(handler); | ||
2726 | 163 | } | ||
2727 | 164 | |||
2728 | 165 | http::Request::Configuration net_config(const net::Uri::Path &path, | ||
2729 | 166 | const net::Uri::QueryParameters ¶meters) { | ||
2730 | 167 | http::Request::Configuration configuration; | ||
2731 | 168 | net::Uri::QueryParameters complete_parameters(parameters); | ||
2732 | 169 | if (!config_.access_token.empty()) { | ||
2733 | 170 | configuration.header.add("Authorization", | ||
2734 | 171 | "bearer " + config_.access_token); | ||
2735 | 172 | } | ||
2736 | 173 | |||
2737 | 174 | if (getenv("ONEDRIVE_LOCAL_SERVER_URL")) { | ||
2738 | 175 | config_.apiroot = string(getenv("ONEDRIVE_LOCAL_SERVER_URL")); | ||
2739 | 176 | configuration.header.add("Authorization", | ||
2740 | 177 | "bearer " + config_.access_token); | ||
2741 | 178 | } | ||
2742 | 179 | |||
2743 | 180 | net::Uri uri = net::make_uri(config_.apiroot, path, | ||
2744 | 181 | complete_parameters); | ||
2745 | 182 | configuration.uri = client_->uri_to_string(uri); | ||
2746 | 183 | std::cout << "uri: "<<configuration.uri << std::endl; | ||
2747 | 184 | |||
2748 | 185 | return configuration; | ||
2749 | 186 | } | ||
2750 | 187 | |||
2751 | 188 | http::Request::Progress::Next progress_changed( | ||
2752 | 189 | const http::Request::Progress&) { | ||
2753 | 190 | return cancelled_ ? | ||
2754 | 191 | http::Request::Progress::Next::abort_operation : | ||
2755 | 192 | http::Request::Progress::Next::continue_operation; | ||
2756 | 193 | } | ||
2757 | 194 | |||
2758 | 195 | template<typename T> | ||
2759 | 196 | future<T> async_get(const net::Uri::Path &path, | ||
2760 | 197 | const net::Uri::QueryParameters ¶meters, | ||
2761 | 198 | const function<T(const json::Value &root)> &func) { | ||
2762 | 199 | auto prom = make_shared<promise<T>>(); | ||
2763 | 200 | |||
2764 | 201 | http::Request::Handler handler; | ||
2765 | 202 | handler.on_progress( | ||
2766 | 203 | bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1)); | ||
2767 | 204 | handler.on_error([prom](const net::Error& e) | ||
2768 | 205 | { | ||
2769 | 206 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
2770 | 207 | }); | ||
2771 | 208 | handler.on_response( | ||
2772 | 209 | [prom,func](const http::Response& response) | ||
2773 | 210 | { | ||
2774 | 211 | json::Reader reader; | ||
2775 | 212 | json::Value root; | ||
2776 | 213 | |||
2777 | 214 | std::cout <<"http status code: " << response.status <<"response.body: " << response.body | ||
2778 | 215 | << std::endl; | ||
2779 | 216 | |||
2780 | 217 | //for download link generation, link can be found at header[location] according to dev doc | ||
2781 | 218 | if (response.status == net::http::Status::accepted) { | ||
2782 | 219 | response.header.enumerate([&root](const std::string& key, | ||
2783 | 220 | const std::set<std::string>& /*values*/) { | ||
2784 | 221 | vector<string> headers; | ||
2785 | 222 | boost::split_regex(headers, key, boost::regex(": ")); | ||
2786 | 223 | boost::trim_right(headers[1]); | ||
2787 | 224 | root[headers[0]] = headers[1]; | ||
2788 | 225 | std::cout << "header: " << key <<" " << headers[1] << std::endl; | ||
2789 | 226 | }); | ||
2790 | 227 | prom->set_value(func(root)); | ||
2791 | 228 | } else if (!reader.parse(response.body, root)) { | ||
2792 | 229 | prom->set_exception(make_exception_ptr(UnknownException("json parse failed"))); | ||
2793 | 230 | } else { | ||
2794 | 231 | if (response.status != net::http::Status::ok) { | ||
2795 | 232 | set_exception<T>(prom, root); | ||
2796 | 233 | } else { | ||
2797 | 234 | prom->set_value(func(root)); | ||
2798 | 235 | } | ||
2799 | 236 | } | ||
2800 | 237 | } | ||
2801 | 238 | ); | ||
2802 | 239 | |||
2803 | 240 | get(path, parameters, handler); | ||
2804 | 241 | |||
2805 | 242 | return prom->get_future(); | ||
2806 | 243 | } | ||
2807 | 244 | |||
2808 | 245 | template<typename T> | ||
2809 | 246 | future<T> async_post(const net::Uri::Path &path, | ||
2810 | 247 | const net::Uri::QueryParameters ¶meters, | ||
2811 | 248 | const std::string &postmsg, | ||
2812 | 249 | const std::string &content_type, | ||
2813 | 250 | const function<T(const json::Value &root)> &func) { | ||
2814 | 251 | auto prom = make_shared<promise<T>>(); | ||
2815 | 252 | |||
2816 | 253 | http::Request::Handler handler; | ||
2817 | 254 | handler.on_progress( | ||
2818 | 255 | bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1)); | ||
2819 | 256 | handler.on_error([prom](const net::Error& e) | ||
2820 | 257 | { | ||
2821 | 258 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
2822 | 259 | }); | ||
2823 | 260 | handler.on_response( | ||
2824 | 261 | [path, prom,func](const http::Response& response) | ||
2825 | 262 | { | ||
2826 | 263 | json::Reader reader; | ||
2827 | 264 | json::Value root; | ||
2828 | 265 | |||
2829 | 266 | std::cout <<"http status code: " << response.status <<"response.body: " << response.body | ||
2830 | 267 | <<" isempty: " <<response.body.empty() << std::endl; | ||
2831 | 268 | |||
2832 | 269 | if (!reader.parse(response.body, root)) { | ||
2833 | 270 | prom->set_exception(make_exception_ptr(runtime_error("json parse failed"))); | ||
2834 | 271 | } else if (response.status != net::http::Status::ok && | ||
2835 | 272 | response.status != net::http::Status::created && | ||
2836 | 273 | response.status != net::http::Status::accepted && | ||
2837 | 274 | response.status != net::http::Status::see_other) { | ||
2838 | 275 | set_exception<T>(prom, root); | ||
2839 | 276 | } else { | ||
2840 | 277 | //To deal with AsyncJobStatus | ||
2841 | 278 | //https://dev.onedrive.com/items/copy.htm | ||
2842 | 279 | string cache_header; | ||
2843 | 280 | if (response.status == net::http::Status::accepted) { | ||
2844 | 281 | json::Value requestJson; | ||
2845 | 282 | json::StyledWriter writer; | ||
2846 | 283 | response.header.enumerate([&requestJson, &cache_header, | ||
2847 | 284 | &writer](const std::string& key, | ||
2848 | 285 | const std::set<std::string>& /*values*/) { | ||
2849 | 286 | vector<string> headers; | ||
2850 | 287 | boost::split_regex(headers, key, boost::regex(": ")); | ||
2851 | 288 | boost::trim_right(headers[1]); | ||
2852 | 289 | requestJson[headers[0]] = headers[1]; | ||
2853 | 290 | std::cout << "sdfsdfsd: " << key <<" " << headers[1] << std::endl; | ||
2854 | 291 | }); | ||
2855 | 292 | |||
2856 | 293 | cache_header = writer.write(requestJson); | ||
2857 | 294 | // return; | ||
2858 | 295 | } | ||
2859 | 296 | |||
2860 | 297 | if (!cache_header.empty() && !reader.parse(cache_header, root)) { | ||
2861 | 298 | prom->set_exception(make_exception_ptr(runtime_error("json parse failed"))); | ||
2862 | 299 | } else { | ||
2863 | 300 | prom->set_value(func(root)); | ||
2864 | 301 | } | ||
2865 | 302 | } | ||
2866 | 303 | } | ||
2867 | 304 | ); | ||
2868 | 305 | |||
2869 | 306 | post(path, parameters, postmsg, content_type, handler); | ||
2870 | 307 | |||
2871 | 308 | return prom->get_future(); | ||
2872 | 309 | } | ||
2873 | 310 | |||
2874 | 311 | template<typename T> | ||
2875 | 312 | future<T> async_patch(const net::Uri::Path &path, | ||
2876 | 313 | const net::Uri::QueryParameters ¶meters, | ||
2877 | 314 | const std::string &postmsg, | ||
2878 | 315 | const std::string &content_type, | ||
2879 | 316 | const function<T(const json::Value &root)> &func) { | ||
2880 | 317 | auto prom = make_shared<promise<T>>(); | ||
2881 | 318 | |||
2882 | 319 | http::Request::Handler handler; | ||
2883 | 320 | handler.on_progress( | ||
2884 | 321 | bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1)); | ||
2885 | 322 | handler.on_error([prom](const net::Error& e) | ||
2886 | 323 | { | ||
2887 | 324 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
2888 | 325 | }); | ||
2889 | 326 | handler.on_response( | ||
2890 | 327 | [path, prom,func](const http::Response& response) | ||
2891 | 328 | { | ||
2892 | 329 | json::Reader reader; | ||
2893 | 330 | json::Value root; | ||
2894 | 331 | |||
2895 | 332 | std::cout <<"http status code: " << response.status <<"response.body: " << response.body | ||
2896 | 333 | <<" isempty: " <<response.body.empty() << std::endl; | ||
2897 | 334 | |||
2898 | 335 | if (!reader.parse(response.body, root)) { | ||
2899 | 336 | prom->set_exception(make_exception_ptr(UnknownException("json parse failed"))); | ||
2900 | 337 | } else { | ||
2901 | 338 | if (response.status != net::http::Status::ok) { | ||
2902 | 339 | set_exception<T>(prom, root); | ||
2903 | 340 | } else { | ||
2904 | 341 | prom->set_value(func(root)); | ||
2905 | 342 | } | ||
2906 | 343 | } | ||
2907 | 344 | } | ||
2908 | 345 | ); | ||
2909 | 346 | |||
2910 | 347 | patch(path, parameters, postmsg, content_type, handler); | ||
2911 | 348 | |||
2912 | 349 | return prom->get_future(); | ||
2913 | 350 | } | ||
2914 | 351 | |||
2915 | 352 | template<typename T> | ||
2916 | 353 | future<T> async_del(const net::Uri::Path &path, | ||
2917 | 354 | const net::Uri::QueryParameters ¶meters, | ||
2918 | 355 | const function<T(const json::Value &root)> &func) { | ||
2919 | 356 | auto prom = make_shared<promise<T>>(); | ||
2920 | 357 | |||
2921 | 358 | http::Request::Handler handler; | ||
2922 | 359 | handler.on_progress( | ||
2923 | 360 | bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1)); | ||
2924 | 361 | handler.on_error([prom](const net::Error& e) | ||
2925 | 362 | { | ||
2926 | 363 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
2927 | 364 | }); | ||
2928 | 365 | handler.on_response( | ||
2929 | 366 | [prom,func](const http::Response& response) | ||
2930 | 367 | { | ||
2931 | 368 | std::cout <<"http status code: " << response.status <<"response.body: " << response.body | ||
2932 | 369 | << std::endl; | ||
2933 | 370 | |||
2934 | 371 | json::Reader reader; | ||
2935 | 372 | json::Value root; | ||
2936 | 373 | if (response.status == net::http::Status::no_content) { | ||
2937 | 374 | prom->set_value(func(root)); | ||
2938 | 375 | } else { | ||
2939 | 376 | if (!reader.parse(response.body, root)) { | ||
2940 | 377 | prom->set_exception(make_exception_ptr(UnknownException("json parse failed"))); | ||
2941 | 378 | } else{ | ||
2942 | 379 | set_exception<T>(prom, root); | ||
2943 | 380 | } | ||
2944 | 381 | } | ||
2945 | 382 | } | ||
2946 | 383 | ); | ||
2947 | 384 | |||
2948 | 385 | del(path, parameters, handler); | ||
2949 | 386 | |||
2950 | 387 | return prom->get_future(); | ||
2951 | 388 | } | ||
2952 | 389 | }; | ||
2953 | 390 | |||
2954 | 391 | ClientPriv::ClientPriv(int request_timeout) | ||
2955 | 392 | : httpclient_(std::make_shared<HttpClient>(request_timeout)) | ||
2956 | 393 | , sync_manager_(std::shared_ptr<SyncManager>(new SyncManager(this))) { | ||
2957 | 394 | } | ||
2958 | 395 | |||
2959 | 396 | ClientPriv::~ClientPriv() { | ||
2960 | 397 | httpclient_->cancelled_ = true; | ||
2961 | 398 | } | ||
2962 | 399 | |||
2963 | 400 | void ClientPriv::set_access_token(const string &access_token) { | ||
2964 | 401 | httpclient_->config_.access_token = access_token; | ||
2965 | 402 | sync_manager_->p_->set_access_token(access_token); | ||
2966 | 403 | } | ||
2967 | 404 | |||
2968 | 405 | StorageInfo ClientPriv::storage_info() { | ||
2969 | 406 | auto storage_future = httpclient_->async_get<StorageInfo>( | ||
2970 | 407 | { "drive" }, { }, | ||
2971 | 408 | [](const json::Value &root) { | ||
2972 | 409 | return StorageInfo(root); | ||
2973 | 410 | }); | ||
2974 | 411 | |||
2975 | 412 | return get_or_throw(storage_future); | ||
2976 | 413 | } | ||
2977 | 414 | |||
2978 | 415 | CloudResource::Ptr ClientPriv::metadata(const string &content_id) { | ||
2979 | 416 | auto disk_future = httpclient_->async_get<CloudResource::Ptr>( | ||
2980 | 417 | { "drive", "items", content_id }, { }, | ||
2981 | 418 | [](const json::Value &root) -> CloudResource::Ptr { | ||
2982 | 419 | if (root.isMember("folder")) | ||
2983 | 420 | return shared_ptr<CloudFolder>(new CloudFolder(root)); | ||
2984 | 421 | return shared_ptr<CloudItem>(new CloudItem(root)); | ||
2985 | 422 | }); | ||
2986 | 423 | |||
2987 | 424 | return get_or_throw(disk_future); | ||
2988 | 425 | } | ||
2989 | 426 | |||
2990 | 427 | CloudFolder::Ptr ClientPriv::root_folder() { | ||
2991 | 428 | auto folder_future = httpclient_->async_get<CloudFolder::Ptr>( | ||
2992 | 429 | { "drive", "items", "root" }, { }, | ||
2993 | 430 | [](const json::Value &root) -> CloudFolder::Ptr { | ||
2994 | 431 | return shared_ptr<CloudFolder>(new CloudFolder(root)); | ||
2995 | 432 | }); | ||
2996 | 433 | |||
2997 | 434 | return get_or_throw(folder_future); | ||
2998 | 435 | } | ||
2999 | 436 | |||
3000 | 437 | tuple<Client::ResourceList, string> ClientPriv::cloud_content_list(const std::string &folder_id, | ||
3001 | 438 | const std::string &page_token) { | ||
3002 | 439 | net::Uri::Path path { "drive", "items" }; | ||
3003 | 440 | if (folder_id.empty()) { | ||
3004 | 441 | path.emplace_back("root"); | ||
3005 | 442 | } else { | ||
3006 | 443 | path.emplace_back(folder_id); | ||
3007 | 444 | } | ||
3008 | 445 | |||
3009 | 446 | net::Uri::QueryParameters params { { "expand", "children" } }; | ||
3010 | 447 | if (!page_token.empty()) { | ||
3011 | 448 | params.emplace_back(make_pair("skiptoken", page_token)); | ||
3012 | 449 | } | ||
3013 | 450 | |||
3014 | 451 | auto resource_future = httpclient_->async_get<tuple<Client::ResourceList, string>>( | ||
3015 | 452 | path, params, | ||
3016 | 453 | [](const json::Value &root) -> tuple<Client::ResourceList, string> { | ||
3017 | 454 | Client::ResourceList results; | ||
3018 | 455 | |||
3019 | 456 | json::Value children; | ||
3020 | 457 | if (root.isMember("children")) | ||
3021 | 458 | children = root["children"]; | ||
3022 | 459 | else if (root.isMember("value")) | ||
3023 | 460 | children = root["value"]; | ||
3024 | 461 | |||
3025 | 462 | for (const auto & child: children) { | ||
3026 | 463 | if (child.isMember("folder")) { | ||
3027 | 464 | results.push_back(std::shared_ptr<CloudFolder>(new CloudFolder(child))); | ||
3028 | 465 | } else { | ||
3029 | 466 | results.push_back(std::shared_ptr<CloudItem>(new CloudItem(child))); | ||
3030 | 467 | } | ||
3031 | 468 | } | ||
3032 | 469 | |||
3033 | 470 | string next_page_token; | ||
3034 | 471 | if (root.isMember("children@odata.nextLink")) { | ||
3035 | 472 | const string nextToken = "skiptoken"; | ||
3036 | 473 | string nextLink = root["children@odata.nextLink"].asString(); | ||
3037 | 474 | size_t pos = nextLink.find(nextToken) + nextToken.length(); | ||
3038 | 475 | next_page_token = nextLink.substr(pos); | ||
3039 | 476 | } | ||
3040 | 477 | |||
3041 | 478 | return make_tuple(results, next_page_token); | ||
3042 | 479 | }); | ||
3043 | 480 | |||
3044 | 481 | return get_or_throw(resource_future); | ||
3045 | 482 | } | ||
3046 | 483 | |||
3047 | 484 | Client::ResourceList ClientPriv::search(const string &name, | ||
3048 | 485 | const string &folder_id) { | ||
3049 | 486 | net::Uri::Path path { "drive", "items" }; | ||
3050 | 487 | if (folder_id.empty()) { | ||
3051 | 488 | path.emplace_back("root"); | ||
3052 | 489 | } else { | ||
3053 | 490 | path.emplace_back(folder_id); | ||
3054 | 491 | } | ||
3055 | 492 | path.emplace_back("view.search"); | ||
3056 | 493 | |||
3057 | 494 | auto resource_future = httpclient_->async_get<Client::ResourceList>( | ||
3058 | 495 | path, {{"q", name}}, | ||
3059 | 496 | [](const json::Value &root) -> Client::ResourceList { | ||
3060 | 497 | Client::ResourceList results; | ||
3061 | 498 | |||
3062 | 499 | json::Value children; | ||
3063 | 500 | if (root.isMember("children")) | ||
3064 | 501 | children = root["children"]; | ||
3065 | 502 | else if (root.isMember("value")) | ||
3066 | 503 | children = root["value"]; | ||
3067 | 504 | for (const auto & child: children) { | ||
3068 | 505 | if (child.isMember("folder")) { | ||
3069 | 506 | results.push_back(std::shared_ptr<CloudFolder>(new CloudFolder(child))); | ||
3070 | 507 | } else { | ||
3071 | 508 | results.push_back(std::shared_ptr<CloudItem>(new CloudItem(child))); | ||
3072 | 509 | } | ||
3073 | 510 | } | ||
3074 | 511 | |||
3075 | 512 | return results; | ||
3076 | 513 | }); | ||
3077 | 514 | |||
3078 | 515 | return get_or_throw(resource_future); | ||
3079 | 516 | } | ||
3080 | 517 | |||
3081 | 518 | CloudFolder::Ptr ClientPriv::create_folder(const string &folder_name, | ||
3082 | 519 | const string &folder_id) { | ||
3083 | 520 | net::Uri::Path path { "drive", "items" }; | ||
3084 | 521 | if (folder_id.empty()) { | ||
3085 | 522 | path.emplace_back("root"); | ||
3086 | 523 | } else { | ||
3087 | 524 | path.emplace_back(folder_id); | ||
3088 | 525 | } | ||
3089 | 526 | path.emplace_back("children"); | ||
3090 | 527 | |||
3091 | 528 | json::Value requestJson; | ||
3092 | 529 | requestJson["name"] = folder_name; | ||
3093 | 530 | requestJson["folder"] = json::Value(json::objectValue); | ||
3094 | 531 | |||
3095 | 532 | json::StyledWriter writer; | ||
3096 | 533 | std::string postbody = writer.write( requestJson ); | ||
3097 | 534 | std::string content_type = "application/json"; | ||
3098 | 535 | std::cout << "postbody: " << postbody << std::endl; | ||
3099 | 536 | |||
3100 | 537 | auto created = httpclient_->async_post<CloudFolder::Ptr>(path, | ||
3101 | 538 | { }, postbody, content_type, | ||
3102 | 539 | [](const json::Value &root) -> CloudFolder::Ptr { | ||
3103 | 540 | return shared_ptr<CloudFolder>(new CloudFolder(root)); | ||
3104 | 541 | }); | ||
3105 | 542 | |||
3106 | 543 | return get_or_throw(created); | ||
3107 | 544 | } | ||
3108 | 545 | |||
3109 | 546 | bool ClientPriv::delete_item(const string item_id) { | ||
3110 | 547 | auto del = httpclient_->async_del<bool>( | ||
3111 | 548 | { "drive", "items", item_id }, { }, | ||
3112 | 549 | [](const json::Value &root) -> bool { | ||
3113 | 550 | return root.isNull() ? true : false; | ||
3114 | 551 | }); | ||
3115 | 552 | |||
3116 | 553 | return get_or_throw(del); | ||
3117 | 554 | } | ||
3118 | 555 | |||
3119 | 556 | /* | ||
3120 | 557 | CloudResource::Ptr ClientPriv::copy_item(const std::string &item_id, | ||
3121 | 558 | const std::string &item_name, | ||
3122 | 559 | const std::string &folder_id) { | ||
3123 | 560 | json::Value requestJson; | ||
3124 | 561 | requestJson["parentReference"]["id"] = folder_id; | ||
3125 | 562 | requestJson["name"] = item_name; | ||
3126 | 563 | |||
3127 | 564 | json::StyledWriter writer; | ||
3128 | 565 | std::string postbody = writer.write( requestJson ); | ||
3129 | 566 | std::string content_type = "application/json"; | ||
3130 | 567 | std::cout << "postbody: " << postbody << std::endl; | ||
3131 | 568 | |||
3132 | 569 | auto copy = httpclient_->async_post<unordered_map<string, string>>( | ||
3133 | 570 | { "drive", "items", item_id, "action.copy"}, { }, postbody, content_type, | ||
3134 | 571 | [](const json::Value &root) -> unordered_map<string, string> { | ||
3135 | 572 | unordered_map<string, string> map{ | ||
3136 | 573 | {"Content-Length", root["Content-Length"].asString()}, | ||
3137 | 574 | {"Location", root["Location"].asString()}, | ||
3138 | 575 | {"Preference-Applied", root["Preference-Applied"].asString()}, | ||
3139 | 576 | {"Server", root["Preference-Applied"].asString()}, | ||
3140 | 577 | {"X-Msnserver", root["X-Msnserver"].asString()}, | ||
3141 | 578 | {"X-Wlsproxy", root["X-Wlsproxy"].asString()} | ||
3142 | 579 | }; | ||
3143 | 580 | return map; | ||
3144 | 581 | }); | ||
3145 | 582 | |||
3146 | 583 | auto cache_header = get_or_throw(copy); | ||
3147 | 584 | for (const auto & c: cache_header) { | ||
3148 | 585 | std::cout << c.first << " "<< c.second << std::endl; | ||
3149 | 586 | } | ||
3150 | 587 | |||
3151 | 588 | auto ePos = cache_header["Location"].find_last_of('/'); | ||
3152 | 589 | auto sub_path = cache_header["Location"].substr(ePos + 1); | ||
3153 | 590 | |||
3154 | 591 | std::cout << "cache_header.size():" << cache_header.size() << " "<< cache_header["Location"] << " " | ||
3155 | 592 | << sub_path << std::endl; | ||
3156 | 593 | if (!cache_header.empty()) { | ||
3157 | 594 | auto check_future = httpclient_->async_get<CloudResource::Ptr>( | ||
3158 | 595 | { "monitor", sub_path}, { }, cache_header, | ||
3159 | 596 | [](const json::Value &root) -> CloudResource::Ptr { | ||
3160 | 597 | return root.isNull()? nullptr : nullptr; | ||
3161 | 598 | }); | ||
3162 | 599 | |||
3163 | 600 | CloudResource::Ptr ptr = get_or_throw(check_future); | ||
3164 | 601 | Client::ResourceList resourceList = search(item_name, folder_id); | ||
3165 | 602 | if (resourceList.size() > 0) | ||
3166 | 603 | return resourceList[0]; | ||
3167 | 604 | } | ||
3168 | 605 | |||
3169 | 606 | throw runtime_error("item copy failed"); | ||
3170 | 607 | } | ||
3171 | 608 | */ | ||
3172 | 609 | |||
3173 | 610 | |||
3174 | 611 | CloudResource::Ptr ClientPriv::move_item(const std::string &item_id, | ||
3175 | 612 | const std::string &folder_id, | ||
3176 | 613 | const std::string &item_name) { | ||
3177 | 614 | json::Value requestJson; | ||
3178 | 615 | requestJson["parentReference"]["id"] = folder_id; | ||
3179 | 616 | if (!item_name.empty()) | ||
3180 | 617 | requestJson["name"] = item_name; | ||
3181 | 618 | |||
3182 | 619 | json::StyledWriter writer; | ||
3183 | 620 | std::string postbody = writer.write(requestJson); | ||
3184 | 621 | std::string content_type = "application/json"; | ||
3185 | 622 | |||
3186 | 623 | auto move_future = httpclient_->async_patch<CloudResource::Ptr>( | ||
3187 | 624 | { "drive", "items", item_id }, { },postbody, content_type, | ||
3188 | 625 | [](const json::Value &root) -> CloudResource::Ptr { | ||
3189 | 626 | if (root.isMember("folder")) | ||
3190 | 627 | return shared_ptr<CloudFolder>(new CloudFolder(root)); | ||
3191 | 628 | return shared_ptr<CloudItem>(new CloudItem(root)); | ||
3192 | 629 | }); | ||
3193 | 630 | |||
3194 | 631 | return get_or_throw(move_future); | ||
3195 | 632 | } | ||
3196 | 633 | |||
3197 | 634 | CloudResource::Ptr ClientPriv::rename_item(const string &item_id, const string &new_name) { | ||
3198 | 635 | json::Value requestJson; | ||
3199 | 636 | requestJson["name"] = new_name; | ||
3200 | 637 | |||
3201 | 638 | json::StyledWriter writer; | ||
3202 | 639 | std::string postbody = writer.write(requestJson); | ||
3203 | 640 | std::string content_type = "application/json"; | ||
3204 | 641 | |||
3205 | 642 | auto move_future = httpclient_->async_patch<CloudResource::Ptr>( | ||
3206 | 643 | { "drive", "items", item_id }, { }, postbody, content_type, | ||
3207 | 644 | [](const json::Value &root) -> CloudResource::Ptr { | ||
3208 | 645 | if (root.isMember("folder")) | ||
3209 | 646 | return shared_ptr<CloudFolder>(new CloudFolder(root)); | ||
3210 | 647 | return shared_ptr<CloudItem>(new CloudItem(root)); | ||
3211 | 648 | }); | ||
3212 | 649 | |||
3213 | 650 | return get_or_throw(move_future); | ||
3214 | 651 | } | ||
3215 | 652 | |||
3216 | 653 | string ClientPriv::request_download_link(const string &item_id) { | ||
3217 | 654 | auto link_future = httpclient_->async_get<string>( | ||
3218 | 655 | { "drive", "items", item_id, "content" }, { }, | ||
3219 | 656 | [](const json::Value &root) -> string { | ||
3220 | 657 | return root["location"].asString(); | ||
3221 | 658 | }); | ||
3222 | 659 | |||
3223 | 660 | return get_or_throw(link_future); | ||
3224 | 661 | } | ||
3225 | 662 | |||
3226 | 663 | //DownloadTaskPriv::Ptr ClientPriv::request_download_link(const DownloadBuffer &buffer_item) { | ||
3227 | 664 | |||
3228 | 665 | //} | ||
3229 | 666 | |||
3230 | 667 | /* | ||
3231 | 668 | SyncManager::UploadList ClientPriv::create_upload_link(const UploadRequest &request_item) { | ||
3232 | 669 | if (!fs::exists(request_item.file_path)) | ||
3233 | 670 | throw std::runtime_error(string("file not exists: ").append(request_item.file_path)); | ||
3234 | 671 | |||
3235 | 672 | string postbody = generate_upload_body(request_item); | ||
3236 | 673 | |||
3237 | 674 | log(postbody); | ||
3238 | 675 | |||
3239 | 676 | auto future = httpclient_->async_post<SyncManager::UploadList>( | ||
3240 | 677 | { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type, | ||
3241 | 678 | [request_item](const tinyxml2::XMLElement *root) { | ||
3242 | 679 | SyncManager::UploadList results; | ||
3243 | 680 | |||
3244 | 681 | auto upload_res = root->FirstChildElement("uploadResult"); | ||
3245 | 682 | std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText(); | ||
3246 | 683 | |||
3247 | 684 | std::string redirection_url; | ||
3248 | 685 | if (upload_res->FirstChildElement("redirectionUrl")) { | ||
3249 | 686 | redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText(); | ||
3250 | 687 | } | ||
3251 | 688 | |||
3252 | 689 | auto content_list = upload_res->FirstChildElement("newContentIDList"); | ||
3253 | 690 | if (content_list) { | ||
3254 | 691 | auto content = content_list->FirstChildElement(); | ||
3255 | 692 | while(content) { | ||
3256 | 693 | results.push(std::shared_ptr<UploadTask>(new UploadTask(content, | ||
3257 | 694 | task_id, | ||
3258 | 695 | redirection_url, | ||
3259 | 696 | request_item.file_path))); | ||
3260 | 697 | content = content->NextSiblingElement(); | ||
3261 | 698 | } | ||
3262 | 699 | } | ||
3263 | 700 | |||
3264 | 701 | return results; | ||
3265 | 702 | }); | ||
3266 | 703 | |||
3267 | 704 | return get_or_throw(future); | ||
3268 | 705 | } | ||
3269 | 706 | |||
3270 | 707 | SyncManager::UploadList ClientPriv::create_upload_link(const UploadBuffer &buffer_item) { | ||
3271 | 708 | string postbody = generate_upload_body(buffer_item); | ||
3272 | 709 | |||
3273 | 710 | log(postbody); | ||
3274 | 711 | |||
3275 | 712 | auto future = httpclient_->async_post<SyncManager::UploadList>( | ||
3276 | 713 | { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type, | ||
3277 | 714 | [buffer_item](const tinyxml2::XMLElement *root) { | ||
3278 | 715 | SyncManager::UploadList results; | ||
3279 | 716 | |||
3280 | 717 | auto upload_res = root->FirstChildElement("uploadResult"); | ||
3281 | 718 | std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText(); | ||
3282 | 719 | |||
3283 | 720 | std::string redirection_url; | ||
3284 | 721 | if (upload_res->FirstChildElement("redirectionUrl")) { | ||
3285 | 722 | redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText(); | ||
3286 | 723 | } | ||
3287 | 724 | |||
3288 | 725 | auto content_list = upload_res->FirstChildElement("newContentIDList"); | ||
3289 | 726 | if (content_list) { | ||
3290 | 727 | auto content = content_list->FirstChildElement(); | ||
3291 | 728 | while(content) { | ||
3292 | 729 | results.push(std::shared_ptr<UploadTask>(new UploadTask(content, | ||
3293 | 730 | task_id, | ||
3294 | 731 | redirection_url, | ||
3295 | 732 | buffer_item.buffer_size, | ||
3296 | 733 | buffer_item.read_cb))); | ||
3297 | 734 | content = content->NextSiblingElement(); | ||
3298 | 735 | } | ||
3299 | 736 | } | ||
3300 | 737 | |||
3301 | 738 | return results; | ||
3302 | 739 | }); | ||
3303 | 740 | |||
3304 | 741 | return get_or_throw(future); | ||
3305 | 742 | } | ||
3306 | 743 | |||
3307 | 744 | bool ClientPriv::refersh_token(const string &refresh_token) { | ||
3308 | 745 | const std::string content_type = "application/x-www-form-urlencoded"; | ||
3309 | 746 | const std::string postbody = "grant_type=refresh_token&refresh_token=" | ||
3310 | 747 | + refresh_token; | ||
3311 | 748 | log(postbody); | ||
3312 | 749 | |||
3313 | 750 | auto future = httpclient_->async_post<bool>( | ||
3314 | 751 | { "oauthApp", "OAuth2", "refreshToken" }, { }, postbody, content_type, | ||
3315 | 752 | [this](const tinyxml2::XMLElement *root) { | ||
3316 | 753 | boost::cmatch cap; | ||
3317 | 754 | const boost::regex exp(".*\"(.*?)\"\\}"); | ||
3318 | 755 | if (boost::regex_match(root->GetText(), cap, exp)) { | ||
3319 | 756 | httpclient_->config_.access_token = cap[1]; | ||
3320 | 757 | return true; | ||
3321 | 758 | } | ||
3322 | 759 | return false; | ||
3323 | 760 | }); | ||
3324 | 761 | |||
3325 | 762 | return get_or_throw(future); | ||
3326 | 763 | } | ||
3327 | 764 | */ | ||
3328 | 765 | |||
3329 | 766 | void ClientPriv::cancel() { | ||
3330 | 767 | httpclient_->cancelled_ = true; | ||
3331 | 768 | } | ||
3332 | 769 | |||
3333 | 770 | SyncManager::Ptr ClientPriv::sync_manager() { | ||
3334 | 771 | return sync_manager_; | ||
3335 | 772 | } | ||
3336 | 773 | |||
3337 | 774 | template<typename T> T ClientPriv::get_or_throw(std::future<T> &f) { | ||
3338 | 775 | if (f.wait_for(std::chrono::seconds(httpclient_->config_.request_timeout)) != std::future_status::ready) { | ||
3339 | 776 | throw HttpTimeoutException("HTTP request timeout"); | ||
3340 | 777 | } | ||
3341 | 778 | |||
3342 | 779 | return f.get(); | ||
3343 | 780 | } | ||
3344 | 0 | 781 | ||
3345 | === added file 'src/onedrive/api/client_priv.h' | |||
3346 | --- src/onedrive/api/client_priv.h 1970-01-01 00:00:00 +0000 | |||
3347 | +++ src/onedrive/api/client_priv.h 2016-09-30 08:26:58 +0000 | |||
3348 | @@ -0,0 +1,106 @@ | |||
3349 | 1 | /* | ||
3350 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
3351 | 3 | * | ||
3352 | 4 | * This library is free software; you can redistribute it and/or modify it under | ||
3353 | 5 | * the terms of version 3 of the GNU Lesser General Public License as published | ||
3354 | 6 | * by the Free Software Foundation. | ||
3355 | 7 | * | ||
3356 | 8 | * This library is distributed in the hope that it will be useful, but WITHOUT | ||
3357 | 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
3358 | 10 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
3359 | 11 | * details. | ||
3360 | 12 | * | ||
3361 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3362 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3363 | 15 | * | ||
3364 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
3365 | 17 | */ | ||
3366 | 18 | |||
3367 | 19 | #ifndef ONEDRIVE_API_CLIENTPRIV_H_ | ||
3368 | 20 | #define ONEDRIVE_API_CLIENTPRIV_H_ | ||
3369 | 21 | |||
3370 | 22 | #include <onedrive/api/client.h> | ||
3371 | 23 | #include <onedrive/api/visibility.h> | ||
3372 | 24 | #include <onedrive/api/cloudresource.h> | ||
3373 | 25 | |||
3374 | 26 | #include <future> | ||
3375 | 27 | #include <string> | ||
3376 | 28 | #include <memory> | ||
3377 | 29 | |||
3378 | 30 | #include "downloadtask_priv.h" | ||
3379 | 31 | #include "uploadtask_priv.h" | ||
3380 | 32 | |||
3381 | 33 | namespace onedrive { | ||
3382 | 34 | namespace api { | ||
3383 | 35 | |||
3384 | 36 | class Client; | ||
3385 | 37 | |||
3386 | 38 | class ONEDRIVE_API_DLL_LOCAL ClientPriv { | ||
3387 | 39 | public: | ||
3388 | 40 | |||
3389 | 41 | enum class ServerCode { | ||
3390 | 42 | }; | ||
3391 | 43 | |||
3392 | 44 | typedef std::shared_ptr<ClientPriv> Ptr; | ||
3393 | 45 | |||
3394 | 46 | ClientPriv(int request_timeout = 10); | ||
3395 | 47 | |||
3396 | 48 | virtual ~ClientPriv(); | ||
3397 | 49 | |||
3398 | 50 | StorageInfo storage_info(); | ||
3399 | 51 | |||
3400 | 52 | void set_access_token(const std::string &access_token); | ||
3401 | 53 | |||
3402 | 54 | // bool refersh_token(const std::string &refresh_token); | ||
3403 | 55 | |||
3404 | 56 | CloudResource::Ptr metadata(const std::string &content_id); | ||
3405 | 57 | |||
3406 | 58 | CloudFolder::Ptr root_folder(); | ||
3407 | 59 | |||
3408 | 60 | std::tuple<Client::ResourceList, std::string> cloud_content_list(const std::string &folder_id = std::string(), | ||
3409 | 61 | const std::string &page_token = std::string()); | ||
3410 | 62 | |||
3411 | 63 | Client::ResourceList search(const std::string &name, | ||
3412 | 64 | const std::string &folder_id); | ||
3413 | 65 | |||
3414 | 66 | CloudFolder::Ptr create_folder(const std::string &folder_name, | ||
3415 | 67 | const std::string &folder_id); | ||
3416 | 68 | |||
3417 | 69 | /* | ||
3418 | 70 | CloudResource::Ptr copy_item(const std::string &item_id, | ||
3419 | 71 | const std::string &item_name, | ||
3420 | 72 | const std::string &folder_id); | ||
3421 | 73 | */ | ||
3422 | 74 | |||
3423 | 75 | CloudResource::Ptr move_item(const std::string &item_id, | ||
3424 | 76 | const std::string &folder_id, | ||
3425 | 77 | const std::string &item_name); | ||
3426 | 78 | |||
3427 | 79 | CloudResource::Ptr rename_item(const std::string &item_id, | ||
3428 | 80 | const std::string &new_name); | ||
3429 | 81 | |||
3430 | 82 | |||
3431 | 83 | bool delete_item(const std::string item_id); | ||
3432 | 84 | |||
3433 | 85 | std::string request_download_link(const std::string &item_id); | ||
3434 | 86 | |||
3435 | 87 | // DownloadTaskPriv::Ptr request_download_link(const DownloadBuffer &buffer_item); | ||
3436 | 88 | |||
3437 | 89 | void cancel(); | ||
3438 | 90 | |||
3439 | 91 | std::shared_ptr<SyncManager> sync_manager(); | ||
3440 | 92 | |||
3441 | 93 | private: | ||
3442 | 94 | template<typename T> T get_or_throw(std::future<T> &f); | ||
3443 | 95 | |||
3444 | 96 | private: | ||
3445 | 97 | class HttpClient; | ||
3446 | 98 | std::shared_ptr<HttpClient> httpclient_; | ||
3447 | 99 | |||
3448 | 100 | std::shared_ptr<SyncManager> sync_manager_; | ||
3449 | 101 | }; | ||
3450 | 102 | |||
3451 | 103 | } | ||
3452 | 104 | } | ||
3453 | 105 | |||
3454 | 106 | #endif // ONEDRIVE_API_CLIENTPRIV_H_ | ||
3455 | 0 | 107 | ||
3456 | === added file 'src/onedrive/api/cloudfolder.cpp' | |||
3457 | --- src/onedrive/api/cloudfolder.cpp 1970-01-01 00:00:00 +0000 | |||
3458 | +++ src/onedrive/api/cloudfolder.cpp 2016-09-30 08:26:58 +0000 | |||
3459 | @@ -0,0 +1,121 @@ | |||
3460 | 1 | /* | ||
3461 | 2 | * Copyright © 2016 Canonical Ltd. | ||
3462 | 3 | * | ||
3463 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3464 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
3465 | 6 | * as published by the Free Software Foundation. | ||
3466 | 7 | * | ||
3467 | 8 | * This program is distributed in the hope that it will be useful, | ||
3468 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3469 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3470 | 11 | * GNU Lesser General Public License for more details. | ||
3471 | 12 | * | ||
3472 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3473 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3474 | 15 | * | ||
3475 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
3476 | 17 | */ | ||
3477 | 18 | |||
3478 | 19 | #include <onedrive/api/cloudfolder.h> | ||
3479 | 20 | |||
3480 | 21 | #include <json/json.h> | ||
3481 | 22 | |||
3482 | 23 | #include <time.h> | ||
3483 | 24 | #include <iostream> | ||
3484 | 25 | #include <sstream> | ||
3485 | 26 | |||
3486 | 27 | namespace json = Json; | ||
3487 | 28 | |||
3488 | 29 | using namespace onedrive::api; | ||
3489 | 30 | using namespace std; | ||
3490 | 31 | |||
3491 | 32 | std::time_t string_to_time(const std::string dt) { | ||
3492 | 33 | struct std::tm tm; | ||
3493 | 34 | std::istringstream ss(dt); | ||
3494 | 35 | strptime(dt.c_str(), "%Y%m%d%H%M%S",&tm); // std::get std::put only available in GCC 5 | ||
3495 | 36 | return std::mktime(&tm); | ||
3496 | 37 | } | ||
3497 | 38 | |||
3498 | 39 | class CloudFolder::Priv { | ||
3499 | 40 | public: | ||
3500 | 41 | Priv(const json::Value &root) { | ||
3501 | 42 | id_ = root["id"].asString(); | ||
3502 | 43 | updated_date_ = string_to_time(root["lastModifiedDateTime"].asString()); | ||
3503 | 44 | created_date_ = string_to_time(root["createdDateTime"].asString()); | ||
3504 | 45 | etag_ = root["eTag"].asString(); | ||
3505 | 46 | name_ = root["name"].asString(); | ||
3506 | 47 | owner_ = root["createdBy"]["user"]["displayName"].asString(); | ||
3507 | 48 | folder_id_ = root.isMember("parentReference")? | ||
3508 | 49 | root["parentReference"]["id"].asString() : ""; | ||
3509 | 50 | children_count_ = root["folder"]["childCount"].asInt(); | ||
3510 | 51 | |||
3511 | 52 | #ifndef NDEBUG | ||
3512 | 53 | cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl; | ||
3513 | 54 | #endif | ||
3514 | 55 | |||
3515 | 56 | } | ||
3516 | 57 | |||
3517 | 58 | std::string id_; | ||
3518 | 59 | |||
3519 | 60 | std::string name_; | ||
3520 | 61 | |||
3521 | 62 | std::time_t created_date_; | ||
3522 | 63 | |||
3523 | 64 | std::time_t updated_date_; | ||
3524 | 65 | |||
3525 | 66 | std::string download_url_; | ||
3526 | 67 | |||
3527 | 68 | std::string folder_id_; | ||
3528 | 69 | |||
3529 | 70 | std::string etag_; | ||
3530 | 71 | |||
3531 | 72 | std::string owner_; | ||
3532 | 73 | |||
3533 | 74 | std::string folder_path_; | ||
3534 | 75 | |||
3535 | 76 | int children_count_; | ||
3536 | 77 | }; | ||
3537 | 78 | |||
3538 | 79 | CloudFolder::CloudFolder(const json::Value &root) | ||
3539 | 80 | :p(std::make_shared<Priv>(root)){ | ||
3540 | 81 | } | ||
3541 | 82 | |||
3542 | 83 | const string &CloudFolder::id() const { | ||
3543 | 84 | return p->id_; | ||
3544 | 85 | } | ||
3545 | 86 | |||
3546 | 87 | const string &CloudFolder::name() const { | ||
3547 | 88 | return p->name_; | ||
3548 | 89 | } | ||
3549 | 90 | |||
3550 | 91 | const time_t &CloudFolder::created_date() const { | ||
3551 | 92 | return p->created_date_; | ||
3552 | 93 | } | ||
3553 | 94 | |||
3554 | 95 | const time_t &CloudFolder::updated_date() const { | ||
3555 | 96 | return p->updated_date_; | ||
3556 | 97 | } | ||
3557 | 98 | |||
3558 | 99 | const string &CloudFolder::download_url() const { | ||
3559 | 100 | return p->download_url_; | ||
3560 | 101 | } | ||
3561 | 102 | |||
3562 | 103 | const string &CloudFolder::folder_id() const { | ||
3563 | 104 | return p->folder_id_; | ||
3564 | 105 | } | ||
3565 | 106 | |||
3566 | 107 | const string &CloudFolder::folder_path() const { | ||
3567 | 108 | return p->folder_path_; | ||
3568 | 109 | } | ||
3569 | 110 | |||
3570 | 111 | const string &CloudFolder::etag() const { | ||
3571 | 112 | return p->etag_; | ||
3572 | 113 | } | ||
3573 | 114 | |||
3574 | 115 | const string &CloudFolder::owner() const { | ||
3575 | 116 | return p->owner_; | ||
3576 | 117 | } | ||
3577 | 118 | |||
3578 | 119 | CloudResource::Property CloudFolder::property() const { | ||
3579 | 120 | return CloudResource::Property::Folder; | ||
3580 | 121 | } | ||
3581 | 0 | 122 | ||
3582 | === added file 'src/onedrive/api/clouditem.cpp' | |||
3583 | --- src/onedrive/api/clouditem.cpp 1970-01-01 00:00:00 +0000 | |||
3584 | +++ src/onedrive/api/clouditem.cpp 2016-09-30 08:26:58 +0000 | |||
3585 | @@ -0,0 +1,166 @@ | |||
3586 | 1 | /* | ||
3587 | 2 | * Copyright © 2016 Canonical Ltd. | ||
3588 | 3 | * | ||
3589 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3590 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
3591 | 6 | * as published by the Free Software Foundation. | ||
3592 | 7 | * | ||
3593 | 8 | * This program is distributed in the hope that it will be useful, | ||
3594 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3595 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3596 | 11 | * GNU Lesser General Public License for more details. | ||
3597 | 12 | * | ||
3598 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3599 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3600 | 15 | * | ||
3601 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
3602 | 17 | */ | ||
3603 | 18 | |||
3604 | 19 | #include <onedrive/api/clouditem.h> | ||
3605 | 20 | #include <json/json.h> | ||
3606 | 21 | |||
3607 | 22 | #include <iostream> | ||
3608 | 23 | |||
3609 | 24 | namespace json = Json; | ||
3610 | 25 | |||
3611 | 26 | using namespace onedrive::api; | ||
3612 | 27 | using namespace std; | ||
3613 | 28 | |||
3614 | 29 | extern std::time_t string_to_time(const std::string dt); | ||
3615 | 30 | |||
3616 | 31 | class CloudItem::Priv { | ||
3617 | 32 | public: | ||
3618 | 33 | Priv(const json::Value &root) { | ||
3619 | 34 | id_ = root["id"].asString(); | ||
3620 | 35 | updated_date_ = string_to_time(root["lastModifiedDateTime"].asString()); | ||
3621 | 36 | created_date_ = string_to_time(root["createdDateTime"].asString()); | ||
3622 | 37 | etag_ = root["eTag"].asString(); | ||
3623 | 38 | name_ = root["name"].asString(); | ||
3624 | 39 | owner_ = root["createdBy"]["user"]["displayName"].asString(); | ||
3625 | 40 | folder_id_ = root["parentReference"]["id"].asString(); | ||
3626 | 41 | mimetype_ = root["file"].isMember("mimeType") ? root["file"]["mimeType"].asString() : ""; | ||
3627 | 42 | content_size_ = root["size"].asInt64(); | ||
3628 | 43 | download_url_ = root["@content.downloadUrl"].asString(); | ||
3629 | 44 | folder_path_ = root["parentReference"]["path"].asString(); | ||
3630 | 45 | |||
3631 | 46 | if (!mimetype_.empty()) { | ||
3632 | 47 | if (mimetype_.find("video/") != string::npos) { | ||
3633 | 48 | if (root.isMember("photo") && root["photo"].isMember("takenDateTime")) { | ||
3634 | 49 | metadata_["takenDateTime"] = root["photo"]["takenDateTime"].asString(); | ||
3635 | 50 | } | ||
3636 | 51 | metadata_["width"] = root["video"]["width"].asInt(); | ||
3637 | 52 | metadata_["height"] = root["video"]["height"].asInt(); | ||
3638 | 53 | metadata_["bitrate"] = root["video"]["bitrate"].asInt(); | ||
3639 | 54 | metadata_["duration"] = root["video"]["duration"].asInt(); | ||
3640 | 55 | } else if (mimetype_.find("audio/") != string::npos) { | ||
3641 | 56 | metadata_["duration"] = root["duration"]["duration"].asUInt(); | ||
3642 | 57 | } else if (mimetype_.find("image/") != string::npos) { | ||
3643 | 58 | metadata_["width"] = root["image"]["width"].asInt(); | ||
3644 | 59 | metadata_["height"] = root["image"]["height"].asInt(); | ||
3645 | 60 | |||
3646 | 61 | if (root.isMember("photo")) { | ||
3647 | 62 | if (root["photo"].isMember("cameraMake")) | ||
3648 | 63 | metadata_["cameraMake"] = root["photo"]["cameraMake"].asString(); | ||
3649 | 64 | if (root["photo"].isMember("cameraModel")) | ||
3650 | 65 | metadata_["cameraModel"] = root["photo"]["cameraModel"].asString(); | ||
3651 | 66 | if (root["photo"].isMember("exposureDenominator")) | ||
3652 | 67 | metadata_["exposureDenominator"] = root["photo"]["exposureDenominator"].asInt(); | ||
3653 | 68 | if (root["photo"].isMember("exposureNumerator")) | ||
3654 | 69 | metadata_["exposureNumerator"] = root["photo"]["exposureNumerator"].asInt(); | ||
3655 | 70 | if (root["photo"].isMember("fNumber")) | ||
3656 | 71 | metadata_["fNumber"] = root["photo"]["fNumber"].asFloat(); | ||
3657 | 72 | if (root["photo"].isMember("iso")) | ||
3658 | 73 | metadata_["iso"] = root["photo"]["iso"].asInt(); | ||
3659 | 74 | } | ||
3660 | 75 | } | ||
3661 | 76 | } | ||
3662 | 77 | #ifndef NDEBUG | ||
3663 | 78 | cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl; | ||
3664 | 79 | #endif | ||
3665 | 80 | } | ||
3666 | 81 | |||
3667 | 82 | std::string id_; | ||
3668 | 83 | |||
3669 | 84 | std::string name_; | ||
3670 | 85 | |||
3671 | 86 | std::time_t created_date_; | ||
3672 | 87 | |||
3673 | 88 | std::time_t updated_date_; | ||
3674 | 89 | |||
3675 | 90 | std::string etag_; | ||
3676 | 91 | |||
3677 | 92 | std::string owner_; | ||
3678 | 93 | |||
3679 | 94 | std::string folder_path_; | ||
3680 | 95 | |||
3681 | 96 | std::string suffix_; | ||
3682 | 97 | |||
3683 | 98 | int64_t content_size_; | ||
3684 | 99 | |||
3685 | 100 | std::string download_url_; | ||
3686 | 101 | |||
3687 | 102 | std::string mimetype_; | ||
3688 | 103 | |||
3689 | 104 | std::string folder_id_; | ||
3690 | 105 | |||
3691 | 106 | std::unordered_map<std::string, std::string> metadata_; | ||
3692 | 107 | }; | ||
3693 | 108 | |||
3694 | 109 | CloudItem::CloudItem(const json::Value &root) | ||
3695 | 110 | : p(std::make_shared<Priv>(root)){ | ||
3696 | 111 | } | ||
3697 | 112 | |||
3698 | 113 | const string &CloudItem::id() const { | ||
3699 | 114 | return p->id_; | ||
3700 | 115 | } | ||
3701 | 116 | |||
3702 | 117 | const string &CloudItem::name() const { | ||
3703 | 118 | return p->name_; | ||
3704 | 119 | } | ||
3705 | 120 | |||
3706 | 121 | const time_t &CloudItem::created_date() const { | ||
3707 | 122 | return p->created_date_; | ||
3708 | 123 | } | ||
3709 | 124 | |||
3710 | 125 | const time_t &CloudItem::updated_date() const { | ||
3711 | 126 | return p->updated_date_; | ||
3712 | 127 | } | ||
3713 | 128 | |||
3714 | 129 | const string &CloudItem::download_url() const { | ||
3715 | 130 | return p->download_url_; | ||
3716 | 131 | } | ||
3717 | 132 | |||
3718 | 133 | const string &CloudItem::folder_id() const { | ||
3719 | 134 | return p->folder_id_; | ||
3720 | 135 | } | ||
3721 | 136 | |||
3722 | 137 | const string &CloudItem::etag() const { | ||
3723 | 138 | return p->etag_; | ||
3724 | 139 | } | ||
3725 | 140 | |||
3726 | 141 | const string &CloudItem::owner() const { | ||
3727 | 142 | return p->owner_; | ||
3728 | 143 | } | ||
3729 | 144 | |||
3730 | 145 | CloudResource::Property CloudItem::property() const { | ||
3731 | 146 | return CloudResource::Property::Content; | ||
3732 | 147 | } | ||
3733 | 148 | |||
3734 | 149 | int64_t CloudItem::size() const { | ||
3735 | 150 | return p->content_size_; | ||
3736 | 151 | } | ||
3737 | 152 | |||
3738 | 153 | const string &CloudItem::folder_path() const | ||
3739 | 154 | { | ||
3740 | 155 | return p->folder_path_; | ||
3741 | 156 | } | ||
3742 | 157 | |||
3743 | 158 | const string &CloudItem::mimetype() const | ||
3744 | 159 | { | ||
3745 | 160 | return p->mimetype_; | ||
3746 | 161 | } | ||
3747 | 162 | |||
3748 | 163 | std::unordered_map<string, string> &CloudItem::metadata() const | ||
3749 | 164 | { | ||
3750 | 165 | return p->metadata_; | ||
3751 | 166 | } | ||
3752 | 0 | 167 | ||
3753 | === added file 'src/onedrive/api/config.h' | |||
3754 | --- src/onedrive/api/config.h 1970-01-01 00:00:00 +0000 | |||
3755 | +++ src/onedrive/api/config.h 2016-09-30 08:26:58 +0000 | |||
3756 | @@ -0,0 +1,55 @@ | |||
3757 | 1 | /* | ||
3758 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
3759 | 3 | * | ||
3760 | 4 | * This library is free software; you can redistribute it and/or modify it under | ||
3761 | 5 | * the terms of version 3 of the GNU Lesser General Public License as published | ||
3762 | 6 | * by the Free Software Foundation. | ||
3763 | 7 | * | ||
3764 | 8 | * This library is distributed in the hope that it will be useful, but WITHOUT | ||
3765 | 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
3766 | 10 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
3767 | 11 | * details. | ||
3768 | 12 | * | ||
3769 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3770 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3771 | 15 | * | ||
3772 | 16 | * Author: Gary Wang <gary.wang@canonical.com> | ||
3773 | 17 | */ | ||
3774 | 18 | |||
3775 | 19 | #ifndef ONEDRIVE_API_CONFIG_H_ | ||
3776 | 20 | #define ONEDRIVE_API_CONFIG_H_ | ||
3777 | 21 | |||
3778 | 22 | #include <memory> | ||
3779 | 23 | #include <string> | ||
3780 | 24 | |||
3781 | 25 | namespace onedrive { | ||
3782 | 26 | namespace api { | ||
3783 | 27 | |||
3784 | 28 | struct Config { | ||
3785 | 29 | typedef std::shared_ptr<Config> Ptr; | ||
3786 | 30 | |||
3787 | 31 | /* | ||
3788 | 32 | * The access token assigned by onedrive after authenticated. | ||
3789 | 33 | */ | ||
3790 | 34 | std::string access_token { }; | ||
3791 | 35 | |||
3792 | 36 | /* | ||
3793 | 37 | * The root of all API request URLs | ||
3794 | 38 | */ | ||
3795 | 39 | std::string apiroot {"https://api.onedrive.com/v1.0"}; | ||
3796 | 40 | |||
3797 | 41 | /* | ||
3798 | 42 | * The custom HTTP user agent string for this library | ||
3799 | 43 | */ | ||
3800 | 44 | std::string user_agent {"ubuntu-onedrive-lib"}; | ||
3801 | 45 | |||
3802 | 46 | /* | ||
3803 | 47 | * request timeout for onedrive restful api | ||
3804 | 48 | */ | ||
3805 | 49 | int request_timeout = 1; | ||
3806 | 50 | }; | ||
3807 | 51 | |||
3808 | 52 | } | ||
3809 | 53 | } | ||
3810 | 54 | |||
3811 | 55 | #endif /* ONEDRIVE_API_CONFIG_H_ */ | ||
3812 | 0 | 56 | ||
3813 | === added file 'src/onedrive/api/downloadtask.cpp' | |||
3814 | --- src/onedrive/api/downloadtask.cpp 1970-01-01 00:00:00 +0000 | |||
3815 | +++ src/onedrive/api/downloadtask.cpp 2016-09-30 08:26:58 +0000 | |||
3816 | @@ -0,0 +1,65 @@ | |||
3817 | 1 | /* | ||
3818 | 2 | * Copyright © 2016 Canonical Ltd. | ||
3819 | 3 | * | ||
3820 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3821 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
3822 | 6 | * as published by the Free Software Foundation. | ||
3823 | 7 | * | ||
3824 | 8 | * This program is distributed in the hope that it will be useful, | ||
3825 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3826 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3827 | 11 | * GNU Lesser General Public License for more details. | ||
3828 | 12 | * | ||
3829 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3830 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3831 | 15 | * | ||
3832 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
3833 | 17 | */ | ||
3834 | 18 | |||
3835 | 19 | #include <onedrive/api/downloadtask.h> | ||
3836 | 20 | |||
3837 | 21 | #include "downloadtask_priv.h" | ||
3838 | 22 | #include "taskhandler.h" | ||
3839 | 23 | |||
3840 | 24 | using namespace onedrive::api; | ||
3841 | 25 | using namespace std; | ||
3842 | 26 | |||
3843 | 27 | DownloadTask::DownloadTask(std::shared_ptr<DownloadTaskPriv> p) | ||
3844 | 28 | :p_(p){ | ||
3845 | 29 | } | ||
3846 | 30 | |||
3847 | 31 | const string & DownloadTask::task_url() const { | ||
3848 | 32 | return p_->task_url(); | ||
3849 | 33 | } | ||
3850 | 34 | |||
3851 | 35 | const string &DownloadTask::error_code() const { | ||
3852 | 36 | return p_->error_code(); | ||
3853 | 37 | } | ||
3854 | 38 | |||
3855 | 39 | Task::Status DownloadTask::status() const { | ||
3856 | 40 | return p_->task_handler()->status(); | ||
3857 | 41 | } | ||
3858 | 42 | |||
3859 | 43 | const string & DownloadTask::content_name() const { | ||
3860 | 44 | return p_->content_name(); | ||
3861 | 45 | } | ||
3862 | 46 | |||
3863 | 47 | const string & DownloadTask::file_path() const { | ||
3864 | 48 | return p_->file_path(); | ||
3865 | 49 | } | ||
3866 | 50 | |||
3867 | 51 | Task::ProgressHandler & DownloadTask::progress_changed() { | ||
3868 | 52 | return p_->progress_changed(); | ||
3869 | 53 | } | ||
3870 | 54 | |||
3871 | 55 | Task::StatusHandler & DownloadTask::status_changed() { | ||
3872 | 56 | return p_->status_changed(); | ||
3873 | 57 | } | ||
3874 | 58 | |||
3875 | 59 | const string & DownloadTask::error_message() const { | ||
3876 | 60 | return p_->error_string(); | ||
3877 | 61 | } | ||
3878 | 62 | |||
3879 | 63 | void DownloadTask::cancel() { | ||
3880 | 64 | p_->task_handler()->cancel(); | ||
3881 | 65 | } | ||
3882 | 0 | 66 | ||
3883 | === added file 'src/onedrive/api/downloadtask_priv.cpp' | |||
3884 | --- src/onedrive/api/downloadtask_priv.cpp 1970-01-01 00:00:00 +0000 | |||
3885 | +++ src/onedrive/api/downloadtask_priv.cpp 2016-09-30 08:26:58 +0000 | |||
3886 | @@ -0,0 +1,193 @@ | |||
3887 | 1 | /* | ||
3888 | 2 | * Copyright © 2016 Canonical Ltd. | ||
3889 | 3 | * | ||
3890 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
3891 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
3892 | 6 | * as published by the Free Software Foundation. | ||
3893 | 7 | * | ||
3894 | 8 | * This program is distributed in the hope that it will be useful, | ||
3895 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3896 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3897 | 11 | * GNU Lesser General Public License for more details. | ||
3898 | 12 | * | ||
3899 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3900 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3901 | 15 | * | ||
3902 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
3903 | 17 | */ | ||
3904 | 18 | |||
3905 | 19 | #include "downloadtask_priv.h" | ||
3906 | 20 | #include "taskhandler.h" | ||
3907 | 21 | |||
3908 | 22 | #include <boost/filesystem.hpp> | ||
3909 | 23 | #include <json/json.h> | ||
3910 | 24 | |||
3911 | 25 | #include <iostream> | ||
3912 | 26 | |||
3913 | 27 | namespace json = Json; | ||
3914 | 28 | namespace fs = boost::filesystem; | ||
3915 | 29 | |||
3916 | 30 | using namespace onedrive::api; | ||
3917 | 31 | using namespace std; | ||
3918 | 32 | |||
3919 | 33 | namespace { | ||
3920 | 34 | static const std::string public_download_dir = std::string(getenv("HOME")) + "/Downloads"; | ||
3921 | 35 | } | ||
3922 | 36 | |||
3923 | 37 | DownloadTaskPriv::DownloadTaskPriv(const CloudItem::Ptr &root, | ||
3924 | 38 | Task::Buffer_Callback write_cb) | ||
3925 | 39 | :progress_handler_(nullptr), | ||
3926 | 40 | status_handler_(nullptr), | ||
3927 | 41 | buffer_callback_(write_cb), | ||
3928 | 42 | task_handler_(std::make_shared<TaskHandler>()) | ||
3929 | 43 | { | ||
3930 | 44 | content_id_ = root->id(); | ||
3931 | 45 | content_name_ = root->name(); | ||
3932 | 46 | task_url_ = root->download_url(); | ||
3933 | 47 | |||
3934 | 48 | if (!buffer_callback_) { | ||
3935 | 49 | // create temp file path in temp path for writing | ||
3936 | 50 | file_path_ = fs::path(fs::temp_directory_path() / fs::unique_path()) | ||
3937 | 51 | .string(); | ||
3938 | 52 | } | ||
3939 | 53 | |||
3940 | 54 | task_handler_->on_prepare() = [this](){ | ||
3941 | 55 | if (!buffer_callback_) { | ||
3942 | 56 | if (ofs_.is_open()) | ||
3943 | 57 | ofs_.close(); | ||
3944 | 58 | |||
3945 | 59 | ofs_.open(file_path_, std::ofstream::out | std::ofstream::trunc); | ||
3946 | 60 | if (ofs_.fail()) { | ||
3947 | 61 | throw runtime_error("failed to open file" + file_path_ + " error: " + strerror(errno)); | ||
3948 | 62 | } | ||
3949 | 63 | } | ||
3950 | 64 | |||
3951 | 65 | //change status | ||
3952 | 66 | task_handler_->set_status(Task::Status::Running); | ||
3953 | 67 | }; | ||
3954 | 68 | |||
3955 | 69 | task_handler_->on_progress() = [this](float percent){ | ||
3956 | 70 | if (progress_handler_) { | ||
3957 | 71 | progress_handler_(percent); | ||
3958 | 72 | } | ||
3959 | 73 | }; | ||
3960 | 74 | |||
3961 | 75 | task_handler_->on_status() = [this](Task::Status status){ | ||
3962 | 76 | if (status_handler_) { | ||
3963 | 77 | status_handler_(status); | ||
3964 | 78 | } | ||
3965 | 79 | }; | ||
3966 | 80 | |||
3967 | 81 | task_handler_->on_finished() = [this](const std::string &/*response*/) -> bool { | ||
3968 | 82 | ofs_.close(); | ||
3969 | 83 | |||
3970 | 84 | if (!buffer_callback_) { | ||
3971 | 85 | std::string download_dir; | ||
3972 | 86 | if (getenv("ONEDRIVE_DOWNLOAD_FOLDER")) { | ||
3973 | 87 | download_dir = string(getenv("ONEDRIVE_DOWNLOAD_FOLDER")); | ||
3974 | 88 | } else { | ||
3975 | 89 | download_dir = public_download_dir; | ||
3976 | 90 | } | ||
3977 | 91 | |||
3978 | 92 | if (!fs::exists(fs::path(download_dir))) { | ||
3979 | 93 | try { | ||
3980 | 94 | fs::create_directory(fs::path(download_dir)); | ||
3981 | 95 | } catch(boost::filesystem::filesystem_error& e) { | ||
3982 | 96 | cerr << "create download directory failed"<< download_dir | ||
3983 | 97 | << "error: " << e.what() << endl; | ||
3984 | 98 | } | ||
3985 | 99 | return false; | ||
3986 | 100 | } | ||
3987 | 101 | |||
3988 | 102 | //check if there is a duplicate one | ||
3989 | 103 | std::string stem = fs::path(content_name_).stem().string(); | ||
3990 | 104 | fs::path dest = download_dir + "/" + content_name_; | ||
3991 | 105 | int dup_count = 0; | ||
3992 | 106 | while (fs::exists(dest)) { | ||
3993 | 107 | dest = fs::path(download_dir) / fs::path(stem | ||
3994 | 108 | + "_" | ||
3995 | 109 | + std::to_string(++dup_count) | ||
3996 | 110 | + dest.extension().string()); | ||
3997 | 111 | } | ||
3998 | 112 | |||
3999 | 113 | try { | ||
4000 | 114 | // rename in final when download is complete. | ||
4001 | 115 | fs::rename(file_path_, dest); | ||
4002 | 116 | file_path_ = dest.string(); | ||
4003 | 117 | } catch (boost::filesystem::filesystem_error& e) { | ||
4004 | 118 | cerr << "create download directory failed"<< download_dir | ||
4005 | 119 | << "error: " << e.what() << endl; | ||
4006 | 120 | return false; | ||
4007 | 121 | } | ||
4008 | 122 | } | ||
4009 | 123 | |||
4010 | 124 | //change status | ||
4011 | 125 | task_handler_->reset_broken_counter(); | ||
4012 | 126 | task_handler_->set_status(Task::Status::Complete); | ||
4013 | 127 | |||
4014 | 128 | return true; | ||
4015 | 129 | }; | ||
4016 | 130 | |||
4017 | 131 | task_handler_->on_ready_read() = [this](const string &data){ | ||
4018 | 132 | if (buffer_callback_) { | ||
4019 | 133 | buffer_callback_((void *)data.c_str(), data.size()); | ||
4020 | 134 | } else { | ||
4021 | 135 | ofs_.write(data.c_str(), data.size()); | ||
4022 | 136 | } | ||
4023 | 137 | }; | ||
4024 | 138 | } | ||
4025 | 139 | |||
4026 | 140 | const string & DownloadTaskPriv::task_url() const { | ||
4027 | 141 | return task_url_; | ||
4028 | 142 | } | ||
4029 | 143 | |||
4030 | 144 | Task::Status DownloadTaskPriv::status() const { | ||
4031 | 145 | return task_handler_->status(); | ||
4032 | 146 | } | ||
4033 | 147 | |||
4034 | 148 | const string & DownloadTaskPriv::content_name() const { | ||
4035 | 149 | return content_name_; | ||
4036 | 150 | } | ||
4037 | 151 | |||
4038 | 152 | const string & DownloadTaskPriv::file_path() const { | ||
4039 | 153 | return file_path_; | ||
4040 | 154 | } | ||
4041 | 155 | |||
4042 | 156 | const string &DownloadTaskPriv::error_code() const { | ||
4043 | 157 | return error_code_; | ||
4044 | 158 | } | ||
4045 | 159 | |||
4046 | 160 | Task::ProgressHandler & DownloadTaskPriv::progress_changed() { | ||
4047 | 161 | return progress_handler_; | ||
4048 | 162 | } | ||
4049 | 163 | |||
4050 | 164 | Task::StatusHandler &DownloadTaskPriv::status_changed() { | ||
4051 | 165 | return status_handler_; | ||
4052 | 166 | } | ||
4053 | 167 | |||
4054 | 168 | Task::Buffer_Callback &DownloadTaskPriv::buffer_callback() { | ||
4055 | 169 | return buffer_callback_; | ||
4056 | 170 | } | ||
4057 | 171 | |||
4058 | 172 | const string & DownloadTaskPriv::error_string() const { | ||
4059 | 173 | return error_string_; | ||
4060 | 174 | } | ||
4061 | 175 | |||
4062 | 176 | void DownloadTaskPriv::set_error_info(const std::string & err) { | ||
4063 | 177 | json::Reader reader; | ||
4064 | 178 | json::Value root; | ||
4065 | 179 | if (reader.parse(err, root)) { | ||
4066 | 180 | error_code_ = root["error"]["code"].asString(); | ||
4067 | 181 | error_string_ = root["error"]["message"].asString(); | ||
4068 | 182 | } else { | ||
4069 | 183 | error_string_ = err; | ||
4070 | 184 | } | ||
4071 | 185 | } | ||
4072 | 186 | |||
4073 | 187 | void DownloadTaskPriv::cancel() { | ||
4074 | 188 | task_handler_->cancel(); | ||
4075 | 189 | } | ||
4076 | 190 | |||
4077 | 191 | std::shared_ptr<TaskHandler> DownloadTaskPriv::task_handler() const { | ||
4078 | 192 | return task_handler_; | ||
4079 | 193 | } | ||
4080 | 0 | 194 | ||
4081 | === added file 'src/onedrive/api/downloadtask_priv.h' | |||
4082 | --- src/onedrive/api/downloadtask_priv.h 1970-01-01 00:00:00 +0000 | |||
4083 | +++ src/onedrive/api/downloadtask_priv.h 2016-09-30 08:26:58 +0000 | |||
4084 | @@ -0,0 +1,95 @@ | |||
4085 | 1 | /* | ||
4086 | 2 | * Copyright © 2016 Canonical Ltd. | ||
4087 | 3 | * | ||
4088 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4089 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
4090 | 6 | * as published by the Free Software Foundation. | ||
4091 | 7 | * | ||
4092 | 8 | * This program is distributed in the hope that it will be useful, | ||
4093 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4094 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4095 | 11 | * GNU Lesser General Public License for more details. | ||
4096 | 12 | * | ||
4097 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4098 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4099 | 15 | * | ||
4100 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
4101 | 17 | */ | ||
4102 | 18 | |||
4103 | 19 | #ifndef ONEDRIVE_API_DOWNLOADTASKPRIV_H_ | ||
4104 | 20 | #define ONEDRIVE_API_DOWNLOADTASKPRIV_H_ | ||
4105 | 21 | |||
4106 | 22 | #include <onedrive/api/task.h> | ||
4107 | 23 | #include <onedrive/api/clouditem.h> | ||
4108 | 24 | |||
4109 | 25 | #include <memory> | ||
4110 | 26 | #include <fstream> | ||
4111 | 27 | |||
4112 | 28 | namespace onedrive { | ||
4113 | 29 | namespace api { | ||
4114 | 30 | |||
4115 | 31 | class TaskHandler; | ||
4116 | 32 | |||
4117 | 33 | class DownloadTaskPriv { | ||
4118 | 34 | public: | ||
4119 | 35 | typedef std::shared_ptr<DownloadTaskPriv> Ptr; | ||
4120 | 36 | |||
4121 | 37 | DownloadTaskPriv(const CloudItem::Ptr &root, | ||
4122 | 38 | Task::Buffer_Callback write_cb = nullptr); | ||
4123 | 39 | |||
4124 | 40 | virtual ~DownloadTaskPriv() = default; | ||
4125 | 41 | |||
4126 | 42 | const std::string & task_url() const; | ||
4127 | 43 | |||
4128 | 44 | Task::Status status() const; | ||
4129 | 45 | |||
4130 | 46 | const std::string & content_id() const; | ||
4131 | 47 | |||
4132 | 48 | const std::string & content_name() const; | ||
4133 | 49 | |||
4134 | 50 | const std::string & file_path() const; | ||
4135 | 51 | |||
4136 | 52 | const std::string & error_code() const; | ||
4137 | 53 | |||
4138 | 54 | const std::string & error_string() const; | ||
4139 | 55 | |||
4140 | 56 | void set_error_info(const std::string & err); | ||
4141 | 57 | |||
4142 | 58 | Task::ProgressHandler & progress_changed(); | ||
4143 | 59 | |||
4144 | 60 | Task::StatusHandler & status_changed(); | ||
4145 | 61 | |||
4146 | 62 | Task::Buffer_Callback & buffer_callback(); | ||
4147 | 63 | |||
4148 | 64 | void cancel(); | ||
4149 | 65 | |||
4150 | 66 | std::shared_ptr<TaskHandler> task_handler() const; | ||
4151 | 67 | |||
4152 | 68 | private: | ||
4153 | 69 | std::string content_id_; | ||
4154 | 70 | |||
4155 | 71 | std::string content_name_; | ||
4156 | 72 | |||
4157 | 73 | std::string file_path_; | ||
4158 | 74 | |||
4159 | 75 | std::string task_url_; | ||
4160 | 76 | |||
4161 | 77 | std::string error_code_; | ||
4162 | 78 | |||
4163 | 79 | std::string error_string_; | ||
4164 | 80 | |||
4165 | 81 | std::ofstream ofs_; | ||
4166 | 82 | |||
4167 | 83 | Task::ProgressHandler progress_handler_; | ||
4168 | 84 | |||
4169 | 85 | Task::StatusHandler status_handler_; | ||
4170 | 86 | |||
4171 | 87 | Task::Buffer_Callback buffer_callback_; | ||
4172 | 88 | |||
4173 | 89 | std::shared_ptr<TaskHandler> task_handler_; | ||
4174 | 90 | }; | ||
4175 | 91 | |||
4176 | 92 | } | ||
4177 | 93 | } | ||
4178 | 94 | |||
4179 | 95 | #endif // ONEDRIVE_API_DOWNLOADTASKPRIV_H_ | ||
4180 | 0 | 96 | ||
4181 | === added file 'src/onedrive/api/storageinfo.cpp' | |||
4182 | --- src/onedrive/api/storageinfo.cpp 1970-01-01 00:00:00 +0000 | |||
4183 | +++ src/onedrive/api/storageinfo.cpp 2016-09-30 08:26:58 +0000 | |||
4184 | @@ -0,0 +1,64 @@ | |||
4185 | 1 | /* | ||
4186 | 2 | * Copyright © 2016 Canonical Ltd. | ||
4187 | 3 | * | ||
4188 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4189 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
4190 | 6 | * as published by the Free Software Foundation. | ||
4191 | 7 | * | ||
4192 | 8 | * This program is distributed in the hope that it will be useful, | ||
4193 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4194 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4195 | 11 | * GNU Lesser General Public License for more details. | ||
4196 | 12 | * | ||
4197 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4198 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4199 | 15 | * | ||
4200 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
4201 | 17 | */ | ||
4202 | 18 | |||
4203 | 19 | #include <onedrive/api/storageinfo.h> | ||
4204 | 20 | |||
4205 | 21 | #include <json/json.h> | ||
4206 | 22 | |||
4207 | 23 | using namespace onedrive::api; | ||
4208 | 24 | using namespace std; | ||
4209 | 25 | |||
4210 | 26 | namespace json = Json; | ||
4211 | 27 | |||
4212 | 28 | class StorageInfo::Priv { | ||
4213 | 29 | public: | ||
4214 | 30 | Priv(const json::Value &root) { | ||
4215 | 31 | id_ = root["owner"]["user"]["id"].asString(); | ||
4216 | 32 | name_ = root["owner"]["user"]["displayName"].asString(); | ||
4217 | 33 | disk_size_ = root["quota"]["total"].asUInt64(); | ||
4218 | 34 | used_disk_size_ = root["quota"]["used"].asUInt64(); | ||
4219 | 35 | } | ||
4220 | 36 | |||
4221 | 37 | string id_; | ||
4222 | 38 | |||
4223 | 39 | string name_; | ||
4224 | 40 | |||
4225 | 41 | int64_t used_disk_size_; | ||
4226 | 42 | |||
4227 | 43 | int64_t disk_size_; | ||
4228 | 44 | }; | ||
4229 | 45 | |||
4230 | 46 | StorageInfo::StorageInfo(const json::Value &root) | ||
4231 | 47 | : p(std::make_shared<Priv>(root)){ | ||
4232 | 48 | } | ||
4233 | 49 | |||
4234 | 50 | int64_t StorageInfo::used_disk_size() const { | ||
4235 | 51 | return p->used_disk_size_; | ||
4236 | 52 | } | ||
4237 | 53 | |||
4238 | 54 | int64_t StorageInfo::total_disk_size() const { | ||
4239 | 55 | return p->disk_size_; | ||
4240 | 56 | } | ||
4241 | 57 | |||
4242 | 58 | const string & StorageInfo::id() const { | ||
4243 | 59 | return p->id_; | ||
4244 | 60 | } | ||
4245 | 61 | |||
4246 | 62 | const string & StorageInfo::name() const { | ||
4247 | 63 | return p->name_; | ||
4248 | 64 | } | ||
4249 | 0 | 65 | ||
4250 | === added file 'src/onedrive/api/syncmanager.cpp' | |||
4251 | --- src/onedrive/api/syncmanager.cpp 1970-01-01 00:00:00 +0000 | |||
4252 | +++ src/onedrive/api/syncmanager.cpp 2016-09-30 08:26:58 +0000 | |||
4253 | @@ -0,0 +1,70 @@ | |||
4254 | 1 | /* | ||
4255 | 2 | * Copyright © 2016 Canonical Ltd. | ||
4256 | 3 | * | ||
4257 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4258 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
4259 | 6 | * as published by the Free Software Foundation. | ||
4260 | 7 | * | ||
4261 | 8 | * This program is distributed in the hope that it will be useful, | ||
4262 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4263 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4264 | 11 | * GNU Lesser General Public License for more details. | ||
4265 | 12 | * | ||
4266 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4267 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4268 | 15 | * | ||
4269 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
4270 | 17 | */ | ||
4271 | 18 | |||
4272 | 19 | |||
4273 | 20 | #include <onedrive/api/syncmanager.h> | ||
4274 | 21 | #include <onedrive/api/taskqueue.h> | ||
4275 | 22 | |||
4276 | 23 | #include "syncthread.h" | ||
4277 | 24 | #include "client_priv.h" | ||
4278 | 25 | #include "syncmanager_priv.h" | ||
4279 | 26 | |||
4280 | 27 | #include <iostream> | ||
4281 | 28 | |||
4282 | 29 | using namespace onedrive::api; | ||
4283 | 30 | using namespace std; | ||
4284 | 31 | |||
4285 | 32 | SyncManager::SyncManager(ClientPriv* client_priv) | ||
4286 | 33 | :p_(std::make_shared<SyncManagerPriv>(client_priv)) { | ||
4287 | 34 | } | ||
4288 | 35 | |||
4289 | 36 | void SyncManager::start() { | ||
4290 | 37 | p_->start(); | ||
4291 | 38 | } | ||
4292 | 39 | |||
4293 | 40 | void SyncManager::cancel() { | ||
4294 | 41 | p_->cancel(); | ||
4295 | 42 | } | ||
4296 | 43 | |||
4297 | 44 | void SyncManager::pause() { | ||
4298 | 45 | p_->pause(); | ||
4299 | 46 | } | ||
4300 | 47 | |||
4301 | 48 | UploadTask::Ptr SyncManager::add_upload_task(const UploadRequest &request_item) { | ||
4302 | 49 | return p_->add_upload_task(request_item); | ||
4303 | 50 | } | ||
4304 | 51 | |||
4305 | 52 | UploadTask::Ptr SyncManager::add_upload_task(const UploadBufferCb &buffer_cb) { | ||
4306 | 53 | return p_->add_upload_task(buffer_cb); | ||
4307 | 54 | } | ||
4308 | 55 | |||
4309 | 56 | DownloadTask::Ptr SyncManager::add_download_task(const string &content_id) { | ||
4310 | 57 | return p_->add_download_task(content_id); | ||
4311 | 58 | } | ||
4312 | 59 | |||
4313 | 60 | DownloadTask::Ptr SyncManager::add_download_task(const DownloadBufferCb &buffer_cb) { | ||
4314 | 61 | return p_->add_download_task(buffer_cb); | ||
4315 | 62 | } | ||
4316 | 63 | |||
4317 | 64 | TaskQueue<std::shared_ptr<DownloadTask>> SyncManager::download_queue() { | ||
4318 | 65 | return p_->download_queue(); | ||
4319 | 66 | } | ||
4320 | 67 | |||
4321 | 68 | TaskQueue<std::shared_ptr<UploadTask>> SyncManager::upload_queue() { | ||
4322 | 69 | return p_->upload_queue(); | ||
4323 | 70 | } | ||
4324 | 0 | 71 | ||
4325 | === added file 'src/onedrive/api/syncmanager_priv.cpp' | |||
4326 | --- src/onedrive/api/syncmanager_priv.cpp 1970-01-01 00:00:00 +0000 | |||
4327 | +++ src/onedrive/api/syncmanager_priv.cpp 2016-09-30 08:26:58 +0000 | |||
4328 | @@ -0,0 +1,111 @@ | |||
4329 | 1 | /* | ||
4330 | 2 | * Copyright © 2016 Canonical Ltd. | ||
4331 | 3 | * | ||
4332 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4333 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
4334 | 6 | * as published by the Free Software Foundation. | ||
4335 | 7 | * | ||
4336 | 8 | * This program is distributed in the hope that it will be useful, | ||
4337 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4338 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4339 | 11 | * GNU Lesser General Public License for more details. | ||
4340 | 12 | * | ||
4341 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4342 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4343 | 15 | * | ||
4344 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
4345 | 17 | */ | ||
4346 | 18 | |||
4347 | 19 | #include <onedrive/api/syncmanager.h> | ||
4348 | 20 | #include <onedrive/api/taskqueue.h> | ||
4349 | 21 | |||
4350 | 22 | #include "syncmanager_priv.h" | ||
4351 | 23 | #include "client_priv.h" | ||
4352 | 24 | #include "syncthread.h" | ||
4353 | 25 | |||
4354 | 26 | #include <iostream> | ||
4355 | 27 | |||
4356 | 28 | using namespace onedrive::api; | ||
4357 | 29 | using namespace std; | ||
4358 | 30 | |||
4359 | 31 | SyncManagerPriv::SyncManagerPriv(ClientPriv *client) | ||
4360 | 32 | : download_thread_() | ||
4361 | 33 | , upload_thread_() | ||
4362 | 34 | , client_(client){ | ||
4363 | 35 | start(); | ||
4364 | 36 | } | ||
4365 | 37 | |||
4366 | 38 | SyncManagerPriv::~SyncManagerPriv() { | ||
4367 | 39 | download_thread_.stop(); | ||
4368 | 40 | upload_thread_.stop(); | ||
4369 | 41 | } | ||
4370 | 42 | |||
4371 | 43 | void SyncManagerPriv::set_access_token(const std::string &token) { | ||
4372 | 44 | download_thread_.set_access_token(token); | ||
4373 | 45 | upload_thread_.set_access_token(token); | ||
4374 | 46 | } | ||
4375 | 47 | |||
4376 | 48 | DownloadTask::Ptr SyncManagerPriv::add_download_task(const string &content_id) { | ||
4377 | 49 | auto res = client_->metadata(content_id); | ||
4378 | 50 | auto item = std::static_pointer_cast<CloudItem>(res); | ||
4379 | 51 | auto task_p = std::shared_ptr<DownloadTaskPriv>(new DownloadTaskPriv(item)); | ||
4380 | 52 | download_thread_.add_task(task_p); | ||
4381 | 53 | |||
4382 | 54 | auto task = std::shared_ptr<DownloadTask>(new DownloadTask(task_p)); | ||
4383 | 55 | download_queue_.push(task); | ||
4384 | 56 | return task; | ||
4385 | 57 | } | ||
4386 | 58 | |||
4387 | 59 | DownloadTask::Ptr SyncManagerPriv::add_download_task(const DownloadBufferCb &buf_item) { | ||
4388 | 60 | auto res = client_->metadata(buf_item.content_id); | ||
4389 | 61 | auto item = std::static_pointer_cast<CloudItem>(res); | ||
4390 | 62 | auto task_p = std::shared_ptr<DownloadTaskPriv>(new DownloadTaskPriv(item, buf_item.write_cb)); | ||
4391 | 63 | download_thread_.add_task(task_p); | ||
4392 | 64 | |||
4393 | 65 | auto task = std::shared_ptr<DownloadTask>(new DownloadTask(task_p)); | ||
4394 | 66 | download_queue_.push(task); | ||
4395 | 67 | return task; | ||
4396 | 68 | } | ||
4397 | 69 | |||
4398 | 70 | UploadTask::Ptr SyncManagerPriv::add_upload_task(const UploadRequest &request) { | ||
4399 | 71 | auto item_p = std::shared_ptr<UploadTaskPriv>(new UploadTaskPriv(request)); | ||
4400 | 72 | cout << "push upload link url in queue : " + item_p->task_url() << endl; | ||
4401 | 73 | upload_thread_.add_task(item_p); | ||
4402 | 74 | |||
4403 | 75 | auto item = std::shared_ptr<UploadTask>(new UploadTask(item_p)); | ||
4404 | 76 | upload_queue_.push(item); | ||
4405 | 77 | return item; | ||
4406 | 78 | } | ||
4407 | 79 | |||
4408 | 80 | UploadTask::Ptr SyncManagerPriv::add_upload_task(const UploadBufferCb &buffer_cb) { | ||
4409 | 81 | auto item_p = std::shared_ptr<UploadTaskPriv>(new UploadTaskPriv(buffer_cb)); | ||
4410 | 82 | cout << "push upload link url in queue : " + item_p->task_url() << endl; | ||
4411 | 83 | upload_thread_.add_task(item_p); | ||
4412 | 84 | |||
4413 | 85 | auto item = std::shared_ptr<UploadTask>(new UploadTask(item_p)); | ||
4414 | 86 | upload_queue_.push(item); | ||
4415 | 87 | return item; | ||
4416 | 88 | } | ||
4417 | 89 | |||
4418 | 90 | TaskQueue<DownloadTask::Ptr> SyncManagerPriv::download_queue() { | ||
4419 | 91 | return download_queue_; | ||
4420 | 92 | } | ||
4421 | 93 | |||
4422 | 94 | TaskQueue<UploadTask::Ptr> SyncManagerPriv::upload_queue() { | ||
4423 | 95 | return upload_queue_; | ||
4424 | 96 | } | ||
4425 | 97 | |||
4426 | 98 | void SyncManagerPriv::start() { | ||
4427 | 99 | download_thread_.start(); | ||
4428 | 100 | upload_thread_.start(); | ||
4429 | 101 | } | ||
4430 | 102 | |||
4431 | 103 | void SyncManagerPriv::cancel() { | ||
4432 | 104 | download_thread_.cancel(); | ||
4433 | 105 | upload_thread_.cancel(); | ||
4434 | 106 | } | ||
4435 | 107 | |||
4436 | 108 | void SyncManagerPriv::pause() { | ||
4437 | 109 | download_thread_.pause(); | ||
4438 | 110 | upload_thread_.pause(); | ||
4439 | 111 | } | ||
4440 | 0 | 112 | ||
4441 | === added file 'src/onedrive/api/syncmanager_priv.h' | |||
4442 | --- src/onedrive/api/syncmanager_priv.h 1970-01-01 00:00:00 +0000 | |||
4443 | +++ src/onedrive/api/syncmanager_priv.h 2016-09-30 08:26:58 +0000 | |||
4444 | @@ -0,0 +1,76 @@ | |||
4445 | 1 | /* | ||
4446 | 2 | * Copyright © 2016 Canonical Ltd. | ||
4447 | 3 | * | ||
4448 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4449 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
4450 | 6 | * as published by the Free Software Foundation. | ||
4451 | 7 | * | ||
4452 | 8 | * This program is distributed in the hope that it will be useful, | ||
4453 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4454 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4455 | 11 | * GNU Lesser General Public License for more details. | ||
4456 | 12 | * | ||
4457 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4458 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4459 | 15 | * | ||
4460 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
4461 | 17 | */ | ||
4462 | 18 | |||
4463 | 19 | #ifndef ONEDRIVE_API_SYNCMANAGERPRIV_H_ | ||
4464 | 20 | #define ONEDRIVE_API_SYNCMANAGERPRIV_H_ | ||
4465 | 21 | |||
4466 | 22 | #include <onedrive/api/taskqueue.h> | ||
4467 | 23 | #include <onedrive/api/downloadtask.h> | ||
4468 | 24 | #include <onedrive/api/uploadtask.h> | ||
4469 | 25 | #include <onedrive/api/visibility.h> | ||
4470 | 26 | |||
4471 | 27 | #include "syncthread.h" | ||
4472 | 28 | |||
4473 | 29 | #include <memory> | ||
4474 | 30 | |||
4475 | 31 | namespace onedrive { | ||
4476 | 32 | namespace api { | ||
4477 | 33 | |||
4478 | 34 | class ClientPriv; | ||
4479 | 35 | |||
4480 | 36 | class SyncManagerPriv { | ||
4481 | 37 | public: | ||
4482 | 38 | SyncManagerPriv(ClientPriv *client); | ||
4483 | 39 | |||
4484 | 40 | ~SyncManagerPriv(); | ||
4485 | 41 | |||
4486 | 42 | void set_access_token(const std::string &token); | ||
4487 | 43 | |||
4488 | 44 | DownloadTask::Ptr add_download_task(const std::string &content_id); | ||
4489 | 45 | |||
4490 | 46 | DownloadTask::Ptr add_download_task(const DownloadBufferCb &buf_item); | ||
4491 | 47 | |||
4492 | 48 | UploadTask::Ptr add_upload_task(const UploadRequest &request); | ||
4493 | 49 | |||
4494 | 50 | UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb); | ||
4495 | 51 | |||
4496 | 52 | TaskQueue<DownloadTask::Ptr> download_queue(); | ||
4497 | 53 | |||
4498 | 54 | TaskQueue<UploadTask::Ptr> upload_queue(); | ||
4499 | 55 | |||
4500 | 56 | void start(); | ||
4501 | 57 | |||
4502 | 58 | void cancel(); | ||
4503 | 59 | |||
4504 | 60 | void pause(); | ||
4505 | 61 | |||
4506 | 62 | private: | ||
4507 | 63 | SyncThread<DownloadTaskPriv> download_thread_; | ||
4508 | 64 | SyncThread<UploadTaskPriv> upload_thread_; | ||
4509 | 65 | |||
4510 | 66 | TaskQueue<DownloadTask::Ptr> download_queue_; | ||
4511 | 67 | TaskQueue<UploadTask::Ptr> upload_queue_; | ||
4512 | 68 | |||
4513 | 69 | ClientPriv* client_; | ||
4514 | 70 | }; | ||
4515 | 71 | |||
4516 | 72 | |||
4517 | 73 | } | ||
4518 | 74 | } | ||
4519 | 75 | |||
4520 | 76 | #endif // ONEDRIVE_API_SYNCMANAGERPRIV_H_ | ||
4521 | 0 | 77 | ||
4522 | === added file 'src/onedrive/api/syncthread.cpp' | |||
4523 | --- src/onedrive/api/syncthread.cpp 1970-01-01 00:00:00 +0000 | |||
4524 | +++ src/onedrive/api/syncthread.cpp 2016-09-30 08:26:58 +0000 | |||
4525 | @@ -0,0 +1,447 @@ | |||
4526 | 1 | /* | ||
4527 | 2 | * Copyright © 2016 Canonical Ltd. | ||
4528 | 3 | * | ||
4529 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
4530 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
4531 | 6 | * as published by the Free Software Foundation. | ||
4532 | 7 | * | ||
4533 | 8 | * This program is distributed in the hope that it will be useful, | ||
4534 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4535 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4536 | 11 | * GNU Lesser General Public License for more details. | ||
4537 | 12 | * | ||
4538 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4539 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4540 | 15 | * | ||
4541 | 16 | * Authored by: Gary Wang <gary.wang@canonical.com> | ||
4542 | 17 | */ | ||
4543 | 18 | |||
4544 | 19 | #include "syncthread.h" | ||
4545 | 20 | #include "taskhandler.h" | ||
4546 | 21 | #include "uploadtask_priv.h" | ||
4547 | 22 | #include "downloadtask_priv.h" | ||
4548 | 23 | |||
4549 | 24 | #include <boost/algorithm/string.hpp> | ||
4550 | 25 | #include <core/net/http/streaming_client.h> | ||
4551 | 26 | #include <core/net/http/streaming_request.h> | ||
4552 | 27 | #include <core/net/http/response.h> | ||
4553 | 28 | #include <core/net/http/status.h> | ||
4554 | 29 | |||
4555 | 30 | #include <fstream> | ||
4556 | 31 | #include <future> | ||
4557 | 32 | #include <iostream> | ||
4558 | 33 | |||
4559 | 34 | namespace http = core::net::http; | ||
4560 | 35 | namespace net = core::net; | ||
4561 | 36 | |||
4562 | 37 | using namespace onedrive::api; | ||
4563 | 38 | using namespace std; | ||
4564 | 39 | |||
4565 | 40 | template <typename T> | ||
4566 | 41 | class SyncThread<T>::HttpStreamClient { | ||
4567 | 42 | public: | ||
4568 | 43 | HttpStreamClient(int request_timeout) : | ||
4569 | 44 | request_timeout_(request_timeout), | ||
4570 | 45 | client_(http::make_streaming_client()), | ||
4571 | 46 | worker_ { [this]() {client_->run();} }{ | ||
4572 | 47 | } | ||
4573 | 48 | |||
4574 | 49 | ~HttpStreamClient() { | ||
4575 | 50 | client_->stop(); | ||
4576 | 51 | if (worker_.joinable()) { | ||
4577 | 52 | worker_.join(); | ||
4578 | 53 | } | ||
4579 | 54 | } | ||
4580 | 55 | |||
4581 | 56 | void async_get(shared_ptr<T> ptr, | ||
4582 | 57 | const http::Header &headers) { | ||
4583 | 58 | auto prom = make_shared<promise<bool>>(); | ||
4584 | 59 | |||
4585 | 60 | auto task_handler = ptr->task_handler(); | ||
4586 | 61 | http::Request::Handler handler; | ||
4587 | 62 | handler.on_progress([task_handler](const http::Request::Progress& progress) | ||
4588 | 63 | { | ||
4589 | 64 | if (task_handler->status() == Task::Status::Canceled) { | ||
4590 | 65 | return http::Request::Progress::Next::abort_operation; | ||
4591 | 66 | } | ||
4592 | 67 | |||
4593 | 68 | if (progress.download.current > 0.0 && progress.download.total > 0.0) { | ||
4594 | 69 | double percent = progress.download.current / progress.download.total; | ||
4595 | 70 | task_handler->on_progress()(percent); | ||
4596 | 71 | } | ||
4597 | 72 | |||
4598 | 73 | return http::Request::Progress::Next::continue_operation; | ||
4599 | 74 | } | ||
4600 | 75 | ); | ||
4601 | 76 | handler.on_error([prom](const net::Error& e) | ||
4602 | 77 | { | ||
4603 | 78 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
4604 | 79 | }); | ||
4605 | 80 | handler.on_response([prom, task_handler](const http::Response& response) | ||
4606 | 81 | { | ||
4607 | 82 | if (response.status != http::Status::ok) { | ||
4608 | 83 | prom->set_exception(make_exception_ptr(runtime_error(response.body))); | ||
4609 | 84 | } else { | ||
4610 | 85 | prom->set_value(task_handler->on_finished()(response.body)); | ||
4611 | 86 | } | ||
4612 | 87 | } | ||
4613 | 88 | ); | ||
4614 | 89 | |||
4615 | 90 | auto http_config = http::Request::Configuration::from_uri_as_string( | ||
4616 | 91 | ptr->task_url()); | ||
4617 | 92 | http_config.header = headers; | ||
4618 | 93 | |||
4619 | 94 | std::shared_future<bool> future = prom->get_future(); | ||
4620 | 95 | auto request = client_->streaming_get(http_config); | ||
4621 | 96 | request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time}); | ||
4622 | 97 | request->set_timeout(std::chrono::milliseconds{request_timeout_}); | ||
4623 | 98 | request->async_execute(handler, task_handler->on_ready_read()); | ||
4624 | 99 | |||
4625 | 100 | task_handler->attach_request(request, future); | ||
4626 | 101 | } | ||
4627 | 102 | |||
4628 | 103 | void async_put(shared_ptr<T> ptr, | ||
4629 | 104 | const http::Header &headers, | ||
4630 | 105 | std::istream &payload, | ||
4631 | 106 | std::size_t size) { | ||
4632 | 107 | auto prom = make_shared<promise<bool>>(); | ||
4633 | 108 | |||
4634 | 109 | auto task_handler = ptr->task_handler(); | ||
4635 | 110 | http::Request::Handler handler; | ||
4636 | 111 | handler.on_progress([task_handler](const http::Request::Progress& progress) | ||
4637 | 112 | { | ||
4638 | 113 | if (task_handler->status() == Task::Status::Canceled) { | ||
4639 | 114 | return http::Request::Progress::Next::abort_operation; | ||
4640 | 115 | } | ||
4641 | 116 | |||
4642 | 117 | if (progress.upload.current > 0.0 && progress.upload.total > 0.0) { | ||
4643 | 118 | double percent = (progress.upload.current / progress.upload.total); | ||
4644 | 119 | task_handler->on_progress()(percent); | ||
4645 | 120 | } | ||
4646 | 121 | |||
4647 | 122 | return http::Request::Progress::Next::continue_operation; | ||
4648 | 123 | } | ||
4649 | 124 | ); | ||
4650 | 125 | handler.on_error([prom](const net::Error& e) | ||
4651 | 126 | { | ||
4652 | 127 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
4653 | 128 | }); | ||
4654 | 129 | handler.on_response([prom, task_handler](const http::Response& response) | ||
4655 | 130 | { | ||
4656 | 131 | if (response.status != http::Status::ok && | ||
4657 | 132 | response.status != http::Status::created) { | ||
4658 | 133 | prom->set_exception(make_exception_ptr(runtime_error(response.body))); | ||
4659 | 134 | } else { | ||
4660 | 135 | prom->set_value(task_handler->on_finished()(response.body)); | ||
4661 | 136 | } | ||
4662 | 137 | } | ||
4663 | 138 | ); | ||
4664 | 139 | |||
4665 | 140 | auto http_config = http::Request::Configuration::from_uri_as_string( | ||
4666 | 141 | ptr->task_url()); | ||
4667 | 142 | http_config.header = headers; | ||
4668 | 143 | |||
4669 | 144 | std::shared_future<bool> future = prom->get_future(); | ||
4670 | 145 | auto request = client_->streaming_put(http_config, payload, size); | ||
4671 | 146 | request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time}); | ||
4672 | 147 | request->set_timeout(std::chrono::milliseconds{request_timeout_}); | ||
4673 | 148 | request->async_execute(handler, task_handler->on_ready_read()); | ||
4674 | 149 | |||
4675 | 150 | task_handler->attach_request(request, future); | ||
4676 | 151 | } | ||
4677 | 152 | |||
4678 | 153 | void async_put(shared_ptr<T> ptr, | ||
4679 | 154 | const http::Header &headers, | ||
4680 | 155 | std::function<size_t(void *dest, size_t buf_size)> read_cb, | ||
4681 | 156 | std::size_t size) { | ||
4682 | 157 | auto prom = make_shared<promise<bool>>(); | ||
4683 | 158 | |||
4684 | 159 | auto task_handler = ptr->task_handler(); | ||
4685 | 160 | http::Request::Handler handler; | ||
4686 | 161 | handler.on_progress([task_handler](const http::Request::Progress& progress) | ||
4687 | 162 | { | ||
4688 | 163 | if (task_handler->status() == Task::Status::Canceled) { | ||
4689 | 164 | return http::Request::Progress::Next::abort_operation; | ||
4690 | 165 | } | ||
4691 | 166 | |||
4692 | 167 | if (progress.upload.current > 0.0 && progress.upload.total > 0.0) { | ||
4693 | 168 | double percent = (progress.upload.current / progress.upload.total); | ||
4694 | 169 | task_handler->on_progress()(percent); | ||
4695 | 170 | } | ||
4696 | 171 | |||
4697 | 172 | return http::Request::Progress::Next::continue_operation; | ||
4698 | 173 | } | ||
4699 | 174 | ); | ||
4700 | 175 | handler.on_error([prom](const net::Error& e) | ||
4701 | 176 | { | ||
4702 | 177 | prom->set_exception(make_exception_ptr(runtime_error(e.what()))); | ||
4703 | 178 | }); | ||
4704 | 179 | handler.on_response([prom, task_handler](const http::Response& response) | ||
4705 | 180 | { | ||
4706 | 181 | if (response.status != http::Status::ok && | ||
4707 | 182 | response.status != http::Status::created) { | ||
4708 | 183 | prom->set_exception(make_exception_ptr(runtime_error(response.body))); | ||
4709 | 184 | } else { | ||
4710 | 185 | prom->set_value(task_handler->on_finished()(response.body)); | ||
4711 | 186 | } | ||
4712 | 187 | } | ||
4713 | 188 | ); | ||
4714 | 189 | |||
4715 | 190 | auto http_config = http::Request::Configuration::from_uri_as_string( | ||
4716 | 191 | ptr->task_url()); | ||
4717 | 192 | http_config.header = headers; | ||
4718 | 193 | |||
4719 | 194 | std::shared_future<bool> future = prom->get_future(); | ||
4720 | 195 | auto request = client_->streaming_put(http_config, read_cb, size); | ||
4721 | 196 | request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time}); | ||
4722 | 197 | request->set_timeout(std::chrono::milliseconds{request_timeout_}); | ||
4723 | 198 | request->async_execute(handler, task_handler->on_ready_read()); | ||
4724 | 199 | |||
4725 | 200 | task_handler->attach_request(request, future); | ||
4726 | 201 | } | ||
4727 | 202 | |||
4728 | 203 | const int low_speed_limit = 1; | ||
4729 | 204 | |||
4730 | 205 | const chrono::seconds low_speed_time{chrono::seconds{10}}; | ||
4731 | 206 | |||
4732 | 207 | int request_timeout_; | ||
4733 | 208 | |||
4734 | 209 | std::shared_ptr<core::net::http::StreamingClient> client_; | ||
4735 | 210 | |||
4736 | 211 | std::thread worker_; | ||
4737 | 212 | }; | ||
4738 | 213 | |||
4739 | 214 | template<typename T> | ||
4740 | 215 | SyncThread<T>::SyncThread() | ||
4741 | 216 | : client_(std::make_shared<SyncThread::HttpStreamClient>(sync_timeout_ * 500)), | ||
4742 | 217 | stop_(true){ | ||
4743 | 218 | } | ||
4744 | 219 | |||
4745 | 220 | template <typename T> | ||
4746 | 221 | SyncThread<T>::~SyncThread() { | ||
4747 | 222 | stop(); | ||
4748 | 223 | } | ||
4749 | 224 | |||
4750 | 225 | template <typename T> | ||
4751 | 226 | void SyncThread<T>::start() { | ||
4752 | 227 | pause_ = false; | ||
4753 | 228 | |||
4754 | 229 | if (stop_ == true) { | ||
4755 | 230 | stop_ = false; | ||
4756 | 231 | thread_ = std::thread(&SyncThread::run, this); | ||
4757 | 232 | } else { | ||
4758 | 233 | //if it's running, then resume | ||
4759 | 234 | for (auto & item_ptr : task_queue_) { | ||
4760 | 235 | if (item_ptr->status() == Task::Status::Paused) { | ||
4761 | 236 | item_ptr->task_handler()->resume(); | ||
4762 | 237 | } | ||
4763 | 238 | } | ||
4764 | 239 | } | ||
4765 | 240 | } | ||
4766 | 241 | |||
4767 | 242 | template <typename T> | ||
4768 | 243 | void SyncThread<T>::cancel() { | ||
4769 | 244 | stop(); | ||
4770 | 245 | } | ||
4771 | 246 | |||
4772 | 247 | template <typename T> | ||
4773 | 248 | void SyncThread<T>::pause() { | ||
4774 | 249 | std::unique_lock<std::mutex> lock(mutex_); | ||
4775 | 250 | |||
4776 | 251 | //pause task if it's running | ||
4777 | 252 | for (auto & item_ptr : task_queue_) { | ||
4778 | 253 | if (item_ptr->status() == Task::Status::Running) { | ||
4779 | 254 | item_ptr->task_handler()->pause(); | ||
4780 | 255 | } | ||
4781 | 256 | } | ||
4782 | 257 | |||
4783 | 258 | pause_ = true; | ||
4784 | 259 | } | ||
4785 | 260 | |||
4786 | 261 | template <typename T> | ||
4787 | 262 | void SyncThread<T>::stop() { | ||
4788 | 263 | //cancel task if it's running or prepared in the queue. | ||
4789 | 264 | for (auto & item_ptr : task_queue_) { | ||
4790 | 265 | if (item_ptr->status() == Task::Status::Running | ||
4791 | 266 | || item_ptr->status() == Task::Status::Paused | ||
4792 | 267 | || item_ptr->status() == Task::Status::Unstart) { | ||
4793 | 268 | item_ptr->task_handler()->cancel(); | ||
4794 | 269 | } | ||
4795 | 270 | } | ||
4796 | 271 | |||
4797 | 272 | { | ||
4798 | 273 | std::unique_lock<std::mutex> lock(mutex_); | ||
4799 | 274 | if (stop_) | ||
4800 | 275 | return; | ||
4801 | 276 | |||
4802 | 277 | //terminate thread | ||
4803 | 278 | stop_ = true; | ||
4804 | 279 | con_.notify_all(); | ||
4805 | 280 | } | ||
4806 | 281 | |||
4807 | 282 | if (thread_.joinable()) | ||
4808 | 283 | thread_.join(); | ||
4809 | 284 | } | ||
4810 | 285 | |||
4811 | 286 | template <typename T> | ||
4812 | 287 | void SyncThread<T>::set_access_token(const std::string &token) { | ||
4813 | 288 | access_token_ = token; | ||
4814 | 289 | } | ||
4815 | 290 | |||
4816 | 291 | template <typename T> | ||
4817 | 292 | void SyncThread<T>::add_task(std::shared_ptr<T> task_ptr) { | ||
4818 | 293 | task_queue_.push(task_ptr); | ||
4819 | 294 | } | ||
4820 | 295 | |||
4821 | 296 | template <typename T> | ||
4822 | 297 | void SyncThread<T>::run() { | ||
4823 | 298 | std::unique_lock<std::mutex> lock(mutex_); | ||
4824 | 299 | |||
4825 | 300 | std::future_status status = std::future_status::ready; | ||
4826 | 301 | std::shared_ptr<DownloadTaskPriv> task_ptr = nullptr; | ||
4827 | 302 | |||
4828 | 303 | while(!stop_) { | ||
4829 | 304 | con_.wait_for(lock, std::chrono::seconds(sync_timeout_)); | ||
4830 | 305 | if (!stop_ && !pause_) { | ||
4831 | 306 | if (status == std::future_status::ready) { | ||
4832 | 307 | //check if there is unstared task item in task queue | ||
4833 | 308 | typename TaskQueue<std::shared_ptr<T>>::const_iterator it = std::find_if( | ||
4834 | 309 | task_queue_.begin(), | ||
4835 | 310 | task_queue_.end(), | ||
4836 | 311 | [](std::shared_ptr<T> task){ | ||
4837 | 312 | return (task->status() == Task::Status::Unstart); | ||
4838 | 313 | }); | ||
4839 | 314 | |||
4840 | 315 | if (it == task_queue_.end()) | ||
4841 | 316 | continue; | ||
4842 | 317 | |||
4843 | 318 | http::Header header; | ||
4844 | 319 | header.add("Authorization", "bearer " + access_token_); | ||
4845 | 320 | task_ptr = (*it); | ||
4846 | 321 | try { | ||
4847 | 322 | task_ptr->task_handler()->on_prepare()(); | ||
4848 | 323 | } catch (std::runtime_error e) { | ||
4849 | 324 | cerr << "error: " << e.what() << endl; | ||
4850 | 325 | continue; | ||
4851 | 326 | } | ||
4852 | 327 | client_->async_get(task_ptr, header); | ||
4853 | 328 | } | ||
4854 | 329 | |||
4855 | 330 | if (task_ptr) { | ||
4856 | 331 | auto task_handler = task_ptr->task_handler(); | ||
4857 | 332 | //do not wait block here forever until download is finished, | ||
4858 | 333 | //that gives a chance to pause/resume download from sync thread. | ||
4859 | 334 | status = task_handler->wait_for(std::chrono::seconds(sync_timeout_)); | ||
4860 | 335 | try { | ||
4861 | 336 | if (status == std::future_status::ready && | ||
4862 | 337 | task_handler->get_result()) { | ||
4863 | 338 | cout << "download content successfully:" << | ||
4864 | 339 | task_ptr->file_path() << endl; | ||
4865 | 340 | task_handler->detach_request(); | ||
4866 | 341 | task_ptr.reset(); | ||
4867 | 342 | } | ||
4868 | 343 | } catch(std::runtime_error &e) { | ||
4869 | 344 | // if error is caused by net issue,not manually(application callback) | ||
4870 | 345 | // increase broken counter and try it again. Once broken counter exceeds broken limit, | ||
4871 | 346 | // it's regarded as the "broken" one and drop it | ||
4872 | 347 | if (task_handler->status() != Task::Status::Canceled) { | ||
4873 | 348 | if (!task_handler->is_broken()) { | ||
4874 | 349 | task_handler->add_broken_counter(); | ||
4875 | 350 | task_handler->set_status(Task::Status::Unstart); | ||
4876 | 351 | } else { | ||
4877 | 352 | task_ptr->set_error_info(e.what()); | ||
4878 | 353 | task_handler->set_status(Task::Status::Broken); | ||
4879 | 354 | } | ||
4880 | 355 | } | ||
4881 | 356 | |||
4882 | 357 | cerr << "download content: "<< task_ptr->content_name() | ||
4883 | 358 | << " error: " << e.what() << endl; | ||
4884 | 359 | task_ptr.reset(); | ||
4885 | 360 | } | ||
4886 | 361 | } | ||
4887 | 362 | } | ||
4888 | 363 | } | ||
4889 | 364 | } | ||
4890 | 365 | |||
4891 | 366 | namespace onedrive { | ||
4892 | 367 | namespace api { | ||
4893 | 368 | |||
4894 | 369 | template <> | ||
4895 | 370 | void SyncThread<UploadTaskPriv>::run() { | ||
4896 | 371 | std::unique_lock<std::mutex> lock(mutex_); | ||
4897 | 372 | |||
4898 | 373 | std::future_status status = std::future_status::ready; | ||
4899 | 374 | UploadTaskPriv::Ptr task_ptr = nullptr; | ||
4900 | 375 | while(!stop_) { | ||
4901 | 376 | con_.wait_for(lock, std::chrono::seconds(sync_timeout_)); | ||
4902 | 377 | |||
4903 | 378 | if (!stop_ && !pause_) { | ||
4904 | 379 | if (status == std::future_status::ready) { | ||
4905 | 380 | //check if there is unstared task item in task queue | ||
4906 | 381 | typename TaskQueue<UploadTaskPriv::Ptr>::const_iterator it = std::find_if( | ||
4907 | 382 | task_queue_.begin(), | ||
4908 | 383 | task_queue_.end(), | ||
4909 | 384 | [](UploadTaskPriv::Ptr task){ | ||
4910 | 385 | return (task->status() == Task::Status::Unstart); | ||
4911 | 386 | }); | ||
4912 | 387 | |||
4913 | 388 | if (it == task_queue_.end()) | ||
4914 | 389 | continue; | ||
4915 | 390 | |||
4916 | 391 | http::Header header; | ||
4917 | 392 | header.add("Authorization", "bearer " + access_token_); | ||
4918 | 393 | task_ptr = (*it); | ||
4919 | 394 | task_ptr->task_handler()->on_prepare()(); | ||
4920 | 395 | if (task_ptr->buffer_callback()) { | ||
4921 | 396 | client_->async_put(task_ptr, header, task_ptr->buffer_callback(), task_ptr->file_size()); | ||
4922 | 397 | } else { | ||
4923 | 398 | client_->async_put(task_ptr, header, task_ptr->ifstream(), task_ptr->file_size()); | ||
4924 | 399 | } | ||
4925 | 400 | } | ||
4926 | 401 | |||
4927 | 402 | if (task_ptr) { | ||
4928 | 403 | auto task_handler = task_ptr->task_handler(); | ||
4929 | 404 | //do not wait block here forever until upload is finished, | ||
4930 | 405 | //that gives a chance to pause/resume upload from sync thread. | ||
4931 | 406 | status = task_handler->wait_for(std::chrono::seconds(sync_timeout_)); | ||
4932 | 407 | try { | ||
4933 | 408 | if (status == std::future_status::ready && | ||
4934 | 409 | task_handler->get_result()) { | ||
4935 | 410 | cout << "upload content successfully:" << task_ptr->content_name() << endl; | ||
4936 | 411 | task_handler->detach_request(); | ||
4937 | 412 | task_ptr.reset(); | ||
4938 | 413 | } | ||
4939 | 414 | }catch (std::runtime_error &e) { | ||
4940 | 415 | //if content data is fetched chunk by chunk(buffering), set it broken once failed | ||
4941 | 416 | //as we didn't cache buffer locally. | ||
4942 | 417 | if (task_ptr->buffer_callback()) { | ||
4943 | 418 | task_ptr->set_error_info(e.what()); | ||
4944 | 419 | task_handler->set_status(Task::Status::Broken); | ||
4945 | 420 | } else if (task_handler->status() != Task::Status::Canceled) { | ||
4946 | 421 | // if content data is local file, when error is caused by net issue, | ||
4947 | 422 | //increase broken counter and try it again. Once broken counter exceeds broken limit, | ||
4948 | 423 | //it's regarded as the "broken" one and we drop it. | ||
4949 | 424 | |||
4950 | 425 | if (!task_handler->is_broken()) { | ||
4951 | 426 | task_handler->add_broken_counter(); | ||
4952 | 427 | task_handler->set_status(Task::Status::Unstart); | ||
4953 | 428 | } else { | ||
4954 | 429 | task_ptr->set_error_info(e.what()); | ||
4955 | 430 | task_handler->set_status(Task::Status::Broken); | ||
4956 | 431 | } | ||
4957 | 432 | } | ||
4958 | 433 | |||
4959 | 434 | cerr << "upload content: "<< task_ptr->content_name() | ||
4960 | 435 | << " error: " << e.what() << endl; | ||
4961 | 436 | task_ptr.reset(); | ||
4962 | 437 | } | ||
4963 | 438 | } | ||
4964 | 439 | } | ||
4965 | 440 | } | ||
4966 | 441 | } | ||
4967 | 442 | |||
4968 | 443 | } | ||
4969 | 444 | } | ||
4970 | 445 | |||
4971 | 446 | template class SyncThread<DownloadTaskPriv>; | ||
4972 | 447 | template class SyncThread<UploadTaskPriv>; | ||
4973 | 0 | 448 | ||
4974 | === added file 'src/onedrive/api/syncthread.h' | |||
4975 | --- src/onedrive/api/syncthread.h 1970-01-01 00:00:00 +0000 | |||
4976 | +++ src/onedrive/api/syncthread.h 2016-09-30 08:26:58 +0000 | |||
4977 | @@ -0,0 +1,81 @@ | |||
4978 | 1 | /* | ||
4979 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
4980 | 3 | * | ||
4981 | 4 | * This library is free software; you can redistribute it and/or modify it under | ||
4982 | 5 | * the terms of version 3 of the GNU Lesser General Public License as published | ||
4983 | 6 | * by the Free Software Foundation. | ||
4984 | 7 | * | ||
4985 | 8 | * This library is distributed in the hope that it will be useful, but WITHOUT | ||
4986 | 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
4987 | 10 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
4988 | 11 | * details. | ||
4989 | 12 | * | ||
4990 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
4991 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4992 | 15 | * | ||
4993 | 16 | * Author: Gary Wang <gary.wang@canonical.com> | ||
4994 | 17 | */ | ||
4995 | 18 | |||
4996 | 19 | #ifndef ONEDRIVE_API_SYNCTHREAD_H_ | ||
4997 | 20 | #define ONEDRIVE_API_SYNCTHREAD_H_ | ||
4998 | 21 | |||
4999 | 22 | #include <onedrive/api/taskqueue.h> | ||
5000 | 23 | #include <onedrive/api/visibility.h> |
FAILED: Continuous integration, rev:9 /jenkins. canonical. com/unity- api-1/job/ lp-storage- provider- onedrive- ci/1/ /jenkins. canonical. com/unity- api-1/job/ build/804/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/810/ console
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-storage- provider- onedrive- ci/1/rebuild
https:/