PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 1.4.9
JetBackup – Backup, Restore & Migrate v1.4.9
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
BackupGuardStorage.php 5 years ago SGDropbox.php 5 years ago SGDropboxStorage.php 5 years ago SGStorage.php 5 years ago
SGDropboxStorage.php
380 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, $backupId = null)
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 $progress = $this->delegate->getProgress();
180
181 $this->state->setProgress($progress);
182 $this->state->setCurrentUploadChunksCount($currentUploadChunksCount);
183 $this->state->setStorageType(SG_STORAGE_DROPBOX);
184 $this->state->setPendingStorageUploads($pendingStorageUploads);
185 $this->state->setToken($token);
186 $this->state->setUploadId($uploadId);
187 $this->state->setOffset($offset);
188 $this->state->setAction(SG_STATE_ACTION_UPLOADING_BACKUP);
189 $this->state->setActiveDirectory($this->getActiveDirectory());
190 $this->state->setActionId($actionId);
191 $this->state->save();
192 }
193
194 public function uploadFile($filePath)
195 {
196 if (!$this->isConnected()) {
197 throw new SGExceptionForbidden('Permission denied. Authentication required.');
198 }
199
200 if (!file_exists($filePath) || !is_readable($filePath)) {
201 throw new SGExceptionNotFound('File does not exist or is not readable: '.$filePath);
202 }
203
204 $client = $this->getClient();
205 $chunkSizeBytes = 2.0 * 1024 * 1024;
206
207 //Note: Because PHP's integer type is signed and many platforms use 32bit integers,
208 //some filesystem functions may return unexpected results for files which are larger than 2GB.
209 $fileSize = backupGuardRealFilesize($filePath);
210
211 $this->delegate->willStartUpload((int)ceil($fileSize/$chunkSizeBytes));
212
213 $handle = fopen($filePath, "rb");
214 $byteOffset = $this->state->getOffset();
215 fseek($handle, $byteOffset);
216
217 if ($this->state->getAction() == SG_STATE_ACTION_PREPARING_STATE_FILE) {
218 $data = fread($handle, $chunkSizeBytes);
219 $uploadId = $client->chunkedUploadStart($data);
220 $byteOffset += strlen($data);
221 }
222 else {
223 $uploadId = $this->state->getUploadId();
224 }
225
226 SGPing::update();
227
228 while ($byteOffset < $fileSize) {
229 $data = fread($handle, $chunkSizeBytes);
230 $client->chunkedUploadContinue($uploadId, $byteOffset, $data);
231 $byteOffset += strlen($data);
232
233 if (!$this->delegate->shouldUploadNextChunk()) {
234 fclose($handle);
235 return;
236 }
237
238 SGPing::update();
239
240 $shouldReload = $this->shouldReload();
241 if ($shouldReload && backupGuardIsReloadEnabled()) {
242 $this->saveStateData($uploadId, $byteOffset);
243 @fclose($handle);
244 $this->reload();
245 }
246 }
247
248 $activeDirectory = $this->getActiveDirectory();
249
250 $path = rtrim($activeDirectory, '/').'/'.basename($filePath);
251
252 $result = $client->chunkedUploadFinish($uploadId, $path, $byteOffset);
253 fclose($handle);
254
255 return $result;
256 }
257
258 public function fileExists($path)
259 {
260 $this->connectOffline();
261 if (!$this->isConnected()) {
262 throw new SGExceptionForbidden('Permission denied. Authentication required.');
263 }
264
265 $client = $this->getClient();
266 try {
267 $result = $client->searchFileNames(dirname($path), basename($path));
268 }
269 catch (Exception $e) {
270 return false;
271 }
272
273 return $result;
274 }
275
276 public function deleteFile($path)
277 {
278 $this->connectOffline();
279 if (!$this->isConnected()) {
280 throw new SGExceptionForbidden('Permission denied. Authentication required.');
281 }
282
283 return $this->getClient()->delete($path);
284 }
285
286 public function deleteFolder($folderName)
287 {
288 return $this->deleteFile($folderName);
289 }
290
291 private function getAppInfo()
292 {
293 $key = SG_STORAGE_DROPBOX_KEY;
294 $secret = SG_STORAGE_DROPBOX_SECRET;
295
296 $appInfo = new dbx\AppInfo($key, $secret);
297 return $appInfo;
298 }
299
300 private function getAccessToken()
301 {
302 return SGConfig::get('SG_DROPBOX_ACCESS_TOKEN');
303 }
304
305 private function setAccessToken($accessToken)
306 {
307 SGConfig::set('SG_DROPBOX_ACCESS_TOKEN', $accessToken, true);
308 }
309
310 private function getClient()
311 {
312 if (!$this->client) {
313 $accessToken = $this->getAccessToken();
314 if (!$accessToken) {
315 return false;
316 }
317
318 $appInfo = $this->getAppInfo();
319 return new dbx\Client($accessToken, SG_STORAGE_DROPBOX_CLIENT_ID, null, $appInfo->getHost());
320 }
321
322 return $this->client;
323 }
324
325 private function getWebAuth()
326 {
327 $appInfo = $this->getAppInfo();
328 $redirectUri = SG_STORAGE_DROPBOX_REDIRECT_URI;
329 $savedCSRFToken = SGConfig::get('SG_DROPBOX_CONNECTION_CSRF_TOKEN');
330 if (!empty($savedCSRFToken)) {
331 $_SESSION['dropbox-auth-csrf-token'] = $savedCSRFToken;
332 SGConfig::set('SG_DROPBOX_CONNECTION_CSRF_TOKEN', false);
333 }
334
335 $csrfTokenStore = new dbx\ArrayEntryStore($_SESSION, 'dropbox-auth-csrf-token');
336 return new dbx\WebAuth($appInfo, SG_STORAGE_DROPBOX_CLIENT_ID, $redirectUri, $csrfTokenStore, null);
337 }
338
339 private function getCurrentURL()
340 {
341 $http = backupGuardGetCurrentUrlScheme();
342 $url = $http.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
343 return $url;
344 }
345
346 private function getRefURL()
347 {
348 $refUrl = $this->getCurrentURL();
349 if (!$_SERVER['QUERY_STRING']) {
350 $refUrl .= '?';
351 }
352 else {
353 $refUrl .= '&';
354 }
355
356 return $refUrl;
357 }
358
359 private function getAuthCodeFromURL(&$cancel = false)
360 {
361 $query = $_SERVER['QUERY_STRING'];
362 if (!$query) return '';
363
364 $query = explode('&', $query);
365 $code = '';
366 foreach ($query as $q) {
367 $q = explode('=', $q);
368 if ($q[0]=='code') {
369 $code = $q[1];
370 }
371 else if ($q[0]=='cancel' && $q[1]=='1') {
372 $cancel = true;
373 break;
374 }
375 }
376
377 return $code;
378 }
379 }
380