Version Description
- Sep 29th 2017 =
- Fix: v1_retired error while backing up the site to Dropbox
Download this release
Release Info
Developer | infinitewp |
Plugin | InfiniteWP Client |
Version | 1.6.6.3 |
Comparing to | |
See all releases |
Code changes from version 1.6.5.1 to 1.6.6.3
- init.php +2 -2
- lib/Dropbox2/API.php +801 -804
- readme.txt +3 -0
init.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: InfiniteWP - Client
|
|
4 |
Plugin URI: http://infinitewp.com/
|
5 |
Description: This is the client plugin of InfiniteWP that communicates with the InfiniteWP Admin panel.
|
6 |
Author: Revmakx
|
7 |
-
Version: 1.6.
|
8 |
Author URI: http://www.revmakx.com
|
9 |
*/
|
10 |
/************************************************************
|
@@ -28,7 +28,7 @@ if(basename($_SERVER['SCRIPT_FILENAME']) == "init.php"):
|
|
28 |
exit;
|
29 |
endif;
|
30 |
if(!defined('IWP_MMB_CLIENT_VERSION'))
|
31 |
-
define('IWP_MMB_CLIENT_VERSION', '1.6.
|
32 |
|
33 |
|
34 |
|
4 |
Plugin URI: http://infinitewp.com/
|
5 |
Description: This is the client plugin of InfiniteWP that communicates with the InfiniteWP Admin panel.
|
6 |
Author: Revmakx
|
7 |
+
Version: 1.6.6.3
|
8 |
Author URI: http://www.revmakx.com
|
9 |
*/
|
10 |
/************************************************************
|
28 |
exit;
|
29 |
endif;
|
30 |
if(!defined('IWP_MMB_CLIENT_VERSION'))
|
31 |
+
define('IWP_MMB_CLIENT_VERSION', '1.6.6.3');
|
32 |
|
33 |
|
34 |
|
lib/Dropbox2/API.php
CHANGED
@@ -1,804 +1,801 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Dropbox API base class
|
5 |
-
* @author Ben Tadiar <ben@handcraftedbyben.co.uk>
|
6 |
-
* @link https://github.com/benthedesigner/dropbox
|
7 |
-
* @link https://www.dropbox.com/developers
|
8 |
-
* @link https://status.dropbox.com Dropbox status
|
9 |
-
* @package Dropbox
|
10 |
-
*/
|
11 |
-
|
12 |
-
class IWP_Dropbox_API {
|
13 |
-
// API Endpoints
|
14 |
-
const API_URL = 'https://api.dropbox.com/1/';
|
15 |
-
const API_URL_V2 = 'https://api.dropboxapi.com/';
|
16 |
-
const CONTENT_URL = 'https://api-content.dropbox.com/1/';
|
17 |
-
const CONTENT_URL_V2 = 'https://content.dropboxapi.com/2/';
|
18 |
-
|
19 |
-
/**
|
20 |
-
* OAuth consumer object
|
21 |
-
* @var null|OAuth\Consumer
|
22 |
-
*/
|
23 |
-
private $OAuth;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* The root level for file paths
|
27 |
-
* Either `dropbox` or `sandbox` (preferred)
|
28 |
-
* @var null|string
|
29 |
-
*/
|
30 |
-
private $root;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Chunk size used for chunked uploads
|
34 |
-
* @see \Dropbox_API::chunkedUpload()
|
35 |
-
*/
|
36 |
-
private $chunkSize = 4194304;
|
37 |
-
|
38 |
-
private $responseFormat = 'php';
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Object to track uploads
|
42 |
-
*/
|
43 |
-
private $tracker;
|
44 |
-
|
45 |
-
private $base;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Set the OAuth consumer object
|
49 |
-
* See 'General Notes' at the link below for information on access type
|
50 |
-
* @link https://www.dropbox.com/developers/reference/api
|
51 |
-
* @param OAuth\Consumer\ConsumerAbstract $OAuth
|
52 |
-
* @param string $root Dropbox app access type
|
53 |
-
*/
|
54 |
-
public function __construct($OAuth, $root = 'dropbox') {
|
55 |
-
$this->OAuth = $OAuth;
|
56 |
-
$this->setRoot($root);
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Set the root level
|
61 |
-
* @param mixed $root
|
62 |
-
* @throws Exception
|
63 |
-
* @return void
|
64 |
-
*/
|
65 |
-
public function setRoot($root) {
|
66 |
-
if ($root !== 'sandbox' && $root !== 'dropbox') {
|
67 |
-
throw new Exception("Expected a root of either 'dropbox' or 'sandbox', got '$root'");
|
68 |
-
} else {
|
69 |
-
$this->root = $root;
|
70 |
-
}
|
71 |
-
}
|
72 |
-
|
73 |
-
/**
|
74 |
-
* Set the tracker
|
75 |
-
* @param Tracker $tracker
|
76 |
-
*/
|
77 |
-
public function setTracker($tracker) {
|
78 |
-
$this->tracker = $tracker;
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Retrieves information about the user's account
|
83 |
-
* @return object stdClass
|
84 |
-
*/
|
85 |
-
public function accountInfo() {
|
86 |
-
//API V1
|
87 |
-
// return $this->fetch('POST', self::API_URL, 'account/info');
|
88 |
-
|
89 |
-
$call = '2/users/get_current_account';
|
90 |
-
$params = array('api_v2' => true);
|
91 |
-
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
92 |
-
return $response;
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Retrieves information about the user's quota
|
97 |
-
* @return object stdClass
|
98 |
-
*/
|
99 |
-
public function quotaInfo() {
|
100 |
-
$call = '2/users/get_space_usage';
|
101 |
-
$params = array('api_v2' => true);
|
102 |
-
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
103 |
-
return $response;
|
104 |
-
}
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Uploads a physical file from disk
|
108 |
-
* Dropbox impose a 150MB limit to files uploaded via the API. If the file
|
109 |
-
* exceeds this limit or does not exist, an Exception will be thrown
|
110 |
-
* @param string $file Absolute path to the file to be uploaded
|
111 |
-
* @param string|bool $filename The destination filename of the uploaded file
|
112 |
-
* @param string $path Path to upload the file to, relative to root
|
113 |
-
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
114 |
-
* @return object stdClass
|
115 |
-
*/
|
116 |
-
public function putFile($file, $path = '', $overwrite = true) {
|
117 |
-
if (!file_exists($file)) {
|
118 |
-
// Throw an Exception if the file does not exist
|
119 |
-
throw new Exception('Local file ' . $file . ' does not exist');
|
120 |
-
}
|
121 |
-
$filesize = iwp_mmb_get_file_size($file);
|
122 |
-
if ($filesize >= 157286400) {
|
123 |
-
$output = $this->chunked_upload_single_call_new($file, $path,$overwrite);
|
124 |
-
return $output;
|
125 |
-
|
126 |
-
}else{
|
127 |
-
$handle = @fopen($file, 'r');
|
128 |
-
//Set the file content to $this->InFile
|
129 |
-
$this->OAuth->setInFile(fread($handle, filesize($file)));
|
130 |
-
fclose($handle);
|
131 |
-
|
132 |
-
$filename = (is_string($filename)) ? $filename : basename($file);
|
133 |
-
$path = '/' . $this->encodePath($path .'/'. $filename);
|
134 |
-
$params = array(
|
135 |
-
'path' => $path,
|
136 |
-
'mute' => true,
|
137 |
-
'mode' => 'overwrite',
|
138 |
-
'api_v2' => true,
|
139 |
-
'content_upload' => true
|
140 |
-
);
|
141 |
-
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload', $params);
|
142 |
-
return $response;
|
143 |
-
}
|
144 |
-
|
145 |
-
}
|
146 |
-
|
147 |
-
public function chunked_upload_single_call_new($file, $path = '',$overwrite=true){
|
148 |
-
$file = str_replace("\\", "/",$file);
|
149 |
-
if (!is_readable($file) or !is_file($file))
|
150 |
-
throw new IWP_DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
|
151 |
-
$file_handle=fopen($file,'r');
|
152 |
-
$uploadID=null;
|
153 |
-
$offset=0;
|
154 |
-
$ProgressFunction=null;
|
155 |
-
while ($data=fread($file_handle, (1024*1024*30))) { //1024*1024*30 = 30MB
|
156 |
-
$firstCommit = (0 == $offset);
|
157 |
-
iwp_mmb_auto_print('dropbox_chucked_upload');
|
158 |
-
$this->OAuth->setInFile($data);
|
159 |
-
|
160 |
-
if ($firstCommit) {
|
161 |
-
$params = array(
|
162 |
-
'close' => false,
|
163 |
-
'api_v2' => true,
|
164 |
-
'content_upload' => true
|
165 |
-
);
|
166 |
-
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
|
167 |
-
$firstCommit = false;
|
168 |
-
|
169 |
-
} else {
|
170 |
-
$params = array(
|
171 |
-
'cursor' => array(
|
172 |
-
'session_id' => $uploadID,
|
173 |
-
// If you send it as a string, Dropbox will be unhappy
|
174 |
-
'offset' => (int)$offset
|
175 |
-
),
|
176 |
-
'api_v2' => true,
|
177 |
-
'content_upload' => true
|
178 |
-
);
|
179 |
-
$response = $this->append_upload($params, false);
|
180 |
-
}
|
181 |
-
|
182 |
-
// On subsequent chunks, use the upload ID returned by the previous request
|
183 |
-
if (isset($response['body']->session_id)) {
|
184 |
-
$uploadID = $response['body']->session_id;
|
185 |
-
}
|
186 |
-
|
187 |
-
/*
|
188 |
-
API v2 no longer returns the offset, we need to manually work this out. So check that there are no errors and update the offset as well as calling the callback method.
|
189 |
-
*/
|
190 |
-
if (!isset($response['body']->error)) {
|
191 |
-
$offset = ftell($file_handle);
|
192 |
-
$output['response']= $response;
|
193 |
-
if($isCommit ==false){
|
194 |
-
|
195 |
-
$output['offset']= $offset;
|
196 |
-
$output['upload_id']= $uploadID;
|
197 |
-
}
|
198 |
-
$this->OAuth->setInFile(null);
|
199 |
-
}
|
200 |
-
fseek($file_handle, $offset);
|
201 |
-
}
|
202 |
-
fclose($file_handle);
|
203 |
-
$filename = (is_string($filename)) ? $filename : basename($file);
|
204 |
-
$params = array(
|
205 |
-
'cursor' => array(
|
206 |
-
'session_id' => $uploadID,
|
207 |
-
'offset' => (int)$offset
|
208 |
-
),
|
209 |
-
'commit' => array(
|
210 |
-
'path' => '/' . $this->encodePath($path .'/'. $filename),
|
211 |
-
'mode' => 'overwrite'
|
212 |
-
),
|
213 |
-
'api_v2' => true,
|
214 |
-
'content_upload' => true
|
215 |
-
);
|
216 |
-
$response = $this->append_upload($params, true);
|
217 |
-
|
218 |
-
return $response;
|
219 |
-
}
|
220 |
-
|
221 |
-
/**
|
222 |
-
* Not used
|
223 |
-
* Uploads file data from a stream
|
224 |
-
* Note: This function is experimental and requires further testing
|
225 |
-
* @todo Add filesize check
|
226 |
-
*@ param resource $stream A readable stream created using fopen()
|
227 |
-
* @param string $filename The destination filename, including path
|
228 |
-
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
229 |
-
* @return array
|
230 |
-
*/
|
231 |
-
// public function putStream($stream, $filename, $overwrite = true) {
|
232 |
-
// $this->OAuth->setInFile($stream);
|
233 |
-
// $path = $this->encodePath($filename);
|
234 |
-
// $call = 'files_put/' . $this->root . '/' . $path;
|
235 |
-
// $params = array('overwrite' => (int) $overwrite);
|
236 |
-
|
237 |
-
// return $this->fetch('PUT', self::CONTENT_URL, $call, $params);
|
238 |
-
// }
|
239 |
-
|
240 |
-
/**
|
241 |
-
* Uploads large files to Dropbox in mulitple chunks
|
242 |
-
* @param string $file Absolute path to the file to be uploaded
|
243 |
-
* @param string|bool $filename The destination filename of the uploaded file
|
244 |
-
* @param string $path Path to upload the file to, relative to root
|
245 |
-
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
246 |
-
* @return stdClass
|
247 |
-
*/
|
248 |
-
public function chunked_upload($file, $path = '', $overwrite = true, $uploadID = null, $offset = 0, $isCommit = false) {
|
249 |
-
$starting_backup_path_time = time();
|
250 |
-
|
251 |
-
$file = str_replace("\\", "/",$file);
|
252 |
-
if (!file_exists($file)) throw new Exception('Local file ' . $file . ' does not exist');
|
253 |
-
|
254 |
-
if (!($handle = @fopen($file, 'r'))) throw new Exception('Could not open ' . $file . ' for reading');
|
255 |
-
|
256 |
-
// Seek to the correct position on the file pointer
|
257 |
-
fseek($handle, $offset);
|
258 |
-
$to_exit = false;
|
259 |
-
|
260 |
-
//Set firstCommit to true so that the upload session start endpoint is called.
|
261 |
-
$firstCommit = (0 == $offset);
|
262 |
-
|
263 |
-
// Read from the file handle until EOF, uploading each chunk
|
264 |
-
if ($data = fread($handle, $this->chunkSize)) {
|
265 |
-
|
266 |
-
// Set the file, request parameters and send the request
|
267 |
-
$this->OAuth->setInFile($data);
|
268 |
-
|
269 |
-
if ($firstCommit) {
|
270 |
-
$params = array(
|
271 |
-
'close' => false,
|
272 |
-
'api_v2' => true,
|
273 |
-
'content_upload' => true
|
274 |
-
);
|
275 |
-
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
|
276 |
-
$firstCommit = false;
|
277 |
-
|
278 |
-
} else {
|
279 |
-
$params = array(
|
280 |
-
'cursor' => array(
|
281 |
-
'session_id' => $uploadID,
|
282 |
-
// If you send it as a string, Dropbox will be unhappy
|
283 |
-
'offset' => (int)$offset
|
284 |
-
),
|
285 |
-
'api_v2' => true,
|
286 |
-
'content_upload' => true
|
287 |
-
);
|
288 |
-
$response = $this->append_upload($params, false);
|
289 |
-
}
|
290 |
-
|
291 |
-
// On subsequent chunks, use the upload ID returned by the previous request
|
292 |
-
if (isset($response['body']->session_id)) {
|
293 |
-
$uploadID = $response['body']->session_id;
|
294 |
-
}
|
295 |
-
|
296 |
-
/*
|
297 |
-
API v2 no longer returns the offset, we need to manually work this out. So check that there are no errors and update the offset as well as calling the callback method.
|
298 |
-
*/
|
299 |
-
if (!isset($response['body']->error)) {
|
300 |
-
$offset = ftell($handle);
|
301 |
-
$output['response']= $response;
|
302 |
-
if($isCommit ==false){
|
303 |
-
|
304 |
-
$output['offset']= $offset;
|
305 |
-
$output['upload_id']= $uploadID;
|
306 |
-
}
|
307 |
-
$this->OAuth->setInFile(null);
|
308 |
-
}
|
309 |
-
|
310 |
-
}
|
311 |
-
// Complete the chunked upload
|
312 |
-
if ($isCommit) {
|
313 |
-
$filename = (is_string($filename)) ? $filename : basename($file);
|
314 |
-
$params = array(
|
315 |
-
'cursor' => array(
|
316 |
-
'session_id' => $uploadID,
|
317 |
-
'offset' => (int)$offset
|
318 |
-
),
|
319 |
-
'commit' => array(
|
320 |
-
'path' => '/' . $this->encodePath($path .'/'. $filename),
|
321 |
-
'mode' => 'overwrite'
|
322 |
-
),
|
323 |
-
'api_v2' => true,
|
324 |
-
'content_upload' => true
|
325 |
-
);
|
326 |
-
$response = $this->append_upload($params, true);
|
327 |
-
$offset = ftell($handle);
|
328 |
-
$output['response']= $response;
|
329 |
-
}
|
330 |
-
|
331 |
-
fclose($handle);
|
332 |
-
return $output;
|
333 |
-
}
|
334 |
-
|
335 |
-
private function append_upload($params, $last_call) {
|
336 |
-
try {
|
337 |
-
if ($last_call){
|
338 |
-
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/finish', $params);
|
339 |
-
} else {
|
340 |
-
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/append_v2', $params);
|
341 |
-
}
|
342 |
-
} catch (Exception $e) {
|
343 |
-
$responseCheck = json_decode($e->getMessage());
|
344 |
-
if (isset($responseCheck) && strpos($responseCheck[0] , 'incorrect_offset') !== false) {
|
345 |
-
$expected_offset = $responseCheck[1];
|
346 |
-
throw new Exception('Submitted input out of alignment: got ['.$params['cursor']['offset'].'] expected ['.$expected_offset.']');
|
347 |
-
//$params['cursor']['offset'] = $responseCheck[1];
|
348 |
-
//$response = $this->append_upload($params, $last_call);
|
349 |
-
} else {
|
350 |
-
throw $e;
|
351 |
-
}
|
352 |
-
}
|
353 |
-
return $response;
|
354 |
-
}
|
355 |
-
|
356 |
-
/**
|
357 |
-
* Downloads a file
|
358 |
-
* Returns the base filename, raw file data and mime type returned by Fileinfo
|
359 |
-
* @param string $file Path to file, relative to root, including path
|
360 |
-
* @param string $outFile Filename to write the downloaded file to
|
361 |
-
* @param string $revision The revision of the file to retrieve
|
362 |
-
* @return array
|
363 |
-
*/
|
364 |
-
public function getFile($file, $outFile = false, $revision = null, $allow_resume = array()) {
|
365 |
-
$handle = null;
|
366 |
-
// $tempFolder = $this->getTempFolderFromOutFile(wp_normalize_path($outFile));
|
367 |
-
if ($outFile !== false) {
|
368 |
-
// Create a file handle if $outFile is specified
|
369 |
-
$this->prepareSetOutFile($outFile, 'w');
|
370 |
-
}
|
371 |
-
|
372 |
-
// $file = $this->encodePath($file);
|
373 |
-
$call = 'files/download';
|
374 |
-
$params = array('path' => '/'.$this->normalisePath($file), 'api_v2' => true, 'content_download' => true);
|
375 |
-
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params);
|
376 |
-
// Close the file handle if one was opened
|
377 |
-
if ($handle) fclose($handle);
|
378 |
-
|
379 |
-
return array(
|
380 |
-
'name' => ($outFile) ? $outFile : basename($file),
|
381 |
-
'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
|
382 |
-
'meta' => json_decode($response['headers']['dropbox-api-result']),
|
383 |
-
'data' => $response['body'],
|
384 |
-
);
|
385 |
-
}
|
386 |
-
|
387 |
-
public function prepareSetOutFile($outFile, $mode) {
|
388 |
-
// $tempFolderFile = $this->getTempFolderFromOutFile(wp_normalize_path($outFile));
|
389 |
-
$tempFolderFile = wp_normalize_path($outFile);
|
390 |
-
|
391 |
-
//setting chmod from filesystem
|
392 |
-
|
393 |
-
if (!$handle = @fopen($tempFolderFile, $mode)) {
|
394 |
-
throw new Exception("Unable to open file handle for $tempFolderFile");
|
395 |
-
} else {
|
396 |
-
$this->OAuth->setOutFile($handle);
|
397 |
-
return $handle;
|
398 |
-
}
|
399 |
-
}
|
400 |
-
|
401 |
-
public function getTempFolderFromOutFile($outFile, $mode = '') {
|
402 |
-
//this function creates the file and its respective folders ; this function also create the exact file path from the DB values
|
403 |
-
$config = WPTC_Factory::get('config');
|
404 |
-
$is_staging_running = $config->get_option('is_staging_running');
|
405 |
-
if($is_staging_running){
|
406 |
-
$site_abspath = $config->get_option('site_abspath');
|
407 |
-
$this_absbath_length = (strlen($site_abspath) - 1);
|
408 |
-
} else{
|
409 |
-
$this_absbath_length = (strlen(ABSPATH) - 1);
|
410 |
-
}
|
411 |
-
|
412 |
-
$this_temp_file = $config->get_option('backup_db_path');
|
413 |
-
$this_temp_file = $config->wp_filesystem_safe_abspath_replace($this_temp_file);
|
414 |
-
$this_temp_file = $this_temp_file. '/tCapsule' . substr($outFile, $this_absbath_length);
|
415 |
-
|
416 |
-
//get the folder name from the full file path
|
417 |
-
$base_file_name = basename($this_temp_file);
|
418 |
-
$base_file_name_pos = strrpos($this_temp_file, $base_file_name);
|
419 |
-
$base_file_name_pos = $base_file_name_pos - 1;
|
420 |
-
$this_temp_folder = substr($this_temp_file, 0, $base_file_name_pos);
|
421 |
-
|
422 |
-
$this_temp_folder = $config->wp_filesystem_safe_abspath_replace($this_temp_folder);
|
423 |
-
|
424 |
-
$this->base->createRecursiveFileSystemFolder($this_temp_folder);
|
425 |
-
return $this_temp_file;
|
426 |
-
}
|
427 |
-
|
428 |
-
/**
|
429 |
-
* Downloads a file
|
430 |
-
* Returns the base filename, raw file data and mime type returned by Fileinfo
|
431 |
-
* @param string $file Path to file, relative to root, including path
|
432 |
-
* @param string $outFile Filename to write the downloaded file to
|
433 |
-
* @param string $revision The revision of the file to retrieve
|
434 |
-
* @return array
|
435 |
-
*/
|
436 |
-
public function chunkedDownload($file, $outFile = false, $revision = null, $isChunkDownload = array(), $meta_file_download = null) {
|
437 |
-
global $start_time_tc;
|
438 |
-
$start_time_tc = time();
|
439 |
-
$handle = null;
|
440 |
-
if ($outFile !== false) {
|
441 |
-
// Create a file handle if $outFile is specified
|
442 |
-
if ($isChunkDownload['c_offset'] == 0) {
|
443 |
-
//while restoring ... first
|
444 |
-
$handle = $this->prepareSetOutFile($outFile, 'w');
|
445 |
-
} else {
|
446 |
-
$handle = $this->prepareSetOutFile($outFile, 'a');
|
447 |
-
}
|
448 |
-
}
|
449 |
-
|
450 |
-
$outFilePath = wp_normalize_path($outFile);
|
451 |
-
$call = 'files/download';
|
452 |
-
$params = array('path' =>'/'.$file, 'api_v2' => true, 'content_download' => true);
|
453 |
-
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params, $isChunkDownload);
|
454 |
-
|
455 |
-
// Set the data offset
|
456 |
-
if ($response) {
|
457 |
-
$offset = filesize($outFilePath);
|
458 |
-
}
|
459 |
-
|
460 |
-
if (empty($meta_file_download)) {
|
461 |
-
if ($this->tracker) {
|
462 |
-
$this->tracker->track_download($outFile, false, $offset, $isChunkDownload);
|
463 |
-
}
|
464 |
-
} else {
|
465 |
-
$this->tracker->track_meta_download($offset, $isChunkDownload);
|
466 |
-
}
|
467 |
-
|
468 |
-
// Close the file handle if one was opened
|
469 |
-
if ($handle) {
|
470 |
-
fclose($handle);
|
471 |
-
}
|
472 |
-
|
473 |
-
$data = array(
|
474 |
-
'name' => ($outFile) ? $outFile : basename($file),
|
475 |
-
'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
|
476 |
-
'meta' => json_decode($response['headers']['dropbox-api-result']),
|
477 |
-
'data' => $response['body'],
|
478 |
-
'chunked' => true,
|
479 |
-
);
|
480 |
-
return $data;
|
481 |
-
}
|
482 |
-
|
483 |
-
public function delete($path) {
|
484 |
-
$call = '2/files/delete';
|
485 |
-
$params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
|
486 |
-
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
487 |
-
return $response;
|
488 |
-
}
|
489 |
-
/**
|
490 |
-
* Not used
|
491 |
-
* Retrieves file and folder metadata
|
492 |
-
* @param string $path The path to the file/folder, relative to root
|
493 |
-
* @param string $rev Return metadata for a specific revision (Default: latest rev)
|
494 |
-
* @param int $limit Maximum number of listings to return
|
495 |
-
* @param string $hash Metadata hash to compare against
|
496 |
-
* @param bool $list Return contents field with response
|
497 |
-
* @param bool $deleted Include files/folders that have been deleted
|
498 |
-
* @return object stdClass
|
499 |
-
*/
|
500 |
-
public function metaData($path = null, $rev = null, $limit = 10000, $hash = false, $list = true, $deleted = false) {
|
501 |
-
$call = '
|
502 |
-
$params = array(
|
503 |
-
'
|
504 |
-
'
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
*
|
515 |
-
*
|
516 |
-
*
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
// $call
|
523 |
-
//
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
*
|
530 |
-
*
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
//
|
536 |
-
//
|
537 |
-
|
538 |
-
//
|
539 |
-
//
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
*
|
546 |
-
*
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
//
|
553 |
-
//
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
*
|
560 |
-
* @param
|
561 |
-
* @
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
//
|
567 |
-
//
|
568 |
-
//
|
569 |
-
//
|
570 |
-
//
|
571 |
-
|
572 |
-
//
|
573 |
-
//
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
*
|
580 |
-
*
|
581 |
-
*
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
//
|
588 |
-
//
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
*
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
//
|
600 |
-
//
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
*
|
607 |
-
*
|
608 |
-
* @
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
//
|
614 |
-
//
|
615 |
-
//
|
616 |
-
|
617 |
-
//
|
618 |
-
//
|
619 |
-
|
620 |
-
// $size
|
621 |
-
//
|
622 |
-
//
|
623 |
-
|
624 |
-
//
|
625 |
-
//
|
626 |
-
|
627 |
-
|
628 |
-
//
|
629 |
-
//
|
630 |
-
|
631 |
-
//
|
632 |
-
// '
|
633 |
-
//
|
634 |
-
//
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
*
|
641 |
-
*
|
642 |
-
*
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
//
|
648 |
-
//
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
*
|
655 |
-
*
|
656 |
-
* @
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
//
|
662 |
-
//
|
663 |
-
//
|
664 |
-
//
|
665 |
-
|
666 |
-
//
|
667 |
-
//
|
668 |
-
|
669 |
-
//
|
670 |
-
|
671 |
-
//
|
672 |
-
//
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
*
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
// $call
|
685 |
-
//
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
*
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
//
|
697 |
-
// $
|
698 |
-
//
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
*
|
705 |
-
*
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
//
|
711 |
-
//
|
712 |
-
//
|
713 |
-
//
|
714 |
-
|
715 |
-
//
|
716 |
-
//
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
*
|
723 |
-
* @param
|
724 |
-
* @
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
//
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
return
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
*
|
764 |
-
*
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
*
|
784 |
-
*
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
*
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
return $this->normalisePath($path);
|
803 |
-
}
|
804 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Dropbox API base class
|
5 |
+
* @author Ben Tadiar <ben@handcraftedbyben.co.uk>
|
6 |
+
* @link https://github.com/benthedesigner/dropbox
|
7 |
+
* @link https://www.dropbox.com/developers
|
8 |
+
* @link https://status.dropbox.com Dropbox status
|
9 |
+
* @package Dropbox
|
10 |
+
*/
|
11 |
+
|
12 |
+
class IWP_Dropbox_API {
|
13 |
+
// API Endpoints
|
14 |
+
const API_URL = 'https://api.dropbox.com/1/';
|
15 |
+
const API_URL_V2 = 'https://api.dropboxapi.com/';
|
16 |
+
const CONTENT_URL = 'https://api-content.dropbox.com/1/';
|
17 |
+
const CONTENT_URL_V2 = 'https://content.dropboxapi.com/2/';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* OAuth consumer object
|
21 |
+
* @var null|OAuth\Consumer
|
22 |
+
*/
|
23 |
+
private $OAuth;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The root level for file paths
|
27 |
+
* Either `dropbox` or `sandbox` (preferred)
|
28 |
+
* @var null|string
|
29 |
+
*/
|
30 |
+
private $root;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Chunk size used for chunked uploads
|
34 |
+
* @see \Dropbox_API::chunkedUpload()
|
35 |
+
*/
|
36 |
+
private $chunkSize = 4194304;
|
37 |
+
|
38 |
+
private $responseFormat = 'php';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Object to track uploads
|
42 |
+
*/
|
43 |
+
private $tracker;
|
44 |
+
|
45 |
+
private $base;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Set the OAuth consumer object
|
49 |
+
* See 'General Notes' at the link below for information on access type
|
50 |
+
* @link https://www.dropbox.com/developers/reference/api
|
51 |
+
* @param OAuth\Consumer\ConsumerAbstract $OAuth
|
52 |
+
* @param string $root Dropbox app access type
|
53 |
+
*/
|
54 |
+
public function __construct($OAuth, $root = 'dropbox') {
|
55 |
+
$this->OAuth = $OAuth;
|
56 |
+
$this->setRoot($root);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Set the root level
|
61 |
+
* @param mixed $root
|
62 |
+
* @throws Exception
|
63 |
+
* @return void
|
64 |
+
*/
|
65 |
+
public function setRoot($root) {
|
66 |
+
if ($root !== 'sandbox' && $root !== 'dropbox') {
|
67 |
+
throw new Exception("Expected a root of either 'dropbox' or 'sandbox', got '$root'");
|
68 |
+
} else {
|
69 |
+
$this->root = $root;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Set the tracker
|
75 |
+
* @param Tracker $tracker
|
76 |
+
*/
|
77 |
+
public function setTracker($tracker) {
|
78 |
+
$this->tracker = $tracker;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Retrieves information about the user's account
|
83 |
+
* @return object stdClass
|
84 |
+
*/
|
85 |
+
public function accountInfo() {
|
86 |
+
//API V1
|
87 |
+
// return $this->fetch('POST', self::API_URL, 'account/info');
|
88 |
+
|
89 |
+
$call = '2/users/get_current_account';
|
90 |
+
$params = array('api_v2' => true);
|
91 |
+
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
92 |
+
return $response;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Retrieves information about the user's quota
|
97 |
+
* @return object stdClass
|
98 |
+
*/
|
99 |
+
public function quotaInfo() {
|
100 |
+
$call = '2/users/get_space_usage';
|
101 |
+
$params = array('api_v2' => true);
|
102 |
+
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
103 |
+
return $response;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Uploads a physical file from disk
|
108 |
+
* Dropbox impose a 150MB limit to files uploaded via the API. If the file
|
109 |
+
* exceeds this limit or does not exist, an Exception will be thrown
|
110 |
+
* @param string $file Absolute path to the file to be uploaded
|
111 |
+
* @param string|bool $filename The destination filename of the uploaded file
|
112 |
+
* @param string $path Path to upload the file to, relative to root
|
113 |
+
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
114 |
+
* @return object stdClass
|
115 |
+
*/
|
116 |
+
public function putFile($file, $path = '', $overwrite = true) {
|
117 |
+
if (!file_exists($file)) {
|
118 |
+
// Throw an Exception if the file does not exist
|
119 |
+
throw new Exception('Local file ' . $file . ' does not exist');
|
120 |
+
}
|
121 |
+
$filesize = iwp_mmb_get_file_size($file);
|
122 |
+
if ($filesize >= 157286400) {
|
123 |
+
$output = $this->chunked_upload_single_call_new($file, $path,$overwrite);
|
124 |
+
return $output;
|
125 |
+
|
126 |
+
}else{
|
127 |
+
$handle = @fopen($file, 'r');
|
128 |
+
//Set the file content to $this->InFile
|
129 |
+
$this->OAuth->setInFile(fread($handle, filesize($file)));
|
130 |
+
fclose($handle);
|
131 |
+
|
132 |
+
$filename = (is_string($filename)) ? $filename : basename($file);
|
133 |
+
$path = '/' . $this->encodePath($path .'/'. $filename);
|
134 |
+
$params = array(
|
135 |
+
'path' => $path,
|
136 |
+
'mute' => true,
|
137 |
+
'mode' => 'overwrite',
|
138 |
+
'api_v2' => true,
|
139 |
+
'content_upload' => true
|
140 |
+
);
|
141 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload', $params);
|
142 |
+
return $response;
|
143 |
+
}
|
144 |
+
|
145 |
+
}
|
146 |
+
|
147 |
+
public function chunked_upload_single_call_new($file, $path = '',$overwrite=true){
|
148 |
+
$file = str_replace("\\", "/",$file);
|
149 |
+
if (!is_readable($file) or !is_file($file))
|
150 |
+
throw new IWP_DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
|
151 |
+
$file_handle=fopen($file,'r');
|
152 |
+
$uploadID=null;
|
153 |
+
$offset=0;
|
154 |
+
$ProgressFunction=null;
|
155 |
+
while ($data=fread($file_handle, (1024*1024*30))) { //1024*1024*30 = 30MB
|
156 |
+
$firstCommit = (0 == $offset);
|
157 |
+
iwp_mmb_auto_print('dropbox_chucked_upload');
|
158 |
+
$this->OAuth->setInFile($data);
|
159 |
+
|
160 |
+
if ($firstCommit) {
|
161 |
+
$params = array(
|
162 |
+
'close' => false,
|
163 |
+
'api_v2' => true,
|
164 |
+
'content_upload' => true
|
165 |
+
);
|
166 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
|
167 |
+
$firstCommit = false;
|
168 |
+
|
169 |
+
} else {
|
170 |
+
$params = array(
|
171 |
+
'cursor' => array(
|
172 |
+
'session_id' => $uploadID,
|
173 |
+
// If you send it as a string, Dropbox will be unhappy
|
174 |
+
'offset' => (int)$offset
|
175 |
+
),
|
176 |
+
'api_v2' => true,
|
177 |
+
'content_upload' => true
|
178 |
+
);
|
179 |
+
$response = $this->append_upload($params, false);
|
180 |
+
}
|
181 |
+
|
182 |
+
// On subsequent chunks, use the upload ID returned by the previous request
|
183 |
+
if (isset($response['body']->session_id)) {
|
184 |
+
$uploadID = $response['body']->session_id;
|
185 |
+
}
|
186 |
+
|
187 |
+
/*
|
188 |
+
API v2 no longer returns the offset, we need to manually work this out. So check that there are no errors and update the offset as well as calling the callback method.
|
189 |
+
*/
|
190 |
+
if (!isset($response['body']->error)) {
|
191 |
+
$offset = ftell($file_handle);
|
192 |
+
$output['response']= $response;
|
193 |
+
if($isCommit ==false){
|
194 |
+
|
195 |
+
$output['offset']= $offset;
|
196 |
+
$output['upload_id']= $uploadID;
|
197 |
+
}
|
198 |
+
$this->OAuth->setInFile(null);
|
199 |
+
}
|
200 |
+
fseek($file_handle, $offset);
|
201 |
+
}
|
202 |
+
fclose($file_handle);
|
203 |
+
$filename = (is_string($filename)) ? $filename : basename($file);
|
204 |
+
$params = array(
|
205 |
+
'cursor' => array(
|
206 |
+
'session_id' => $uploadID,
|
207 |
+
'offset' => (int)$offset
|
208 |
+
),
|
209 |
+
'commit' => array(
|
210 |
+
'path' => '/' . $this->encodePath($path .'/'. $filename),
|
211 |
+
'mode' => 'overwrite'
|
212 |
+
),
|
213 |
+
'api_v2' => true,
|
214 |
+
'content_upload' => true
|
215 |
+
);
|
216 |
+
$response = $this->append_upload($params, true);
|
217 |
+
|
218 |
+
return $response;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Not used
|
223 |
+
* Uploads file data from a stream
|
224 |
+
* Note: This function is experimental and requires further testing
|
225 |
+
* @todo Add filesize check
|
226 |
+
*@ param resource $stream A readable stream created using fopen()
|
227 |
+
* @param string $filename The destination filename, including path
|
228 |
+
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
229 |
+
* @return array
|
230 |
+
*/
|
231 |
+
// public function putStream($stream, $filename, $overwrite = true) {
|
232 |
+
// $this->OAuth->setInFile($stream);
|
233 |
+
// $path = $this->encodePath($filename);
|
234 |
+
// $call = 'files_put/' . $this->root . '/' . $path;
|
235 |
+
// $params = array('overwrite' => (int) $overwrite);
|
236 |
+
|
237 |
+
// return $this->fetch('PUT', self::CONTENT_URL, $call, $params);
|
238 |
+
// }
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Uploads large files to Dropbox in mulitple chunks
|
242 |
+
* @param string $file Absolute path to the file to be uploaded
|
243 |
+
* @param string|bool $filename The destination filename of the uploaded file
|
244 |
+
* @param string $path Path to upload the file to, relative to root
|
245 |
+
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
246 |
+
* @return stdClass
|
247 |
+
*/
|
248 |
+
public function chunked_upload($file, $path = '', $overwrite = true, $uploadID = null, $offset = 0, $isCommit = false) {
|
249 |
+
$starting_backup_path_time = time();
|
250 |
+
|
251 |
+
$file = str_replace("\\", "/",$file);
|
252 |
+
if (!file_exists($file)) throw new Exception('Local file ' . $file . ' does not exist');
|
253 |
+
|
254 |
+
if (!($handle = @fopen($file, 'r'))) throw new Exception('Could not open ' . $file . ' for reading');
|
255 |
+
|
256 |
+
// Seek to the correct position on the file pointer
|
257 |
+
fseek($handle, $offset);
|
258 |
+
$to_exit = false;
|
259 |
+
|
260 |
+
//Set firstCommit to true so that the upload session start endpoint is called.
|
261 |
+
$firstCommit = (0 == $offset);
|
262 |
+
|
263 |
+
// Read from the file handle until EOF, uploading each chunk
|
264 |
+
if ($data = fread($handle, $this->chunkSize)) {
|
265 |
+
|
266 |
+
// Set the file, request parameters and send the request
|
267 |
+
$this->OAuth->setInFile($data);
|
268 |
+
|
269 |
+
if ($firstCommit) {
|
270 |
+
$params = array(
|
271 |
+
'close' => false,
|
272 |
+
'api_v2' => true,
|
273 |
+
'content_upload' => true
|
274 |
+
);
|
275 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
|
276 |
+
$firstCommit = false;
|
277 |
+
|
278 |
+
} else {
|
279 |
+
$params = array(
|
280 |
+
'cursor' => array(
|
281 |
+
'session_id' => $uploadID,
|
282 |
+
// If you send it as a string, Dropbox will be unhappy
|
283 |
+
'offset' => (int)$offset
|
284 |
+
),
|
285 |
+
'api_v2' => true,
|
286 |
+
'content_upload' => true
|
287 |
+
);
|
288 |
+
$response = $this->append_upload($params, false);
|
289 |
+
}
|
290 |
+
|
291 |
+
// On subsequent chunks, use the upload ID returned by the previous request
|
292 |
+
if (isset($response['body']->session_id)) {
|
293 |
+
$uploadID = $response['body']->session_id;
|
294 |
+
}
|
295 |
+
|
296 |
+
/*
|
297 |
+
API v2 no longer returns the offset, we need to manually work this out. So check that there are no errors and update the offset as well as calling the callback method.
|
298 |
+
*/
|
299 |
+
if (!isset($response['body']->error)) {
|
300 |
+
$offset = ftell($handle);
|
301 |
+
$output['response']= $response;
|
302 |
+
if($isCommit ==false){
|
303 |
+
|
304 |
+
$output['offset']= $offset;
|
305 |
+
$output['upload_id']= $uploadID;
|
306 |
+
}
|
307 |
+
$this->OAuth->setInFile(null);
|
308 |
+
}
|
309 |
+
|
310 |
+
}
|
311 |
+
// Complete the chunked upload
|
312 |
+
if ($isCommit) {
|
313 |
+
$filename = (is_string($filename)) ? $filename : basename($file);
|
314 |
+
$params = array(
|
315 |
+
'cursor' => array(
|
316 |
+
'session_id' => $uploadID,
|
317 |
+
'offset' => (int)$offset
|
318 |
+
),
|
319 |
+
'commit' => array(
|
320 |
+
'path' => '/' . $this->encodePath($path .'/'. $filename),
|
321 |
+
'mode' => 'overwrite'
|
322 |
+
),
|
323 |
+
'api_v2' => true,
|
324 |
+
'content_upload' => true
|
325 |
+
);
|
326 |
+
$response = $this->append_upload($params, true);
|
327 |
+
$offset = ftell($handle);
|
328 |
+
$output['response']= $response;
|
329 |
+
}
|
330 |
+
|
331 |
+
fclose($handle);
|
332 |
+
return $output;
|
333 |
+
}
|
334 |
+
|
335 |
+
private function append_upload($params, $last_call) {
|
336 |
+
try {
|
337 |
+
if ($last_call){
|
338 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/finish', $params);
|
339 |
+
} else {
|
340 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/append_v2', $params);
|
341 |
+
}
|
342 |
+
} catch (Exception $e) {
|
343 |
+
$responseCheck = json_decode($e->getMessage());
|
344 |
+
if (isset($responseCheck) && strpos($responseCheck[0] , 'incorrect_offset') !== false) {
|
345 |
+
$expected_offset = $responseCheck[1];
|
346 |
+
throw new Exception('Submitted input out of alignment: got ['.$params['cursor']['offset'].'] expected ['.$expected_offset.']');
|
347 |
+
//$params['cursor']['offset'] = $responseCheck[1];
|
348 |
+
//$response = $this->append_upload($params, $last_call);
|
349 |
+
} else {
|
350 |
+
throw $e;
|
351 |
+
}
|
352 |
+
}
|
353 |
+
return $response;
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Downloads a file
|
358 |
+
* Returns the base filename, raw file data and mime type returned by Fileinfo
|
359 |
+
* @param string $file Path to file, relative to root, including path
|
360 |
+
* @param string $outFile Filename to write the downloaded file to
|
361 |
+
* @param string $revision The revision of the file to retrieve
|
362 |
+
* @return array
|
363 |
+
*/
|
364 |
+
public function getFile($file, $outFile = false, $revision = null, $allow_resume = array()) {
|
365 |
+
$handle = null;
|
366 |
+
// $tempFolder = $this->getTempFolderFromOutFile(wp_normalize_path($outFile));
|
367 |
+
if ($outFile !== false) {
|
368 |
+
// Create a file handle if $outFile is specified
|
369 |
+
$this->prepareSetOutFile($outFile, 'w');
|
370 |
+
}
|
371 |
+
|
372 |
+
// $file = $this->encodePath($file);
|
373 |
+
$call = 'files/download';
|
374 |
+
$params = array('path' => '/'.$this->normalisePath($file), 'api_v2' => true, 'content_download' => true);
|
375 |
+
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params);
|
376 |
+
// Close the file handle if one was opened
|
377 |
+
if ($handle) fclose($handle);
|
378 |
+
|
379 |
+
return array(
|
380 |
+
'name' => ($outFile) ? $outFile : basename($file),
|
381 |
+
'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
|
382 |
+
'meta' => json_decode($response['headers']['dropbox-api-result']),
|
383 |
+
'data' => $response['body'],
|
384 |
+
);
|
385 |
+
}
|
386 |
+
|
387 |
+
public function prepareSetOutFile($outFile, $mode) {
|
388 |
+
// $tempFolderFile = $this->getTempFolderFromOutFile(wp_normalize_path($outFile));
|
389 |
+
$tempFolderFile = wp_normalize_path($outFile);
|
390 |
+
|
391 |
+
//setting chmod from filesystem
|
392 |
+
|
393 |
+
if (!$handle = @fopen($tempFolderFile, $mode)) {
|
394 |
+
throw new Exception("Unable to open file handle for $tempFolderFile");
|
395 |
+
} else {
|
396 |
+
$this->OAuth->setOutFile($handle);
|
397 |
+
return $handle;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
public function getTempFolderFromOutFile($outFile, $mode = '') {
|
402 |
+
//this function creates the file and its respective folders ; this function also create the exact file path from the DB values
|
403 |
+
$config = WPTC_Factory::get('config');
|
404 |
+
$is_staging_running = $config->get_option('is_staging_running');
|
405 |
+
if($is_staging_running){
|
406 |
+
$site_abspath = $config->get_option('site_abspath');
|
407 |
+
$this_absbath_length = (strlen($site_abspath) - 1);
|
408 |
+
} else{
|
409 |
+
$this_absbath_length = (strlen(ABSPATH) - 1);
|
410 |
+
}
|
411 |
+
|
412 |
+
$this_temp_file = $config->get_option('backup_db_path');
|
413 |
+
$this_temp_file = $config->wp_filesystem_safe_abspath_replace($this_temp_file);
|
414 |
+
$this_temp_file = $this_temp_file. '/tCapsule' . substr($outFile, $this_absbath_length);
|
415 |
+
|
416 |
+
//get the folder name from the full file path
|
417 |
+
$base_file_name = basename($this_temp_file);
|
418 |
+
$base_file_name_pos = strrpos($this_temp_file, $base_file_name);
|
419 |
+
$base_file_name_pos = $base_file_name_pos - 1;
|
420 |
+
$this_temp_folder = substr($this_temp_file, 0, $base_file_name_pos);
|
421 |
+
|
422 |
+
$this_temp_folder = $config->wp_filesystem_safe_abspath_replace($this_temp_folder);
|
423 |
+
|
424 |
+
$this->base->createRecursiveFileSystemFolder($this_temp_folder);
|
425 |
+
return $this_temp_file;
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* Downloads a file
|
430 |
+
* Returns the base filename, raw file data and mime type returned by Fileinfo
|
431 |
+
* @param string $file Path to file, relative to root, including path
|
432 |
+
* @param string $outFile Filename to write the downloaded file to
|
433 |
+
* @param string $revision The revision of the file to retrieve
|
434 |
+
* @return array
|
435 |
+
*/
|
436 |
+
public function chunkedDownload($file, $outFile = false, $revision = null, $isChunkDownload = array(), $meta_file_download = null) {
|
437 |
+
global $start_time_tc;
|
438 |
+
$start_time_tc = time();
|
439 |
+
$handle = null;
|
440 |
+
if ($outFile !== false) {
|
441 |
+
// Create a file handle if $outFile is specified
|
442 |
+
if ($isChunkDownload['c_offset'] == 0) {
|
443 |
+
//while restoring ... first
|
444 |
+
$handle = $this->prepareSetOutFile($outFile, 'w');
|
445 |
+
} else {
|
446 |
+
$handle = $this->prepareSetOutFile($outFile, 'a');
|
447 |
+
}
|
448 |
+
}
|
449 |
+
|
450 |
+
$outFilePath = wp_normalize_path($outFile);
|
451 |
+
$call = 'files/download';
|
452 |
+
$params = array('path' =>'/'.$file, 'api_v2' => true, 'content_download' => true);
|
453 |
+
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params, $isChunkDownload);
|
454 |
+
|
455 |
+
// Set the data offset
|
456 |
+
if ($response) {
|
457 |
+
$offset = filesize($outFilePath);
|
458 |
+
}
|
459 |
+
|
460 |
+
if (empty($meta_file_download)) {
|
461 |
+
if ($this->tracker) {
|
462 |
+
$this->tracker->track_download($outFile, false, $offset, $isChunkDownload);
|
463 |
+
}
|
464 |
+
} else {
|
465 |
+
$this->tracker->track_meta_download($offset, $isChunkDownload);
|
466 |
+
}
|
467 |
+
|
468 |
+
// Close the file handle if one was opened
|
469 |
+
if ($handle) {
|
470 |
+
fclose($handle);
|
471 |
+
}
|
472 |
+
|
473 |
+
$data = array(
|
474 |
+
'name' => ($outFile) ? $outFile : basename($file),
|
475 |
+
'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
|
476 |
+
'meta' => json_decode($response['headers']['dropbox-api-result']),
|
477 |
+
'data' => $response['body'],
|
478 |
+
'chunked' => true,
|
479 |
+
);
|
480 |
+
return $data;
|
481 |
+
}
|
482 |
+
|
483 |
+
public function delete($path) {
|
484 |
+
$call = '2/files/delete';
|
485 |
+
$params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
|
486 |
+
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
487 |
+
return $response;
|
488 |
+
}
|
489 |
+
/**
|
490 |
+
* Not used
|
491 |
+
* Retrieves file and folder metadata
|
492 |
+
* @param string $path The path to the file/folder, relative to root
|
493 |
+
* @param string $rev Return metadata for a specific revision (Default: latest rev)
|
494 |
+
* @param int $limit Maximum number of listings to return
|
495 |
+
* @param string $hash Metadata hash to compare against
|
496 |
+
* @param bool $list Return contents field with response
|
497 |
+
* @param bool $deleted Include files/folders that have been deleted
|
498 |
+
* @return object stdClass
|
499 |
+
*/
|
500 |
+
public function metaData($path = null, $rev = null, $limit = 10000, $hash = false, $list = true, $deleted = false) {
|
501 |
+
$call = '2/files/get_metadata' ;
|
502 |
+
$params = array(
|
503 |
+
'path' => '/' . $this->normalisePath($path),
|
504 |
+
'api_v2' => true
|
505 |
+
);
|
506 |
+
|
507 |
+
return $this->fetch('POST', self::API_URL_V2, $call, $params);
|
508 |
+
}
|
509 |
+
|
510 |
+
/**
|
511 |
+
* Not used
|
512 |
+
* Return "delta entries", intructing you how to update
|
513 |
+
* your application state to match the server's state
|
514 |
+
* Important: This method does not make changes to the application state
|
515 |
+
* @param null|string $cursor Used to keep track of your current state
|
516 |
+
* @return array Array of delta entries
|
517 |
+
*/
|
518 |
+
// public function delta($cursor = null) {
|
519 |
+
// $call = 'delta';
|
520 |
+
// $params = array('cursor' => $cursor);
|
521 |
+
|
522 |
+
// return $this->fetch('POST', self::API_URL, $call, $params);
|
523 |
+
// }
|
524 |
+
|
525 |
+
/**
|
526 |
+
* Not used
|
527 |
+
* Obtains metadata for the previous revisions of a file
|
528 |
+
* @param string Path to the file, relative to root
|
529 |
+
* @param integer Number of revisions to return (1-1000)
|
530 |
+
* @return array
|
531 |
+
*/
|
532 |
+
// public function revisions($file, $limit = 10) {
|
533 |
+
// $call = 'revisions/' . $this->root . '/' . $this->encodePath($file);
|
534 |
+
// $params = array(
|
535 |
+
// 'rev_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
|
536 |
+
// );
|
537 |
+
|
538 |
+
// return $this->fetch('GET', self::API_URL, $call, $params);
|
539 |
+
// }
|
540 |
+
|
541 |
+
/**
|
542 |
+
* Not used
|
543 |
+
* Restores a file path to a previous revision
|
544 |
+
* @param string $file Path to the file, relative to root
|
545 |
+
* @param string $revision The revision of the file to restore
|
546 |
+
* @return object stdClass
|
547 |
+
*/
|
548 |
+
// public function restore($file, $revision) {
|
549 |
+
// $call = 'restore/' . $this->root . '/' . $this->encodePath($file);
|
550 |
+
// $params = array('rev' => $revision);
|
551 |
+
|
552 |
+
// return $this->fetch('POST', self::API_URL, $call, $params);
|
553 |
+
// }
|
554 |
+
|
555 |
+
/**
|
556 |
+
* Returns metadata for all files and folders that match the search query
|
557 |
+
* @param mixed $query The search string. Must be at least 3 characters long
|
558 |
+
* @param string $path The path to the folder you want to search in
|
559 |
+
* @param integer $limit Maximum number of results to return (1-1000)
|
560 |
+
* @param boolean $deleted Include deleted files/folders in the search
|
561 |
+
* @return array
|
562 |
+
*/
|
563 |
+
//Not used
|
564 |
+
// public function search($query, $path = '', $limit = 1000, $deleted = false) {
|
565 |
+
// $call = 'search/' . $this->root . '/' . $this->encodePath($path);
|
566 |
+
// $params = array(
|
567 |
+
// 'query' => $query,
|
568 |
+
// 'file_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
|
569 |
+
// 'include_deleted' => (int) $deleted,
|
570 |
+
// );
|
571 |
+
|
572 |
+
// return $this->fetch('GET', self::API_URL, $call, $params);
|
573 |
+
// }
|
574 |
+
|
575 |
+
/**
|
576 |
+
* Not used
|
577 |
+
* Creates and returns a shareable link to files or folders
|
578 |
+
* The link returned is for a preview page from which the user an choose to
|
579 |
+
* download the file if they wish. For direct download links, see media().
|
580 |
+
* @param string $path The path to the file/folder you want a sharable link to
|
581 |
+
* @return object stdClass
|
582 |
+
*/
|
583 |
+
// public function shares($path, $shortUrl = true) {
|
584 |
+
// $call = 'shares/' . $this->root . '/' . $this->encodePath($path);
|
585 |
+
// $params = array('short_url' => ($shortUrl) ? 1 : 0);
|
586 |
+
|
587 |
+
// return $this->fetch('POST', self::API_URL, $call, $params);
|
588 |
+
// }
|
589 |
+
|
590 |
+
/**
|
591 |
+
* Not used
|
592 |
+
* Returns a link directly to a file
|
593 |
+
* @param string $path The path to the media file you want a direct link to
|
594 |
+
* @return object stdClass
|
595 |
+
*/
|
596 |
+
// public function media($path) {
|
597 |
+
// $call = 'media/' . $this->root . '/' . $this->encodePath($path);
|
598 |
+
|
599 |
+
// return $this->fetch('POST', self::API_URL, $call);
|
600 |
+
// }
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Not used
|
604 |
+
* Gets a thumbnail for an image
|
605 |
+
* @param string $file The path to the image you wish to thumbnail
|
606 |
+
* @param string $format The thumbnail format, either JPEG or PNG
|
607 |
+
* @param string $size The size of the thumbnail
|
608 |
+
* @return array
|
609 |
+
*/
|
610 |
+
// public function thumbnails($file, $format = 'JPEG', $size = 'small') {
|
611 |
+
// $format = strtoupper($format);
|
612 |
+
// // If $format is not 'PNG', default to 'JPEG'
|
613 |
+
// if ($format != 'PNG') {
|
614 |
+
// $format = 'JPEG';
|
615 |
+
// }
|
616 |
+
|
617 |
+
// $size = strtolower($size);
|
618 |
+
// $sizes = array('s', 'm', 'l', 'xl', 'small', 'medium', 'large');
|
619 |
+
// // If $size is not valid, default to 'small'
|
620 |
+
// if (!in_array($size, $sizes)) {
|
621 |
+
// $size = 'small';
|
622 |
+
// }
|
623 |
+
|
624 |
+
// $call = 'thumbnails/' . $this->root . '/' . $this->encodePath($file);
|
625 |
+
// $params = array('format' => $format, 'size' => $size);
|
626 |
+
// $response = $this->fetch('GET', self::CONTENT_URL, $call, $params);
|
627 |
+
|
628 |
+
// return array(
|
629 |
+
// 'name' => basename($file),
|
630 |
+
// 'mime' => $this->getMimeType($response['body']),
|
631 |
+
// 'meta' => json_decode($response['headers']['x-dropbox-metadata']),
|
632 |
+
// 'data' => $response['body'],
|
633 |
+
// );
|
634 |
+
// }
|
635 |
+
|
636 |
+
/**
|
637 |
+
* Not used
|
638 |
+
* Creates and returns a copy_ref to a file
|
639 |
+
* This reference string can be used to copy that file to another user's
|
640 |
+
* Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy
|
641 |
+
* @param $path File for which ref should be created, relative to root
|
642 |
+
* @return array
|
643 |
+
*/
|
644 |
+
// public function copyRef($path) {
|
645 |
+
// $call = 'copy_ref/' . $this->root . '/' . $this->encodePath($path);
|
646 |
+
|
647 |
+
// return $this->fetch('GET', self::API_URL, $call);
|
648 |
+
// }
|
649 |
+
|
650 |
+
/**
|
651 |
+
* Not used
|
652 |
+
* Copies a file or folder to a new location
|
653 |
+
* @param string $from File or folder to be copied, relative to root
|
654 |
+
* @param string $to Destination path, relative to root
|
655 |
+
* @param null|string $fromCopyRef Must be used instead of the from_path
|
656 |
+
* @return object stdClass
|
657 |
+
*/
|
658 |
+
// public function copy($from, $to, $fromCopyRef = null) {
|
659 |
+
// $call = 'fileops/copy';
|
660 |
+
// $params = array(
|
661 |
+
// 'root' => $this->root,
|
662 |
+
// 'from_path' => $this->normalisePath($from),
|
663 |
+
// 'to_path' => $this->normalisePath($to),
|
664 |
+
// );
|
665 |
+
|
666 |
+
// if ($fromCopyRef) {
|
667 |
+
// $params['from_path'] = null;
|
668 |
+
// $params['from_copy_ref'] = $fromCopyRef;
|
669 |
+
// }
|
670 |
+
|
671 |
+
// return $this->fetch('POST', self::API_URL, $call, $params);
|
672 |
+
// }
|
673 |
+
|
674 |
+
/**
|
675 |
+
* Not used
|
676 |
+
* Creates a folder
|
677 |
+
* @param string New folder to create relative to root
|
678 |
+
* @return object stdClass
|
679 |
+
*/
|
680 |
+
// public function create($path) {
|
681 |
+
// $call = 'fileops/create_folder';
|
682 |
+
// $params = array('root' => $this->root, 'path' => $this->normalisePath($path));
|
683 |
+
|
684 |
+
// return $this->fetch('POST', self::API_URL, $call, $params);
|
685 |
+
// }
|
686 |
+
|
687 |
+
/**
|
688 |
+
* Not used
|
689 |
+
* Deletes a file or folder
|
690 |
+
* @param string $path The path to the file or folder to be deleted
|
691 |
+
* @return object stdClass
|
692 |
+
*/
|
693 |
+
// public function delete($path) {
|
694 |
+
// $call = '2/files/delete';
|
695 |
+
// $params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
|
696 |
+
// $response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
697 |
+
// return $response;
|
698 |
+
// }
|
699 |
+
|
700 |
+
/**
|
701 |
+
* Not used
|
702 |
+
* Moves a file or folder to a new location
|
703 |
+
* @param string $from File or folder to be moved, relative to root
|
704 |
+
* @param string $to Destination path, relative to root
|
705 |
+
* @return object stdClass
|
706 |
+
*/
|
707 |
+
// public function move($from, $to) {
|
708 |
+
// $call = 'fileops/move';
|
709 |
+
// $params = array(
|
710 |
+
// 'root' => $this->root,
|
711 |
+
// 'from_path' => $this->normalisePath($from),
|
712 |
+
// 'to_path' => $this->normalisePath($to),
|
713 |
+
// );
|
714 |
+
|
715 |
+
// return $this->fetch('POST', self::API_URL, $call, $params);
|
716 |
+
// }
|
717 |
+
|
718 |
+
/**
|
719 |
+
* Intermediate fetch function
|
720 |
+
* @param string $method The HTTP method
|
721 |
+
* @param string $url The API endpoint
|
722 |
+
* @param string $call The API method to call
|
723 |
+
* @param array $params Additional parameters
|
724 |
+
* @return mixed
|
725 |
+
*/
|
726 |
+
private function fetch($method, $url, $call, array $params = array(), $isChunkDownload = array())
|
727 |
+
{
|
728 |
+
// Make the API call via the consumer
|
729 |
+
$response = $this->OAuth->fetch($method, $url, $call, $params, $isChunkDownload);
|
730 |
+
|
731 |
+
// Format the response and return
|
732 |
+
switch ($this->responseFormat) {
|
733 |
+
case 'json':
|
734 |
+
return json_encode($response);
|
735 |
+
case 'jsonp':
|
736 |
+
$response = json_encode($response);
|
737 |
+
return $this->callback . '(' . $response . ')';
|
738 |
+
default:
|
739 |
+
return $response;
|
740 |
+
}
|
741 |
+
}
|
742 |
+
|
743 |
+
|
744 |
+
/**
|
745 |
+
* Set the chunk size for chunked uploads
|
746 |
+
* If $chunkSize is empty, set to 4194304 bytes (4 MB)
|
747 |
+
* @see \Dropbox\API\chunkedUpload()
|
748 |
+
*/
|
749 |
+
public function setChunkSize($chunkSize = 4194304) {
|
750 |
+
if (!is_int($chunkSize)) {
|
751 |
+
throw new Exception('Expecting chunk size to be an integer, got ' . gettype($chunkSize));
|
752 |
+
} elseif ($chunkSize > 157286400) {
|
753 |
+
throw new Exception('Chunk size must not exceed 157286400 bytes, got ' . $chunkSize);
|
754 |
+
} else {
|
755 |
+
$this->chunkSize = $chunkSize;
|
756 |
+
}
|
757 |
+
}
|
758 |
+
|
759 |
+
/**
|
760 |
+
* Get the mime type of downloaded file
|
761 |
+
* If the Fileinfo extension is not loaded, return false
|
762 |
+
* @param string $data File contents as a string or filename
|
763 |
+
* @param string $isFilename Is $data a filename?
|
764 |
+
* @return boolean|string Mime type and encoding of the file
|
765 |
+
*/
|
766 |
+
private function getMimeType($data, $isFilename = false) {
|
767 |
+
if (extension_loaded('fileinfo')) {
|
768 |
+
$finfo = new finfo(FILEINFO_MIME);
|
769 |
+
if ($isFilename !== false) {
|
770 |
+
return @$finfo->file($data);
|
771 |
+
}
|
772 |
+
|
773 |
+
return $finfo->buffer($data);
|
774 |
+
}
|
775 |
+
|
776 |
+
return false;
|
777 |
+
}
|
778 |
+
|
779 |
+
/**
|
780 |
+
* Trim the path of forward slashes and replace
|
781 |
+
* consecutive forward slashes with a single slash
|
782 |
+
* then replace backslashes with forward slashes
|
783 |
+
* @param string $path The path to normalise
|
784 |
+
* @return string
|
785 |
+
*/
|
786 |
+
private function normalisePath($path) {
|
787 |
+
$path = preg_replace('#/+#', '/', trim($path, '/'));
|
788 |
+
return $path;
|
789 |
+
}
|
790 |
+
|
791 |
+
/**
|
792 |
+
* Encode the path, then replace encoded slashes
|
793 |
+
* with literal forward slash characters
|
794 |
+
* @param string $path The path to encode
|
795 |
+
* @return string
|
796 |
+
*/
|
797 |
+
private function encodePath($path) {
|
798 |
+
// in APIv1, encoding was needed because parameters were passed as part of the URL; this is no longer done in our APIv2 SDK; hence, all that we now do here is normalise.
|
799 |
+
return $this->normalisePath($path);
|
800 |
+
}
|
801 |
+
}
|
|
|
|
|
|
readme.txt
CHANGED
@@ -47,6 +47,9 @@ Credits: [Vladimir Prelovac](http://prelovac.com/vladimir) for his worker plugin
|
|
47 |
5. One-click updates
|
48 |
|
49 |
== Changelog ==
|
|
|
|
|
|
|
50 |
= 1.6.5.1 - Sep 9th 2017 =
|
51 |
* Feature: WP Time Capsule support enabled.
|
52 |
* Improvement: Copy Details in client plugin installation has been updated to clipboard.js from flash.
|
47 |
5. One-click updates
|
48 |
|
49 |
== Changelog ==
|
50 |
+
= 1.6.6.3 - Sep 29th 2017 =
|
51 |
+
* Fix: v1_retired error while backing up the site to Dropbox
|
52 |
+
|
53 |
= 1.6.5.1 - Sep 9th 2017 =
|
54 |
* Feature: WP Time Capsule support enabled.
|
55 |
* Improvement: Copy Details in client plugin installation has been updated to clipboard.js from flash.
|