InfiniteWP Client - Version 1.6.6.3

Version Description

  • Sep 29th 2017 =
  • Fix: v1_retired error while backing up the site to Dropbox
Download this release

Release Info

Developer infinitewp
Plugin Icon 128x128 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

Files changed (3) hide show
  1. init.php +2 -2
  2. lib/Dropbox2/API.php +801 -804
  3. 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.5.1
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.5.1');
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 = 'metadata/' . $this->root . '/' . $this->encodePath($path);
502
- $params = array(
503
- 'file_limit' => ($limit < 1) ? 1 : (($limit > 10000) ? 10000 : (int) $limit),
504
- 'hash' => (is_string($hash)) ? $hash : 0,
505
- 'list' => (int) $list,
506
- 'include_deleted' => (int) $deleted,
507
- 'rev' => (is_string($rev)) ? $rev : null,
508
- );
509
-
510
- return $this->fetch('POST', self::API_URL, $call, $params);
511
- }
512
-
513
- /**
514
- * Not used
515
- * Return "delta entries", intructing you how to update
516
- * your application state to match the server's state
517
- * Important: This method does not make changes to the application state
518
- * @param null|string $cursor Used to keep track of your current state
519
- * @return array Array of delta entries
520
- */
521
- // public function delta($cursor = null) {
522
- // $call = 'delta';
523
- // $params = array('cursor' => $cursor);
524
-
525
- // return $this->fetch('POST', self::API_URL, $call, $params);
526
- // }
527
-
528
- /**
529
- * Not used
530
- * Obtains metadata for the previous revisions of a file
531
- * @param string Path to the file, relative to root
532
- * @param integer Number of revisions to return (1-1000)
533
- * @return array
534
- */
535
- // public function revisions($file, $limit = 10) {
536
- // $call = 'revisions/' . $this->root . '/' . $this->encodePath($file);
537
- // $params = array(
538
- // 'rev_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
539
- // );
540
-
541
- // return $this->fetch('GET', self::API_URL, $call, $params);
542
- // }
543
-
544
- /**
545
- * Not used
546
- * Restores a file path to a previous revision
547
- * @param string $file Path to the file, relative to root
548
- * @param string $revision The revision of the file to restore
549
- * @return object stdClass
550
- */
551
- // public function restore($file, $revision) {
552
- // $call = 'restore/' . $this->root . '/' . $this->encodePath($file);
553
- // $params = array('rev' => $revision);
554
-
555
- // return $this->fetch('POST', self::API_URL, $call, $params);
556
- // }
557
-
558
- /**
559
- * Returns metadata for all files and folders that match the search query
560
- * @param mixed $query The search string. Must be at least 3 characters long
561
- * @param string $path The path to the folder you want to search in
562
- * @param integer $limit Maximum number of results to return (1-1000)
563
- * @param boolean $deleted Include deleted files/folders in the search
564
- * @return array
565
- */
566
- //Not used
567
- // public function search($query, $path = '', $limit = 1000, $deleted = false) {
568
- // $call = 'search/' . $this->root . '/' . $this->encodePath($path);
569
- // $params = array(
570
- // 'query' => $query,
571
- // 'file_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
572
- // 'include_deleted' => (int) $deleted,
573
- // );
574
-
575
- // return $this->fetch('GET', self::API_URL, $call, $params);
576
- // }
577
-
578
- /**
579
- * Not used
580
- * Creates and returns a shareable link to files or folders
581
- * The link returned is for a preview page from which the user an choose to
582
- * download the file if they wish. For direct download links, see media().
583
- * @param string $path The path to the file/folder you want a sharable link to
584
- * @return object stdClass
585
- */
586
- // public function shares($path, $shortUrl = true) {
587
- // $call = 'shares/' . $this->root . '/' . $this->encodePath($path);
588
- // $params = array('short_url' => ($shortUrl) ? 1 : 0);
589
-
590
- // return $this->fetch('POST', self::API_URL, $call, $params);
591
- // }
592
-
593
- /**
594
- * Not used
595
- * Returns a link directly to a file
596
- * @param string $path The path to the media file you want a direct link to
597
- * @return object stdClass
598
- */
599
- // public function media($path) {
600
- // $call = 'media/' . $this->root . '/' . $this->encodePath($path);
601
-
602
- // return $this->fetch('POST', self::API_URL, $call);
603
- // }
604
-
605
- /**
606
- * Not used
607
- * Gets a thumbnail for an image
608
- * @param string $file The path to the image you wish to thumbnail
609
- * @param string $format The thumbnail format, either JPEG or PNG
610
- * @param string $size The size of the thumbnail
611
- * @return array
612
- */
613
- // public function thumbnails($file, $format = 'JPEG', $size = 'small') {
614
- // $format = strtoupper($format);
615
- // // If $format is not 'PNG', default to 'JPEG'
616
- // if ($format != 'PNG') {
617
- // $format = 'JPEG';
618
- // }
619
-
620
- // $size = strtolower($size);
621
- // $sizes = array('s', 'm', 'l', 'xl', 'small', 'medium', 'large');
622
- // // If $size is not valid, default to 'small'
623
- // if (!in_array($size, $sizes)) {
624
- // $size = 'small';
625
- // }
626
-
627
- // $call = 'thumbnails/' . $this->root . '/' . $this->encodePath($file);
628
- // $params = array('format' => $format, 'size' => $size);
629
- // $response = $this->fetch('GET', self::CONTENT_URL, $call, $params);
630
-
631
- // return array(
632
- // 'name' => basename($file),
633
- // 'mime' => $this->getMimeType($response['body']),
634
- // 'meta' => json_decode($response['headers']['x-dropbox-metadata']),
635
- // 'data' => $response['body'],
636
- // );
637
- // }
638
-
639
- /**
640
- * Not used
641
- * Creates and returns a copy_ref to a file
642
- * This reference string can be used to copy that file to another user's
643
- * Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy
644
- * @param $path File for which ref should be created, relative to root
645
- * @return array
646
- */
647
- // public function copyRef($path) {
648
- // $call = 'copy_ref/' . $this->root . '/' . $this->encodePath($path);
649
-
650
- // return $this->fetch('GET', self::API_URL, $call);
651
- // }
652
-
653
- /**
654
- * Not used
655
- * Copies a file or folder to a new location
656
- * @param string $from File or folder to be copied, relative to root
657
- * @param string $to Destination path, relative to root
658
- * @param null|string $fromCopyRef Must be used instead of the from_path
659
- * @return object stdClass
660
- */
661
- // public function copy($from, $to, $fromCopyRef = null) {
662
- // $call = 'fileops/copy';
663
- // $params = array(
664
- // 'root' => $this->root,
665
- // 'from_path' => $this->normalisePath($from),
666
- // 'to_path' => $this->normalisePath($to),
667
- // );
668
-
669
- // if ($fromCopyRef) {
670
- // $params['from_path'] = null;
671
- // $params['from_copy_ref'] = $fromCopyRef;
672
- // }
673
-
674
- // return $this->fetch('POST', self::API_URL, $call, $params);
675
- // }
676
-
677
- /**
678
- * Not used
679
- * Creates a folder
680
- * @param string New folder to create relative to root
681
- * @return object stdClass
682
- */
683
- // public function create($path) {
684
- // $call = 'fileops/create_folder';
685
- // $params = array('root' => $this->root, 'path' => $this->normalisePath($path));
686
-
687
- // return $this->fetch('POST', self::API_URL, $call, $params);
688
- // }
689
-
690
- /**
691
- * Not used
692
- * Deletes a file or folder
693
- * @param string $path The path to the file or folder to be deleted
694
- * @return object stdClass
695
- */
696
- // public function delete($path) {
697
- // $call = '2/files/delete';
698
- // $params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
699
- // $response = $this->fetch('POST', self::API_URL_V2, $call, $params);
700
- // return $response;
701
- // }
702
-
703
- /**
704
- * Not used
705
- * Moves a file or folder to a new location
706
- * @param string $from File or folder to be moved, relative to root
707
- * @param string $to Destination path, relative to root
708
- * @return object stdClass
709
- */
710
- // public function move($from, $to) {
711
- // $call = 'fileops/move';
712
- // $params = array(
713
- // 'root' => $this->root,
714
- // 'from_path' => $this->normalisePath($from),
715
- // 'to_path' => $this->normalisePath($to),
716
- // );
717
-
718
- // return $this->fetch('POST', self::API_URL, $call, $params);
719
- // }
720
-
721
- /**
722
- * Intermediate fetch function
723
- * @param string $method The HTTP method
724
- * @param string $url The API endpoint
725
- * @param string $call The API method to call
726
- * @param array $params Additional parameters
727
- * @return mixed
728
- */
729
- private function fetch($method, $url, $call, array $params = array(), $isChunkDownload = array())
730
- {
731
- // Make the API call via the consumer
732
- $response = $this->OAuth->fetch($method, $url, $call, $params, $isChunkDownload);
733
-
734
- // Format the response and return
735
- switch ($this->responseFormat) {
736
- case 'json':
737
- return json_encode($response);
738
- case 'jsonp':
739
- $response = json_encode($response);
740
- return $this->callback . '(' . $response . ')';
741
- default:
742
- return $response;
743
- }
744
- }
745
-
746
-
747
- /**
748
- * Set the chunk size for chunked uploads
749
- * If $chunkSize is empty, set to 4194304 bytes (4 MB)
750
- * @see \Dropbox\API\chunkedUpload()
751
- */
752
- public function setChunkSize($chunkSize = 4194304) {
753
- if (!is_int($chunkSize)) {
754
- throw new Exception('Expecting chunk size to be an integer, got ' . gettype($chunkSize));
755
- } elseif ($chunkSize > 157286400) {
756
- throw new Exception('Chunk size must not exceed 157286400 bytes, got ' . $chunkSize);
757
- } else {
758
- $this->chunkSize = $chunkSize;
759
- }
760
- }
761
-
762
- /**
763
- * Get the mime type of downloaded file
764
- * If the Fileinfo extension is not loaded, return false
765
- * @param string $data File contents as a string or filename
766
- * @param string $isFilename Is $data a filename?
767
- * @return boolean|string Mime type and encoding of the file
768
- */
769
- private function getMimeType($data, $isFilename = false) {
770
- if (extension_loaded('fileinfo')) {
771
- $finfo = new finfo(FILEINFO_MIME);
772
- if ($isFilename !== false) {
773
- return @$finfo->file($data);
774
- }
775
-
776
- return $finfo->buffer($data);
777
- }
778
-
779
- return false;
780
- }
781
-
782
- /**
783
- * Trim the path of forward slashes and replace
784
- * consecutive forward slashes with a single slash
785
- * then replace backslashes with forward slashes
786
- * @param string $path The path to normalise
787
- * @return string
788
- */
789
- private function normalisePath($path) {
790
- $path = preg_replace('#/+#', '/', trim($path, '/'));
791
- return $path;
792
- }
793
-
794
- /**
795
- * Encode the path, then replace encoded slashes
796
- * with literal forward slash characters
797
- * @param string $path The path to encode
798
- * @return string
799
- */
800
- private function encodePath($path) {
801
- // 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.
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.