PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 1.3.4
JetBackup – Backup, Restore & Migrate v1.3.4
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / com / core / storage / SGDropboxStorage.php
backup / com / core / storage Last commit date
SGDropbox.php 6 years ago SGDropboxStorage.php 6 years ago SGStorage.php 6 years ago
SGDropboxStorage.php
372 lines
1 <?php
2 require_once(SG_STORAGE_PATH.'SGStorage.php');
3
4 use \Dropbox as dbx;
5
6 class SGDropboxStorage extends SGStorage
7 {
8 private $client = null;
9
10 public function init()
11 {
12 //check if curl extension is loaded
13 SGBoot::checkRequirement('curl');
14
15 // Dropbox api 2
16 $this->setActiveDirectory('');
17
18 @set_exception_handler(array('SGDropboxStorage', 'exceptionHandler'));
19 require_once(SG_STORAGE_PATH.'SGDropbox.php');
20 }
21
22 public static function exceptionHandler($exception)
23 {
24 if(SG_ENV_ADAPTER == SG_ENV_WORDPRESS) {
25 wp_die($exception->getMessage());
26 }
27 elseif (SG_ENV_ADAPTER == SG_ENV_MAGENTO) {
28 die($exception->getMessage());
29 }
30 }
31
32 public function connect()
33 {
34 if ($this->isConnected()) {
35 return;
36 }
37
38 $authCode = $this->getAuthCodeFromURL($cancel);
39
40 if ($cancel) {
41 throw new SGExceptionMethodNotAllowed('User did not allow access');
42 }
43
44 $this->auth($authCode);
45 }
46
47 private function auth($authCode = '')
48 {
49 if ($authCode) {
50 try {
51 //exchange authorization code for access token
52 parse_str($_SERVER['QUERY_STRING'], $arr);
53 list($accessToken, $userId, $urlState) = $this->getWebAuth()->finish($arr);
54
55 $this->setAccessToken($accessToken);
56 $accountInfo = $this->getClient()->getAccountInfo();
57 SGConfig::set('SG_DROPBOX_CONNECTION_STRING', $accountInfo['email']);
58
59 $this->connected = true;
60 return;
61 }
62 catch (Exception $ex) {
63 }
64 }
65
66 $refUrl = base64_encode($this->getRefURL());
67 $authorizeUrl = $this->getWebAuth()->start($refUrl);
68 header("Location: $authorizeUrl");
69 exit;
70 }
71
72 public function connectOffline()
73 {
74 if ($this->isConnected()) {
75 return;
76 }
77
78 if (!$this->getClient()) {
79 throw new SGExceptionNotFound('Access token not found');
80 }
81
82 $this->connected = true;
83 }
84
85 public function checkConnected()
86 {
87 $accessToken = $this->getAccessToken();
88 $this->connected = $accessToken?true:false;
89 }
90
91 public function getListOfFiles()
92 {
93 if (!$this->isConnected()) {
94 throw new SGExceptionForbidden('Permission denied. Authentication required.');
95 }
96
97 $listOfFiles = array();
98 $activeDirectory = rtrim($this->getActiveDirectory()).'/';
99 $metaData = $this->getClient()->getMetadataWithChildren($activeDirectory.SGConfig::get('SG_STORAGE_BACKUPS_FOLDER_NAME'));
100
101 foreach($metaData['entries'] as $file) {
102 $size = $file['size'];
103 $date = $this->standardizeFileCreationDate($file['client_modified']);
104 $name = basename($file['path_display']);
105
106 $listOfFiles[$name] = array(
107 'name' => $name,
108 'size' => $size,
109 'date' => $date,
110 'path' => $file['path_display'],
111 );
112 }
113
114 krsort($listOfFiles);
115 return $listOfFiles;
116 }
117
118 public function createFolder($folderName)
119 {
120 if (!$this->isConnected()) {
121 throw new SGExceptionForbidden('Permission denied. Authentication required.');
122 }
123
124 $path = rtrim($this->getActiveDirectory(), '/').'/'.$folderName;
125 $this->getClient()->createFolder($path);
126
127 return $path;
128 }
129
130 private $fd = null;
131 private $filePath = '';
132
133 public function downloadFile($file, $size)
134 {
135 if (!$file) {
136 return false;
137 }
138
139 $this->filePath = SG_BACKUP_DIRECTORY.basename($file);
140 $this->fd = fopen(SG_BACKUP_DIRECTORY.basename($file), "wb");
141
142 $client = $this->getClient();
143
144 $url = "https://content.dropboxapi.com/2/files/download";
145 $params = array (
146 "path" => $file
147 );
148
149 $curl = $client->mkCurl($url);
150 $curl->set(CURLOPT_CUSTOMREQUEST, "POST");
151 $curl->addHeader("Dropbox-API-Arg: ".json_encode($params));
152 $curl->set(CURLOPT_WRITEFUNCTION, array($this, 'callback'));
153
154 $response = $curl->exec();
155
156 fclose($this->fd);
157
158 if ($response->statusCode !== 200) return false;
159
160 return true;
161 }
162
163 public function callback ($ch, $data)
164 {
165 if (!file_exists($this->filePath)) {
166 return -1;
167 }
168
169 fwrite($this->fd, $data);
170 return strlen($data);
171 }
172
173 private function saveStateData($uploadId, $offset)
174 {
175 $token = $this->delegate->getToken();
176 $actionId = $this->delegate->getActionId();
177 $pendingStorageUploads = $this->delegate->getPendingStorageUploads();
178 $currentUploadChunksCount = $this->delegate->getCurrentUploadChunksCount();
179
180 $this->state->setCurrentUploadChunksCount($currentUploadChunksCount);
181 $this->state->setStorageType(SG_STORAGE_DROPBOX);
182 $this->state->setPendingStorageUploads($pendingStorageUploads);
183 $this->state->setToken($token);
184 $this->state->setUploadId($uploadId);
185 $this->state->setOffset($offset);
186 $this->state->setAction(SG_STATE_ACTION_UPLOADING_BACKUP);
187 $this->state->setActiveDirectory($this->getActiveDirectory());
188 $this->state->setActionId($actionId);
189 $this->state->save();
190 }
191
192 public function uploadFile($filePath)
193 {
194 if (!$this->isConnected()) {
195 throw new SGExceptionForbidden('Permission denied. Authentication required.');
196 }
197
198 if (!file_exists($filePath) || !is_readable($filePath)) {
199 throw new SGExceptionNotFound('File does not exist or is not readable: '.$filePath);
200 }
201
202 $client = $this->getClient();
203 $chunkSizeBytes = 2.0 * 1024 * 1024;
204
205 //Note: Because PHP's integer type is signed and many platforms use 32bit integers,
206 //some filesystem functions may return unexpected results for files which are larger than 2GB.
207 $fileSize = backupGuardRealFilesize($filePath);
208
209 $this->delegate->willStartUpload((int)ceil($fileSize/$chunkSizeBytes));
210
211 $handle = fopen($filePath, "rb");
212 $byteOffset = $this->state->getOffset();
213 fseek($handle, $byteOffset);
214
215 if ($this->state->getAction() == SG_STATE_ACTION_PREPARING_STATE_FILE) {
216 $data = fread($handle, $chunkSizeBytes);
217 $uploadId = $client->chunkedUploadStart($data);
218 $byteOffset += strlen($data);
219 }
220 else {
221 $uploadId = $this->state->getUploadId();
222 }
223
224 SGPing::update();
225
226 while ($byteOffset < $fileSize) {
227 $data = fread($handle, $chunkSizeBytes);
228 $client->chunkedUploadContinue($uploadId, $byteOffset, $data);
229 $byteOffset += strlen($data);
230
231 if (!$this->delegate->shouldUploadNextChunk()) {
232 fclose($handle);
233 return;
234 }
235
236 SGPing::update();
237
238 $shouldReload = $this->shouldReload();
239 if ($shouldReload && backupGuardIsReloadEnabled()) {
240 $this->saveStateData($uploadId, $byteOffset);
241 @fclose($handle);
242 $this->reload();
243 }
244 }
245
246 $activeDirectory = $this->getActiveDirectory();
247
248 $path = rtrim($activeDirectory, '/').'/'.basename($filePath);
249
250 $result = $client->chunkedUploadFinish($uploadId, $path, $byteOffset);
251 fclose($handle);
252
253 return $result;
254 }
255
256 public function fileExists($path)
257 {
258 $this->connectOffline();
259 if (!$this->isConnected()) {
260 throw new SGExceptionForbidden('Permission denied. Authentication required.');
261 }
262
263 $client = $this->getClient();
264 try {
265 $result = $client->searchFileNames(dirname($path), basename($path));
266 }
267 catch (Exception $e) {
268 return false;
269 }
270
271 return $result;
272 }
273
274 public function deleteFile($path)
275 {
276 $this->connectOffline();
277 if (!$this->isConnected()) {
278 throw new SGExceptionForbidden('Permission denied. Authentication required.');
279 }
280
281 return $this->getClient()->delete($path);
282 }
283
284 public function deleteFolder($folderName)
285 {
286 return $this->deleteFile($folderName);
287 }
288
289 private function getAppInfo()
290 {
291 $key = SG_STORAGE_DROPBOX_KEY;
292 $secret = SG_STORAGE_DROPBOX_SECRET;
293
294 $appInfo = new dbx\AppInfo($key, $secret);
295 return $appInfo;
296 }
297
298 private function getAccessToken()
299 {
300 return SGConfig::get('SG_DROPBOX_ACCESS_TOKEN');
301 }
302
303 private function setAccessToken($accessToken)
304 {
305 SGConfig::set('SG_DROPBOX_ACCESS_TOKEN', $accessToken, true);
306 }
307
308 private function getClient()
309 {
310 if (!$this->client) {
311 $accessToken = $this->getAccessToken();
312 if (!$accessToken) {
313 return false;
314 }
315
316 $appInfo = $this->getAppInfo();
317 return new dbx\Client($accessToken, SG_STORAGE_DROPBOX_CLIENT_ID, null, $appInfo->getHost());
318 }
319
320 return $this->client;
321 }
322
323 private function getWebAuth()
324 {
325 $appInfo = $this->getAppInfo();
326 $redirectUri = SG_STORAGE_DROPBOX_REDIRECT_URI;
327 $csrfTokenStore = new dbx\ArrayEntryStore($_SESSION, 'dropbox-auth-csrf-token');
328 return new dbx\WebAuth($appInfo, SG_STORAGE_DROPBOX_CLIENT_ID, $redirectUri, $csrfTokenStore, null);
329 }
330
331 private function getCurrentURL()
332 {
333 $http = backupGuardGetCurrentUrlScheme();
334 $url = $http.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
335 return $url;
336 }
337
338 private function getRefURL()
339 {
340 $refUrl = $this->getCurrentURL();
341 if (!$_SERVER['QUERY_STRING']) {
342 $refUrl .= '?';
343 }
344 else {
345 $refUrl .= '&';
346 }
347
348 return $refUrl;
349 }
350
351 private function getAuthCodeFromURL(&$cancel = false)
352 {
353 $query = $_SERVER['QUERY_STRING'];
354 if (!$query) return '';
355
356 $query = explode('&', $query);
357 $code = '';
358 foreach ($query as $q) {
359 $q = explode('=', $q);
360 if ($q[0]=='code') {
361 $code = $q[1];
362 }
363 else if ($q[0]=='cancel' && $q[1]=='1') {
364 $cancel = true;
365 break;
366 }
367 }
368
369 return $code;
370 }
371 }
372