Version Description
- Feb 14th 2022 =
- Feature: Added support for Litespeed Cache.
- Improvement: Ensure phpseclib Crypt_Blowfish is loaded over PEARs version.
- Improvement: Enabled support for new Dropbox OAuth Authentication.
- Fix: Enabled version number for InfiniteWP MU plugin loader.
- Fix: Undefined array key hook_suffix warning.
- Fix: Delete SFTP test backup file on the remote server.
- Fix: PPL addon editor image not uploaded. (issue happening from 1.9.4.9).
- Fix: Fatal error while backing up a 0kb file using the single call method on site installed on site with php8 server.
Download this release
Release Info
Developer | infinitewp |
Plugin | InfiniteWP Client |
Version | 1.9.6 |
Comparing to | |
See all releases |
Code changes from version 1.9.4.11 to 1.9.6
- addons/post_links/post.class.php +7 -3
- addons/wp_optimize/purge-plugins-cache-class.php +29 -0
- backup.class.multicall.php +56 -15
- backup.class.singlecall.php +50 -14
- backup/backup-repo-test.php +36 -8
- backup/backup.core.class.php +77 -9
- backup/backup.upload.php +26 -3
- backup/dropbox.php +19 -8
- core.class.php +2 -0
- init.php +43 -5
- lib/Dropbox2/API.php +335 -315
- lib/Dropbox2/OAuth/Consumer/ConsumerAbstract.php +123 -25
- lib/Dropbox2/OAuth/Consumer/Curl.php +35 -20
- lib/Dropbox2/OAuth/Consumer/WordPress.php +0 -1
- lib/Dropbox2/OAuth/Storage/Encrypter.php +12 -13
- lib/Dropbox2/OAuth/Storage/WordPress.php +9 -7
- lib/sftp.php +2 -0
- pclzip.class.php +4 -0
- plugin.compatibility.class.php +2 -2
- readme.txt +12 -2
addons/post_links/post.class.php
CHANGED
@@ -62,11 +62,16 @@ class IWP_MMB_Post extends IWP_MMB_Core
|
|
62 |
|
63 |
// create dynamic url RegExp
|
64 |
$dot_match_count = 0;
|
65 |
-
$iwp_regexp_url = "";
|
66 |
|
67 |
-
if(
|
|
|
|
|
|
|
|
|
|
|
68 |
$iwp_base_url = parse_url($post_upload_dir['url']);
|
69 |
$iwp_regexp_url = $iwp_base_url['host'] . $iwp_base_url['path'];
|
|
|
70 |
$rep = array(
|
71 |
'/',
|
72 |
'+',
|
@@ -88,7 +93,6 @@ class IWP_MMB_Post extends IWP_MMB_Core
|
|
88 |
$iwp_mmb_dot_url = '..' . $iwp_base_url['path'];
|
89 |
$iwp_mmb_dot_url = str_replace($rep, $with, $iwp_mmb_dot_url);
|
90 |
$dot_match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]*' . $iwp_mmb_dot_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $dot_get_urls, PREG_SET_ORDER);
|
91 |
-
}
|
92 |
|
93 |
|
94 |
if ($dot_match_count > 0) {
|
62 |
|
63 |
// create dynamic url RegExp
|
64 |
$dot_match_count = 0;
|
|
|
65 |
|
66 |
+
if(empty($post_upload_dir)){
|
67 |
+
$iwp_regexp_url = "";
|
68 |
+
$iwp_base_url = array();
|
69 |
+
$iwp_base_url['host'] = '';
|
70 |
+
$iwp_base_url['path'] = '';
|
71 |
+
}else{
|
72 |
$iwp_base_url = parse_url($post_upload_dir['url']);
|
73 |
$iwp_regexp_url = $iwp_base_url['host'] . $iwp_base_url['path'];
|
74 |
+
}
|
75 |
$rep = array(
|
76 |
'/',
|
77 |
'+',
|
93 |
$iwp_mmb_dot_url = '..' . $iwp_base_url['path'];
|
94 |
$iwp_mmb_dot_url = str_replace($rep, $with, $iwp_mmb_dot_url);
|
95 |
$dot_match_count = preg_match_all('/(<a[^>]+href=\"([^"]+)\"[^>]*>)?(<\s*img.[^\/>]*src="([^"]*' . $iwp_mmb_dot_url . '[^\s]+\.(jpg|jpeg|png|gif|bmp))"[^>]*>)/ixu', $post_data['post_content'], $dot_get_urls, PREG_SET_ORDER);
|
|
|
96 |
|
97 |
|
98 |
if ($dot_match_count > 0) {
|
addons/wp_optimize/purge-plugins-cache-class.php
CHANGED
@@ -79,6 +79,17 @@ class IWP_MMB_PURGE_CACHE extends IWP_MMB_Core
|
|
79 |
}
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
if ($text !==''){
|
83 |
$cleanup_values['message'] = $text;
|
84 |
return $cleanup_values;
|
@@ -129,6 +140,15 @@ class IWP_MMB_PURGE_CACHE extends IWP_MMB_Core
|
|
129 |
return false;
|
130 |
}
|
131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
/*
|
133 |
* Public function, Will return the Comet cache plugin is loaded or not
|
134 |
*/
|
@@ -279,6 +299,15 @@ class IWP_MMB_PURGE_CACHE extends IWP_MMB_Core
|
|
279 |
}
|
280 |
}
|
281 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
}
|
283 |
|
284 |
if(class_exists('WpFastestCache')){
|
79 |
}
|
80 |
}
|
81 |
|
82 |
+
if (empty($params) || isset($params['litespeed-cache'])) {
|
83 |
+
$response = $this->deleteAllLiteSpeedCache();
|
84 |
+
if (!empty($response['success'])) {
|
85 |
+
$text .= "<span class='wpm_results_db'> Litespeed Cache"." : " . $response['success'] . "</span><br>";
|
86 |
+
$cleanup_values['value_array']['litespeed-cache'] = $values['value'];
|
87 |
+
}elseif(!empty($response['error'])){
|
88 |
+
$text .= "<span class='wpm_results_db'> Litespeed Cache"." : " . $response['error'] . "</span><br>";
|
89 |
+
$cleanup_values['value_array']['auto_optimize'] = 'Litespeed Cache';
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
if ($text !==''){
|
94 |
$cleanup_values['message'] = $text;
|
95 |
return $cleanup_values;
|
140 |
return false;
|
141 |
}
|
142 |
|
143 |
+
public function checkLiteSpeedCachePlugin() {
|
144 |
+
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
145 |
+
if ( is_plugin_active( 'litespeed-cache/litespeed-cache.php' ) ) {
|
146 |
+
@include_once(WP_PLUGIN_DIR . '/litespeed-cache/litespeed-cache.php');
|
147 |
+
return true;
|
148 |
+
}
|
149 |
+
return false;
|
150 |
+
}
|
151 |
+
|
152 |
/*
|
153 |
* Public function, Will return the Comet cache plugin is loaded or not
|
154 |
*/
|
299 |
}
|
300 |
}
|
301 |
|
302 |
+
public function deleteAllLiteSpeedCache(){
|
303 |
+
if ($this->checkLiteSpeedCachePlugin()) {
|
304 |
+
do_action('litespeed_purge_all');
|
305 |
+
return array('success' => 'Purged all caches successfully');
|
306 |
+
}else {
|
307 |
+
return array('error'=>"Litespeed cache not activated", 'error_code' => 'litespeed_cache_plugin_is_not_activated');
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
}
|
312 |
|
313 |
if(class_exists('WpFastestCache')){
|
backup.class.multicall.php
CHANGED
@@ -284,6 +284,10 @@ class IWP_MMB_Backup_Multicall extends IWP_MMB_Core
|
|
284 |
}
|
285 |
upgradeOldDropBoxBackupList($params['account_info']['iwp_dropbox']);
|
286 |
}
|
|
|
|
|
|
|
|
|
287 |
|
288 |
if(file_exists(IWP_BACKUP_DIR) && is_dir(IWP_BACKUP_DIR)){
|
289 |
$this->statusLog($historyID, array('stage' => 'verification', 'status' => 'processing', 'statusMsg' => 'Directory Writable'));
|
@@ -4523,6 +4527,7 @@ function ftp_backup($historyID,$args = '')
|
|
4523 |
|
4524 |
function remove_ftp_backup($args)
|
4525 |
{
|
|
|
4526 |
extract($args);
|
4527 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
4528 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
@@ -4544,6 +4549,7 @@ function ftp_backup($historyID,$args = '')
|
|
4544 |
'partial' => 1
|
4545 |
);
|
4546 |
}
|
|
|
4547 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
4548 |
return array(
|
4549 |
'error' => 'FTP user name and password invalid',
|
@@ -4598,6 +4604,7 @@ function ftp_backup($historyID,$args = '')
|
|
4598 |
|
4599 |
function get_ftp_backup($args, $current_file_num = 0)
|
4600 |
{
|
|
|
4601 |
extract($args);
|
4602 |
if(isset($use_sftp) && $use_sftp==1) {
|
4603 |
$port = $ftp_port ? $ftp_port : 22; //default port is 22
|
@@ -4617,6 +4624,7 @@ function ftp_backup($historyID,$args = '')
|
|
4617 |
'partial' => 1
|
4618 |
);
|
4619 |
}
|
|
|
4620 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
4621 |
return array(
|
4622 |
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
@@ -4773,14 +4781,31 @@ function ftp_backup($historyID,$args = '')
|
|
4773 |
else
|
4774 |
$dropbox_destination .= '/' . basename($backup_file);
|
4775 |
}else{
|
4776 |
-
|
4777 |
-
|
4778 |
-
|
4779 |
-
|
4780 |
-
|
4781 |
-
|
4782 |
-
|
4783 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4784 |
$oldRoot = 'Apps/InfiniteWP/';
|
4785 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
4786 |
$dropbox_destination = rtrim($dropbox_destination, '/');
|
@@ -4980,14 +5005,30 @@ function ftp_backup($historyID,$args = '')
|
|
4980 |
if ($dropbox_site_folder == true)
|
4981 |
$dropbox_destination .= '/' . $this->site_name;
|
4982 |
}else{
|
4983 |
-
|
4984 |
-
|
4985 |
-
|
4986 |
-
|
|
|
4987 |
|
4988 |
-
|
4989 |
-
|
4990 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4991 |
$oldRoot = 'Apps/InfiniteWP/';
|
4992 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
4993 |
$dropbox_destination = rtrim($dropbox_destination, '/');
|
284 |
}
|
285 |
upgradeOldDropBoxBackupList($params['account_info']['iwp_dropbox']);
|
286 |
}
|
287 |
+
|
288 |
+
if (!empty($params['account_info']['iwp_dropbox'])) {
|
289 |
+
set_iwp_dropbox_auth_setting($params['account_info']['iwp_dropbox']);
|
290 |
+
}
|
291 |
|
292 |
if(file_exists(IWP_BACKUP_DIR) && is_dir(IWP_BACKUP_DIR)){
|
293 |
$this->statusLog($historyID, array('stage' => 'verification', 'status' => 'processing', 'statusMsg' => 'Directory Writable'));
|
4527 |
|
4528 |
function remove_ftp_backup($args)
|
4529 |
{
|
4530 |
+
global $iwp_backup_core;
|
4531 |
extract($args);
|
4532 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
4533 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
4549 |
'partial' => 1
|
4550 |
);
|
4551 |
}
|
4552 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
4553 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
4554 |
return array(
|
4555 |
'error' => 'FTP user name and password invalid',
|
4604 |
|
4605 |
function get_ftp_backup($args, $current_file_num = 0)
|
4606 |
{
|
4607 |
+
global $iwp_backup_core;
|
4608 |
extract($args);
|
4609 |
if(isset($use_sftp) && $use_sftp==1) {
|
4610 |
$port = $ftp_port ? $ftp_port : 22; //default port is 22
|
4624 |
'partial' => 1
|
4625 |
);
|
4626 |
}
|
4627 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
4628 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
4629 |
return array(
|
4630 |
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
4781 |
else
|
4782 |
$dropbox_destination .= '/' . basename($backup_file);
|
4783 |
}else{
|
4784 |
+
|
4785 |
+
if(!isset($dropbox_email) && empty($dropbox_email)){
|
4786 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/API.php';
|
4787 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/Exception.php';
|
4788 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/ConsumerAbstract.php';
|
4789 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/Curl.php';
|
4790 |
+
|
4791 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
4792 |
+
|
4793 |
+
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
4794 |
+
$oauth->setToken($dropbox_access_token);
|
4795 |
+
$dropbox = new IWP_Dropbox_API($oauth);
|
4796 |
+
|
4797 |
+
}else{
|
4798 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
4799 |
+
|
4800 |
+
try{
|
4801 |
+
$helper = new IWP_MMB_UploadModule_dropbox();
|
4802 |
+
$dropbox = $helper->bootstrap();
|
4803 |
+
}
|
4804 |
+
catch(Exception $e){
|
4805 |
+
return $this->statusLog($historyID, array('stage' => 'uploadDropBox', 'status' => 'error', 'statusMsg' => $e->getMessage(), 'statusCode' => 'dropbox_verification_failed_file_may_be_corrupted'));
|
4806 |
+
}
|
4807 |
+
}
|
4808 |
+
|
4809 |
$oldRoot = 'Apps/InfiniteWP/';
|
4810 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
4811 |
$dropbox_destination = rtrim($dropbox_destination, '/');
|
5005 |
if ($dropbox_site_folder == true)
|
5006 |
$dropbox_destination .= '/' . $this->site_name;
|
5007 |
}else{
|
5008 |
+
if(!isset($dropbox_email) && empty($dropbox_email)){
|
5009 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/API.php';
|
5010 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/Exception.php';
|
5011 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/ConsumerAbstract.php';
|
5012 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/Curl.php';
|
5013 |
|
5014 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
5015 |
+
|
5016 |
+
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
5017 |
+
$oauth->setToken($dropbox_access_token);
|
5018 |
+
$dropbox = new IWP_Dropbox_API($oauth);
|
5019 |
+
|
5020 |
+
}else{
|
5021 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
5022 |
+
|
5023 |
+
try{
|
5024 |
+
set_iwp_dropbox_auth_setting($args);
|
5025 |
+
$helper = new IWP_MMB_UploadModule_dropbox();
|
5026 |
+
$dropbox = $helper->bootstrap();
|
5027 |
+
}
|
5028 |
+
catch(Exception $e){
|
5029 |
+
|
5030 |
+
}
|
5031 |
+
}
|
5032 |
$oldRoot = 'Apps/InfiniteWP/';
|
5033 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
5034 |
$dropbox_destination = rtrim($dropbox_destination, '/');
|
backup.class.singlecall.php
CHANGED
@@ -2027,6 +2027,7 @@ function delete_task_now($task_name){
|
|
2027 |
|
2028 |
function ftp_backup($args)
|
2029 |
{
|
|
|
2030 |
extract($args);
|
2031 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
|
2032 |
if(isset($use_sftp) && $use_sftp==1) {
|
@@ -2047,6 +2048,7 @@ function ftp_backup($args)
|
|
2047 |
'partial' => 1
|
2048 |
);
|
2049 |
}
|
|
|
2050 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
2051 |
return array(
|
2052 |
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
@@ -2148,6 +2150,7 @@ function ftp_backup($args)
|
|
2148 |
|
2149 |
function remove_ftp_backup($args)
|
2150 |
{
|
|
|
2151 |
extract($args);
|
2152 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
2153 |
if(isset($use_sftp) && $use_sftp==1) {
|
@@ -2168,6 +2171,7 @@ function ftp_backup($args)
|
|
2168 |
'partial' => 1
|
2169 |
);
|
2170 |
}
|
|
|
2171 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
2172 |
return array(
|
2173 |
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
@@ -2239,14 +2243,30 @@ function ftp_backup($args)
|
|
2239 |
else
|
2240 |
$dropbox_destination .= '/' . basename($backup_file);
|
2241 |
}else{
|
2242 |
-
|
2243 |
-
|
2244 |
-
|
2245 |
-
|
|
|
2246 |
|
2247 |
-
|
2248 |
-
|
2249 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2250 |
$oldRoot = 'Apps/InfiniteWP/';
|
2251 |
$oldVersion = false;
|
2252 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
@@ -2307,14 +2327,30 @@ function ftp_backup($args)
|
|
2307 |
$dropbox_destination .= '/' . $this->site_name;
|
2308 |
$oldVersion = true;
|
2309 |
}else{
|
2310 |
-
|
2311 |
-
|
2312 |
-
|
2313 |
-
|
|
|
2314 |
|
2315 |
-
|
2316 |
-
|
2317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2318 |
$oldRoot = 'Apps/InfiniteWP/';
|
2319 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
2320 |
$dropbox_destination = rtrim($dropbox_destination, '/');
|
2027 |
|
2028 |
function ftp_backup($args)
|
2029 |
{
|
2030 |
+
global $iwp_backup_core;
|
2031 |
extract($args);
|
2032 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
|
2033 |
if(isset($use_sftp) && $use_sftp==1) {
|
2048 |
'partial' => 1
|
2049 |
);
|
2050 |
}
|
2051 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
2052 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
2053 |
return array(
|
2054 |
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
2150 |
|
2151 |
function remove_ftp_backup($args)
|
2152 |
{
|
2153 |
+
global $iwp_backup_core;
|
2154 |
extract($args);
|
2155 |
//Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
|
2156 |
if(isset($use_sftp) && $use_sftp==1) {
|
2171 |
'partial' => 1
|
2172 |
);
|
2173 |
}
|
2174 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
2175 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
2176 |
return array(
|
2177 |
'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
|
2243 |
else
|
2244 |
$dropbox_destination .= '/' . basename($backup_file);
|
2245 |
}else{
|
2246 |
+
if(!isset($dropbox_email) && empty($dropbox_email)){
|
2247 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/API.php';
|
2248 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/Exception.php';
|
2249 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/ConsumerAbstract.php';
|
2250 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/Curl.php';
|
2251 |
|
2252 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
2253 |
+
|
2254 |
+
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
2255 |
+
$oauth->setToken($dropbox_access_token);
|
2256 |
+
$dropbox = new IWP_Dropbox_API($oauth);
|
2257 |
+
|
2258 |
+
}else{
|
2259 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
2260 |
+
|
2261 |
+
try{
|
2262 |
+
set_iwp_dropbox_auth_setting($args);
|
2263 |
+
$helper = new IWP_MMB_UploadModule_dropbox();
|
2264 |
+
$dropbox = $helper->bootstrap();
|
2265 |
+
}
|
2266 |
+
catch(Exception $e){
|
2267 |
+
|
2268 |
+
}
|
2269 |
+
}
|
2270 |
$oldRoot = 'Apps/InfiniteWP/';
|
2271 |
$oldVersion = false;
|
2272 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
2327 |
$dropbox_destination .= '/' . $this->site_name;
|
2328 |
$oldVersion = true;
|
2329 |
}else{
|
2330 |
+
if(!isset($dropbox_email) && empty($dropbox_email)){
|
2331 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/API.php';
|
2332 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/Exception.php';
|
2333 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/ConsumerAbstract.php';
|
2334 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/Curl.php';
|
2335 |
|
2336 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
2337 |
+
|
2338 |
+
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
2339 |
+
$oauth->setToken($dropbox_access_token);
|
2340 |
+
$dropbox = new IWP_Dropbox_API($oauth);
|
2341 |
+
|
2342 |
+
}else{
|
2343 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
2344 |
+
|
2345 |
+
try{
|
2346 |
+
set_iwp_dropbox_auth_setting($args);
|
2347 |
+
$helper = new IWP_MMB_UploadModule_dropbox();
|
2348 |
+
$dropbox = $helper->bootstrap();
|
2349 |
+
}
|
2350 |
+
catch(Exception $e){
|
2351 |
+
|
2352 |
+
}
|
2353 |
+
}
|
2354 |
$oldRoot = 'Apps/InfiniteWP/';
|
2355 |
$dropbox_destination = $oldRoot.ltrim(trim($dropbox_destination), '/');
|
2356 |
$dropbox_destination = rtrim($dropbox_destination, '/');
|
backup/backup-repo-test.php
CHANGED
@@ -143,6 +143,7 @@ class IWP_BACKUP_REPO_TEST {
|
|
143 |
}
|
144 |
|
145 |
public function SFTPTestConnection($args){
|
|
|
146 |
extract($args);
|
147 |
|
148 |
$ftp_hostname = $ftp_hostname ? $ftp_hostname : $hostName;
|
@@ -160,6 +161,8 @@ class IWP_BACKUP_REPO_TEST {
|
|
160 |
'errorMsg' => 'Failed to connect to host',
|
161 |
);
|
162 |
}
|
|
|
|
|
163 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
164 |
return array('status' => 'error',
|
165 |
'errorMsg' => 'Invalid FTP Username and password login ',
|
@@ -188,6 +191,8 @@ class IWP_BACKUP_REPO_TEST {
|
|
188 |
$sftp->chdir($ftp_remote_folder);
|
189 |
$uploadFilePath = IWP_BACKUP_DIR;
|
190 |
$uploadTestFile = $sftp->put(basename($backup_file),$backup_file,NET_SFTP_LOCAL_FILE);
|
|
|
|
|
191 |
@unlink($backup_file);
|
192 |
if ($uploadTestFile === false) {
|
193 |
return array('status' => 'error',
|
@@ -201,25 +206,48 @@ class IWP_BACKUP_REPO_TEST {
|
|
201 |
|
202 |
public function backupRepositoryDropbox($args){
|
203 |
extract($args);
|
204 |
-
|
205 |
-
|
206 |
-
require_once $GLOBALS['iwp_mmb_plugin_dir'].'/lib/Dropbox/
|
207 |
-
require_once $GLOBALS['iwp_mmb_plugin_dir'].'/lib/Dropbox/
|
208 |
-
require_once $GLOBALS['iwp_mmb_plugin_dir'].'/lib/Dropbox/OAuth/Consumer/
|
209 |
-
|
|
|
|
|
210 |
try{
|
211 |
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
212 |
$oauth->setToken($dropbox_access_token);
|
213 |
-
$dropbox = new IWP_Dropbox_API($oauth);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
$oldRoot = 'Apps/InfiniteWP';
|
215 |
$dropbox_destination = $oldRoot.$dropbox_destination;
|
216 |
$response = $dropbox->accountInfo();
|
217 |
-
return array('status' => 'success');
|
218 |
}
|
219 |
catch(Exception $e){
|
220 |
return array('error' => $e->getMessage(), 'error_code' => 'dropbox_test_failed');
|
221 |
}
|
222 |
}
|
|
|
223 |
return array('error' => 'Consumer Secret not available', 'error_code' => 'consumer_secret_not_available');
|
224 |
}
|
225 |
|
143 |
}
|
144 |
|
145 |
public function SFTPTestConnection($args){
|
146 |
+
global $iwp_backup_core;
|
147 |
extract($args);
|
148 |
|
149 |
$ftp_hostname = $ftp_hostname ? $ftp_hostname : $hostName;
|
161 |
'errorMsg' => 'Failed to connect to host',
|
162 |
);
|
163 |
}
|
164 |
+
// Ensure phpseclib Crypt_Blowfish is loaded, over PEAR's
|
165 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
166 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
167 |
return array('status' => 'error',
|
168 |
'errorMsg' => 'Invalid FTP Username and password login ',
|
191 |
$sftp->chdir($ftp_remote_folder);
|
192 |
$uploadFilePath = IWP_BACKUP_DIR;
|
193 |
$uploadTestFile = $sftp->put(basename($backup_file),$backup_file,NET_SFTP_LOCAL_FILE);
|
194 |
+
$remote_test_file = rtrim($ftp_remote_folder, '/') . '/' . basename($backup_file);
|
195 |
+
$sftp->delete($remote_test_file);
|
196 |
@unlink($backup_file);
|
197 |
if ($uploadTestFile === false) {
|
198 |
return array('status' => 'error',
|
206 |
|
207 |
public function backupRepositoryDropbox($args){
|
208 |
extract($args);
|
209 |
+
$dropbox = null;
|
210 |
+
if(!isset($dropbox_email) && empty($dropbox_email) && isset($dropbox_access_token) && !empty($dropbox_access_token)){
|
211 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/API.php';
|
212 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/Exception.php';
|
213 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/ConsumerAbstract.php';
|
214 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/Curl.php';
|
215 |
+
|
216 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
217 |
try{
|
218 |
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
219 |
$oauth->setToken($dropbox_access_token);
|
220 |
+
$dropbox = new IWP_Dropbox_API($oauth);
|
221 |
+
}
|
222 |
+
catch(Exception $e){
|
223 |
+
return array('error' => $e->getMessage(), 'error_code' => 'dropbox_test_failed');
|
224 |
+
}
|
225 |
+
|
226 |
+
}elseif( isset($dropbox_email) && !empty($dropbox_email) ){
|
227 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
228 |
+
|
229 |
+
try{
|
230 |
+
set_iwp_dropbox_auth_setting($args);
|
231 |
+
$helper = new IWP_MMB_UploadModule_dropbox();
|
232 |
+
$dropbox = $helper->bootstrap();
|
233 |
+
}
|
234 |
+
catch(Exception $e){
|
235 |
+
return array('error' => $e->getMessage(), 'error_code' => 'dropbox_test_failed');
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
if (!is_null($dropbox)) {
|
240 |
+
try{
|
241 |
$oldRoot = 'Apps/InfiniteWP';
|
242 |
$dropbox_destination = $oldRoot.$dropbox_destination;
|
243 |
$response = $dropbox->accountInfo();
|
244 |
+
return array('status' => 'success');
|
245 |
}
|
246 |
catch(Exception $e){
|
247 |
return array('error' => $e->getMessage(), 'error_code' => 'dropbox_test_failed');
|
248 |
}
|
249 |
}
|
250 |
+
|
251 |
return array('error' => 'Consumer Secret not available', 'error_code' => 'consumer_secret_not_available');
|
252 |
}
|
253 |
|
backup/backup.core.class.php
CHANGED
@@ -3738,7 +3738,7 @@ CREATE TABLE $wpdb->signups (
|
|
3738 |
|
3739 |
}
|
3740 |
|
3741 |
-
public function
|
3742 |
|
3743 |
$this->no_deprecation_warnings_on_php7();
|
3744 |
|
@@ -3761,6 +3761,43 @@ CREATE TABLE $wpdb->signups (
|
|
3761 |
}
|
3762 |
}
|
3763 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3764 |
public function fetch_log($backup_nonce = '', $log_pointer = 0, $output_format = 'html') {
|
3765 |
global $iwp_backup_core;
|
3766 |
|
@@ -3996,6 +4033,9 @@ CREATE TABLE $wpdb->signups (
|
|
3996 |
'CSRF' => '',
|
3997 |
'dropbox_site_folder' => $dropbox_details['dropbox_site_folder']
|
3998 |
);
|
|
|
|
|
|
|
3999 |
IWP_MMB_Backup_Options::update_iwp_backup_option('IWP_dropbox', $opts);
|
4000 |
}elseif (!empty($params['account_info']['iwp_gdrive'])) {
|
4001 |
update_option('IWP_service', 'googledrive');
|
@@ -4424,16 +4464,33 @@ CREATE TABLE $wpdb->signups (
|
|
4424 |
}
|
4425 |
|
4426 |
public function createCloudInstance($type, $args){
|
|
|
4427 |
if ($type == 'dropbox') {
|
4428 |
extract($args['iwp_dropbox']);
|
4429 |
-
|
4430 |
-
|
4431 |
-
|
4432 |
-
|
|
|
4433 |
|
4434 |
-
|
4435 |
-
|
4436 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4437 |
return $dropbox;
|
4438 |
}elseif ($type == 'ftp') {
|
4439 |
extract($args['iwp_ftp']);
|
@@ -4451,6 +4508,7 @@ CREATE TABLE $wpdb->signups (
|
|
4451 |
if(!$sftp) {
|
4452 |
return false;
|
4453 |
}
|
|
|
4454 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
4455 |
return false;
|
4456 |
} else {
|
@@ -4696,6 +4754,13 @@ CREATE TABLE $wpdb->signups (
|
|
4696 |
}
|
4697 |
}
|
4698 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4699 |
}
|
4700 |
|
4701 |
$files_to_delete = array();
|
@@ -4752,7 +4817,7 @@ CREATE TABLE $wpdb->signups (
|
|
4752 |
|
4753 |
foreach ($instance_settings as $instance_id => $options) {
|
4754 |
|
4755 |
-
$remote_obj->set_options($
|
4756 |
|
4757 |
foreach ($files as $index => $file) {
|
4758 |
if ($remote_deleted == $remote_delete_limit) {
|
@@ -4987,6 +5052,9 @@ CREATE TABLE $wpdb->signups (
|
|
4987 |
'CSRF' => '',
|
4988 |
'dropbox_site_folder' => $dropbox_details['dropbox_site_folder']
|
4989 |
);
|
|
|
|
|
|
|
4990 |
IWP_MMB_Backup_Options::update_iwp_backup_option('IWP_dropbox', $opts);
|
4991 |
}elseif (!empty($params['account_info']['iwp_gdrive'])) {
|
4992 |
$google_details = $params['account_info']['iwp_gdrive'];
|
3738 |
|
3739 |
}
|
3740 |
|
3741 |
+
public function ensure_phpseclib_old($classes = false, $class_paths = false) {
|
3742 |
|
3743 |
$this->no_deprecation_warnings_on_php7();
|
3744 |
|
3761 |
}
|
3762 |
}
|
3763 |
|
3764 |
+
public function ensure_phpseclib($classes = array()) {
|
3765 |
+
|
3766 |
+
$classes = (array) $classes;
|
3767 |
+
|
3768 |
+
$this->no_deprecation_warnings_on_php7();
|
3769 |
+
|
3770 |
+
$any_missing = false;
|
3771 |
+
|
3772 |
+
foreach ($classes as $cl) {
|
3773 |
+
if (!class_exists($cl)) $any_missing = true;
|
3774 |
+
}
|
3775 |
+
|
3776 |
+
if (!$any_missing) return true;
|
3777 |
+
|
3778 |
+
$ret = true;
|
3779 |
+
|
3780 |
+
// From phpseclib/phpseclib/phpseclib/bootstrap.php - we nullify it there, but log here instead
|
3781 |
+
if (extension_loaded('mbstring')) {
|
3782 |
+
// 2 - MB_OVERLOAD_STRING
|
3783 |
+
// @codingStandardsIgnoreLine
|
3784 |
+
if (ini_get('mbstring.func_overload') & 2) {
|
3785 |
+
// We go on to try anyway, in case the caller wasn't using an affected part of phpseclib
|
3786 |
+
// @codingStandardsIgnoreLine
|
3787 |
+
$ret = new WP_Error('mbstring_func_overload', 'Overloading of string functions using mbstring.func_overload is not supported by phpseclib.');
|
3788 |
+
}
|
3789 |
+
}
|
3790 |
+
|
3791 |
+
$phpseclib_dir = $GLOBALS['iwp_mmb_plugin_dir'].'/lib/phpseclib/phpseclib/phpseclib';
|
3792 |
+
if (false === strpos(get_include_path(), $phpseclib_dir)) set_include_path(get_include_path().PATH_SEPARATOR.$phpseclib_dir);
|
3793 |
+
foreach ($classes as $cl) {
|
3794 |
+
$path = str_replace('_', '/', $cl);
|
3795 |
+
if (!class_exists($cl)) include_once($phpseclib_dir.'/'.$path.'.php');
|
3796 |
+
}
|
3797 |
+
|
3798 |
+
return $ret;
|
3799 |
+
}
|
3800 |
+
|
3801 |
public function fetch_log($backup_nonce = '', $log_pointer = 0, $output_format = 'html') {
|
3802 |
global $iwp_backup_core;
|
3803 |
|
4033 |
'CSRF' => '',
|
4034 |
'dropbox_site_folder' => $dropbox_details['dropbox_site_folder']
|
4035 |
);
|
4036 |
+
if ( !empty($dropbox_details['dropbox_email']) ) {
|
4037 |
+
$opts['email'] = $dropbox_details['dropbox_email'];
|
4038 |
+
}
|
4039 |
IWP_MMB_Backup_Options::update_iwp_backup_option('IWP_dropbox', $opts);
|
4040 |
}elseif (!empty($params['account_info']['iwp_gdrive'])) {
|
4041 |
update_option('IWP_service', 'googledrive');
|
4464 |
}
|
4465 |
|
4466 |
public function createCloudInstance($type, $args){
|
4467 |
+
global $iwp_backup_core;
|
4468 |
if ($type == 'dropbox') {
|
4469 |
extract($args['iwp_dropbox']);
|
4470 |
+
if(!isset($dropbox_email) && empty($dropbox_email)){
|
4471 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/API.php';
|
4472 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/Exception.php';
|
4473 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/ConsumerAbstract.php';
|
4474 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/lib/Dropbox/OAuth/Consumer/Curl.php';
|
4475 |
|
4476 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
4477 |
+
|
4478 |
+
$oauth = new IWP_Dropbox_OAuth_Consumer_Curl($dropbox_app_key, $dropbox_app_secure_key);
|
4479 |
+
$oauth->setToken($dropbox_access_token);
|
4480 |
+
$dropbox = new IWP_Dropbox_API($oauth);
|
4481 |
+
|
4482 |
+
}else{
|
4483 |
+
require_once $GLOBALS['iwp_mmb_plugin_dir'] . '/backup/dropbox.php';
|
4484 |
+
|
4485 |
+
try{
|
4486 |
+
set_iwp_dropbox_auth_setting($args['iwp_dropbox']);
|
4487 |
+
$helper = new IWP_MMB_UploadModule_dropbox();
|
4488 |
+
$dropbox = $helper->bootstrap();
|
4489 |
+
}
|
4490 |
+
catch(Exception $e){
|
4491 |
+
return false;
|
4492 |
+
}
|
4493 |
+
}
|
4494 |
return $dropbox;
|
4495 |
}elseif ($type == 'ftp') {
|
4496 |
extract($args['iwp_ftp']);
|
4508 |
if(!$sftp) {
|
4509 |
return false;
|
4510 |
}
|
4511 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
4512 |
if (!$sftp->login($ftp_username, $ftp_password)) {
|
4513 |
return false;
|
4514 |
} else {
|
4754 |
}
|
4755 |
}
|
4756 |
}
|
4757 |
+
|
4758 |
+
if (isset($backups[$timestamp]['service_setting'])) {
|
4759 |
+
$service_setting = $backups[$timestamp]['service_setting'];
|
4760 |
+
if (isset($service_setting['dropbox_site_folder'])) {
|
4761 |
+
set_iwp_dropbox_auth_setting($service_setting);
|
4762 |
+
}
|
4763 |
+
}
|
4764 |
}
|
4765 |
|
4766 |
$files_to_delete = array();
|
4817 |
|
4818 |
foreach ($instance_settings as $instance_id => $options) {
|
4819 |
|
4820 |
+
$remote_obj->set_options($service_setting, false, $instance_id);
|
4821 |
|
4822 |
foreach ($files as $index => $file) {
|
4823 |
if ($remote_deleted == $remote_delete_limit) {
|
5052 |
'CSRF' => '',
|
5053 |
'dropbox_site_folder' => $dropbox_details['dropbox_site_folder']
|
5054 |
);
|
5055 |
+
if ( !empty($dropbox_details['dropbox_email']) ) {
|
5056 |
+
$opts['email'] = $dropbox_details['dropbox_email'];
|
5057 |
+
}
|
5058 |
IWP_MMB_Backup_Options::update_iwp_backup_option('IWP_dropbox', $opts);
|
5059 |
}elseif (!empty($params['account_info']['iwp_gdrive'])) {
|
5060 |
$google_details = $params['account_info']['iwp_gdrive'];
|
backup/backup.upload.php
CHANGED
@@ -8,6 +8,8 @@ abstract class IWP_MMB_UploadModule {
|
|
8 |
private $_options;
|
9 |
|
10 |
private $_instance_id;
|
|
|
|
|
11 |
|
12 |
/**
|
13 |
* Store options (within this class) for this remote storage module. There is also a parameter for saving to the permanent storage (i.e. database).
|
@@ -22,6 +24,8 @@ abstract class IWP_MMB_UploadModule {
|
|
22 |
$this->_options = $options;
|
23 |
|
24 |
if (null !== $instance_id) $this->set_instance_id($instance_id);
|
|
|
|
|
25 |
|
26 |
if ($save) return $this->save_options();
|
27 |
|
@@ -38,9 +42,9 @@ abstract class IWP_MMB_UploadModule {
|
|
38 |
throw new Exception('set_options() can only be called on a storage method which supports multi_options (this module, '.$this->get_id().', does not)');
|
39 |
}
|
40 |
|
41 |
-
if (!$this->_instance_id) {
|
42 |
-
|
43 |
-
}
|
44 |
|
45 |
global $iwp_backup_core;
|
46 |
|
@@ -291,4 +295,23 @@ abstract class IWP_MMB_UploadModule {
|
|
291 |
if (is_string($legacy_key)) $iwp_backup_core->jobdata_delete($legacy_key);
|
292 |
|
293 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
294 |
}
|
8 |
private $_options;
|
9 |
|
10 |
private $_instance_id;
|
11 |
+
|
12 |
+
private $_storage;
|
13 |
|
14 |
/**
|
15 |
* Store options (within this class) for this remote storage module. There is also a parameter for saving to the permanent storage (i.e. database).
|
24 |
$this->_options = $options;
|
25 |
|
26 |
if (null !== $instance_id) $this->set_instance_id($instance_id);
|
27 |
+
|
28 |
+
if (!empty($this->_storage)) unset($this->_storage);
|
29 |
|
30 |
if ($save) return $this->save_options();
|
31 |
|
42 |
throw new Exception('set_options() can only be called on a storage method which supports multi_options (this module, '.$this->get_id().', does not)');
|
43 |
}
|
44 |
|
45 |
+
// if (!$this->_instance_id) {
|
46 |
+
// throw new Exception('set_options() requires an instance ID, but was called without setting one (either directly or via set_instance_id())');
|
47 |
+
// }
|
48 |
|
49 |
global $iwp_backup_core;
|
50 |
|
295 |
if (is_string($legacy_key)) $iwp_backup_core->jobdata_delete($legacy_key);
|
296 |
|
297 |
}
|
298 |
+
|
299 |
+
|
300 |
+
/**
|
301 |
+
* This method will set the stored storage object to that indicated
|
302 |
+
*
|
303 |
+
* @param Object $storage - the storage client
|
304 |
+
*/
|
305 |
+
public function set_storage($storage) {
|
306 |
+
$this->_storage = $storage;
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* This method will return the stored storage client
|
311 |
+
*
|
312 |
+
* @return Object - the stored remote storage client
|
313 |
+
*/
|
314 |
+
public function get_storage() {
|
315 |
+
if (!empty($this->_storage)) return $this->_storage;
|
316 |
+
}
|
317 |
}
|
backup/dropbox.php
CHANGED
@@ -31,6 +31,7 @@ class IWP_MMB_UploadModule_dropbox extends IWP_MMB_UploadModule {
|
|
31 |
$iwp_backup_core->jobdata_set('IWP_dbof_'.$this->current_file_hash, $offset);
|
32 |
|
33 |
$time_now = microtime(true);
|
|
|
34 |
|
35 |
$time_since_last_tick = $time_now - $this->upload_tick;
|
36 |
$data_since_last_tick = $offset - $this->uploaded_offset;
|
@@ -49,7 +50,7 @@ class IWP_MMB_UploadModule_dropbox extends IWP_MMB_UploadModule {
|
|
49 |
$new_chunk = max(min($upload_secs * $upload_rate * 0.9, 10485760), 1048576);
|
50 |
$new_chunk = $new_chunk - ($new_chunk % 524288);
|
51 |
$chunk_size = (int)$new_chunk;
|
52 |
-
$
|
53 |
$iwp_backup_core->jobdata_set('dropbox_chunk_size', $chunk_size);
|
54 |
}
|
55 |
}
|
@@ -440,7 +441,7 @@ class IWP_MMB_UploadModule_dropbox extends IWP_MMB_UploadModule {
|
|
440 |
|
441 |
}
|
442 |
|
443 |
-
public function config_print() {
|
444 |
|
445 |
$opts = $this->get_options();
|
446 |
$ownername = empty($opts['ownername']) ? '' : $opts['ownername'];
|
@@ -485,14 +486,18 @@ public function config_print() {
|
|
485 |
$key = empty($opts['secret']) ? '' : $opts['secret'];
|
486 |
$sec = empty($opts['appkey']) ? '' : $opts['appkey'];
|
487 |
|
488 |
-
$oauth2_id =
|
|
|
|
|
|
|
|
|
489 |
|
490 |
|
491 |
// Instantiate the Encrypter and storage objects
|
492 |
$encrypter = new Dropbox_Encrypter('ThisOneDoesNotMatterBeyondLength');
|
493 |
|
494 |
// Instantiate the storage
|
495 |
-
$
|
496 |
|
497 |
// WordPress consumer does not yet work
|
498 |
// $OAuth = new Dropbox_ConsumerWordPress($sec, $key, $storage, $callback);
|
@@ -507,7 +512,7 @@ public function config_print() {
|
|
507 |
}
|
508 |
|
509 |
try {
|
510 |
-
$OAuth = new Dropbox_Curl($sec, $oauth2_id, $key, $
|
511 |
} catch (Exception $e) {
|
512 |
global $iwp_backup_core;
|
513 |
$iwp_backup_core->log("Dropbox Curl error: ".$e->getMessage());
|
@@ -516,10 +521,16 @@ public function config_print() {
|
|
516 |
}
|
517 |
|
518 |
if ($deauthenticate) return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
519 |
|
520 |
-
$
|
521 |
-
$this->dropbox_object = new IWP_MMB_Dropbox_API($OAuth, $root);
|
522 |
-
return $this->dropbox_object;
|
523 |
}
|
524 |
|
525 |
}
|
31 |
$iwp_backup_core->jobdata_set('IWP_dbof_'.$this->current_file_hash, $offset);
|
32 |
|
33 |
$time_now = microtime(true);
|
34 |
+
$storage = $this->get_storage();
|
35 |
|
36 |
$time_since_last_tick = $time_now - $this->upload_tick;
|
37 |
$data_since_last_tick = $offset - $this->uploaded_offset;
|
50 |
$new_chunk = max(min($upload_secs * $upload_rate * 0.9, 10485760), 1048576);
|
51 |
$new_chunk = $new_chunk - ($new_chunk % 524288);
|
52 |
$chunk_size = (int)$new_chunk;
|
53 |
+
$storage->setChunkSize($chunk_size);
|
54 |
$iwp_backup_core->jobdata_set('dropbox_chunk_size', $chunk_size);
|
55 |
}
|
56 |
}
|
441 |
|
442 |
}
|
443 |
|
444 |
+
public function config_print() {
|
445 |
|
446 |
$opts = $this->get_options();
|
447 |
$ownername = empty($opts['ownername']) ? '' : $opts['ownername'];
|
486 |
$key = empty($opts['secret']) ? '' : $opts['secret'];
|
487 |
$sec = empty($opts['appkey']) ? '' : $opts['appkey'];
|
488 |
|
489 |
+
$oauth2_id = $key;
|
490 |
+
$old_auth = false;
|
491 |
+
if ( empty($opts['email']) ) {
|
492 |
+
$old_auth = true;
|
493 |
+
}
|
494 |
|
495 |
|
496 |
// Instantiate the Encrypter and storage objects
|
497 |
$encrypter = new Dropbox_Encrypter('ThisOneDoesNotMatterBeyondLength');
|
498 |
|
499 |
// Instantiate the storage
|
500 |
+
$dropbox_storage = new Dropbox_WordPress($encrypter, "tk_", 'IWP_dropbox', $this);
|
501 |
|
502 |
// WordPress consumer does not yet work
|
503 |
// $OAuth = new Dropbox_ConsumerWordPress($sec, $key, $storage, $callback);
|
512 |
}
|
513 |
|
514 |
try {
|
515 |
+
$OAuth = new Dropbox_Curl($sec, $oauth2_id, $key, $dropbox_storage, null, null, $deauthenticate, null,$old_auth);
|
516 |
} catch (Exception $e) {
|
517 |
global $iwp_backup_core;
|
518 |
$iwp_backup_core->log("Dropbox Curl error: ".$e->getMessage());
|
521 |
}
|
522 |
|
523 |
if ($deauthenticate) return true;
|
524 |
+
|
525 |
+
if ( empty($opts['email']) ) {
|
526 |
+
$dropbox_storage->set($opts['tk_access_token'], 'access_token');
|
527 |
+
}
|
528 |
+
|
529 |
+
$storage = new IWP_MMB_Dropbox_API($OAuth, $root);
|
530 |
+
|
531 |
+
$this->set_storage($storage);
|
532 |
|
533 |
+
return $storage;
|
|
|
|
|
534 |
}
|
535 |
|
536 |
}
|
core.class.php
CHANGED
@@ -793,6 +793,7 @@ Plugin Name: InfiniteWP - Client Loader
|
|
793 |
Plugin URI: https://infinitewp.com/
|
794 |
Description: This plugin will be created automatically when you activate your InfiniteWP Client plugin to improve the performance. And it will be deleted when you deactivate the client plugin.
|
795 |
Author: Revmakx
|
|
|
796 |
Author URI: https://infinitewp.com/
|
797 |
*/
|
798 |
|
@@ -843,6 +844,7 @@ EOF;
|
|
843 |
$error = error_get_last();
|
844 |
throw new Exception(sprintf('Unable to write loader: %s', $error['message']));
|
845 |
}
|
|
|
846 |
}
|
847 |
|
848 |
function error_notices()
|
793 |
Plugin URI: https://infinitewp.com/
|
794 |
Description: This plugin will be created automatically when you activate your InfiniteWP Client plugin to improve the performance. And it will be deleted when you deactivate the client plugin.
|
795 |
Author: Revmakx
|
796 |
+
Version: 1.0.0
|
797 |
Author URI: https://infinitewp.com/
|
798 |
*/
|
799 |
|
844 |
$error = error_get_last();
|
845 |
throw new Exception(sprintf('Unable to write loader: %s', $error['message']));
|
846 |
}
|
847 |
+
update_option('iwp_mu_plugin_version','1.0.0');
|
848 |
}
|
849 |
|
850 |
function error_notices()
|
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.9.
|
8 |
Author URI: http://www.revmakx.com
|
9 |
Network: true
|
10 |
*/
|
@@ -29,7 +29,7 @@ if(basename($_SERVER['SCRIPT_FILENAME']) == "init.php"):
|
|
29 |
exit;
|
30 |
endif;
|
31 |
if(!defined('IWP_MMB_CLIENT_VERSION'))
|
32 |
-
define('IWP_MMB_CLIENT_VERSION', '1.9.
|
33 |
|
34 |
|
35 |
|
@@ -3280,7 +3280,7 @@ function iwp_plugin_compatibility_fix(){
|
|
3280 |
$iwp_plugin_fix->fixSidekickPlugin();
|
3281 |
$iwp_plugin_fix->fixSpamShield();
|
3282 |
$iwp_plugin_fix->fixWpSpamShieldBan();
|
3283 |
-
$iwp_plugin_fix->
|
3284 |
|
3285 |
}
|
3286 |
|
@@ -3291,14 +3291,52 @@ function iwp_mu_plugin_loader(){
|
|
3291 |
$loaderPath = $mustUsePluginDir.'/'.$loaderName;
|
3292 |
|
3293 |
if (file_exists($loaderPath)) {
|
3294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3295 |
}
|
3296 |
try {
|
3297 |
-
$iwp_mmb_core->registerMustUse($loaderName
|
3298 |
} catch (Exception $e) {
|
3299 |
iwp_mmb_response(array('error' => 'Unable to write InfiniteWP Client loader:'.$e->getMessage(), 'error_code' => 'iwp_mu_plugin_loader_failed'), false);
|
3300 |
}
|
3301 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3302 |
if(!function_exists('iwp_mmb_is_WPTC')) {
|
3303 |
function iwp_mmb_is_WPTC() {
|
3304 |
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
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.9.6
|
8 |
Author URI: http://www.revmakx.com
|
9 |
Network: true
|
10 |
*/
|
29 |
exit;
|
30 |
endif;
|
31 |
if(!defined('IWP_MMB_CLIENT_VERSION'))
|
32 |
+
define('IWP_MMB_CLIENT_VERSION', '1.9.6');
|
33 |
|
34 |
|
35 |
|
3280 |
$iwp_plugin_fix->fixSidekickPlugin();
|
3281 |
$iwp_plugin_fix->fixSpamShield();
|
3282 |
$iwp_plugin_fix->fixWpSpamShieldBan();
|
3283 |
+
$iwp_plugin_fix->fixGlobals();
|
3284 |
|
3285 |
}
|
3286 |
|
3291 |
$loaderPath = $mustUsePluginDir.'/'.$loaderName;
|
3292 |
|
3293 |
if (file_exists($loaderPath)) {
|
3294 |
+
$iwp_mu_plugin_version = get_option('iwp_mu_plugin_version');
|
3295 |
+
if(empty($iwp_mu_plugin_version)){
|
3296 |
+
$iwp_mu_plugin_version = '1.0.0';
|
3297 |
+
$data = build_mu_plugin_version($loaderPath,$iwp_mu_plugin_version);
|
3298 |
+
if(!$data){
|
3299 |
+
iwp_mmb_response(array('error' => 'Unable to read InfiniteWP must use plugin', 'error_code' => 'iwp_mu_plugin_read_failed'), false);
|
3300 |
+
return;
|
3301 |
+
}
|
3302 |
+
}else{
|
3303 |
+
return; //Both file and version number exisit
|
3304 |
+
}
|
3305 |
+
}else{
|
3306 |
+
$data = $iwp_mmb_core->buildLoaderContent('iwp-client/init.php');
|
3307 |
}
|
3308 |
try {
|
3309 |
+
$iwp_mmb_core->registerMustUse($loaderName,$data);
|
3310 |
} catch (Exception $e) {
|
3311 |
iwp_mmb_response(array('error' => 'Unable to write InfiniteWP Client loader:'.$e->getMessage(), 'error_code' => 'iwp_mu_plugin_loader_failed'), false);
|
3312 |
}
|
3313 |
}
|
3314 |
+
|
3315 |
+
function build_mu_plugin_version($loaderPath,$iwp_mu_plugin_version){
|
3316 |
+
$res = false;
|
3317 |
+
$loaderWritten = @file_get_contents($loaderPath);
|
3318 |
+
if($loaderWritten){
|
3319 |
+
$res = preg_replace('/Author: Revmakx/', "Author: Revmakx ".PHP_EOL."Version :".$iwp_mu_plugin_version." ", $loaderWritten);
|
3320 |
+
}
|
3321 |
+
return $res;
|
3322 |
+
}
|
3323 |
+
|
3324 |
+
function set_iwp_dropbox_auth_setting($dropbox_details){
|
3325 |
+
if ( !empty($dropbox_details['dropbox_email']) ) {
|
3326 |
+
$opts = array(
|
3327 |
+
'appkey' => $dropbox_details['dropbox_app_key'],
|
3328 |
+
'secret' => $dropbox_details['dropbox_app_secure_key'],
|
3329 |
+
'tk_access_token' => $dropbox_details['dropbox_access_token'],
|
3330 |
+
'folder' => $dropbox_details['dropbox_destination'],
|
3331 |
+
'ownername' => '',
|
3332 |
+
'email' => $dropbox_details['dropbox_email'],
|
3333 |
+
'CSRF' => '',
|
3334 |
+
'dropbox_site_folder' => $dropbox_details['dropbox_site_folder']
|
3335 |
+
);
|
3336 |
+
IWP_MMB_Backup_Options::update_iwp_backup_option('IWP_dropbox', $opts);
|
3337 |
+
}
|
3338 |
+
}
|
3339 |
+
|
3340 |
if(!function_exists('iwp_mmb_is_WPTC')) {
|
3341 |
function iwp_mmb_is_WPTC() {
|
3342 |
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
|
lib/Dropbox2/API.php
CHANGED
@@ -10,9 +10,7 @@
|
|
10 |
*/
|
11 |
class IWP_MMB_Dropbox_API {
|
12 |
// API Endpoints
|
13 |
-
const API_URL = 'https://api.dropbox.com/1/';
|
14 |
const API_URL_V2 = 'https://api.dropboxapi.com/';
|
15 |
-
const CONTENT_URL = 'https://api-content.dropbox.com/1/';
|
16 |
const CONTENT_URL_V2 = 'https://content.dropboxapi.com/2/';
|
17 |
|
18 |
/**
|
@@ -71,6 +69,15 @@ class IWP_MMB_Dropbox_API {
|
|
71 |
$this->root = $root;
|
72 |
}
|
73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
/**
|
76 |
* Retrieves information about the user's account
|
@@ -85,68 +92,20 @@ class IWP_MMB_Dropbox_API {
|
|
85 |
|
86 |
/**
|
87 |
* Retrieves information about the user's quota
|
|
|
88 |
* @return object stdClass
|
89 |
*/
|
90 |
-
public function quotaInfo() {
|
91 |
$call = '2/users/get_space_usage';
|
92 |
-
|
|
|
|
|
|
|
|
|
93 |
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
94 |
return $response;
|
95 |
}
|
96 |
|
97 |
-
/**
|
98 |
-
* Not used
|
99 |
-
* Uploads a physical file from disk
|
100 |
-
* Dropbox impose a 150MB limit to files uploaded via the API. If the file
|
101 |
-
* exceeds this limit or does not exist, an Exception will be thrown
|
102 |
-
* @param string $file Absolute path to the file to be uploaded
|
103 |
-
* @param string|bool $filename The destination filename of the uploaded file
|
104 |
-
* @param string $path Path to upload the file to, relative to root
|
105 |
-
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
106 |
-
* @return object stdClass
|
107 |
-
*/
|
108 |
-
// public function putFile($file, $filename = false, $path = '', $overwrite = true)
|
109 |
-
// {
|
110 |
-
// if (file_exists($file)) {
|
111 |
-
// if (filesize($file) <= 157286400) {
|
112 |
-
// $call = 'files/' . $this->root . '/' . $this->encodePath($path);
|
113 |
-
// // If no filename is provided we'll use the original filename
|
114 |
-
// $filename = (is_string($filename)) ? $filename : basename($file);
|
115 |
-
// $params = array(
|
116 |
-
// 'filename' => $filename,
|
117 |
-
// 'file' => '@' . str_replace('\\', '/', $file) . ';filename=' . $filename,
|
118 |
-
// 'overwrite' => (int) $overwrite,
|
119 |
-
// );
|
120 |
-
// $response = $this->fetch('POST', self::CONTENT_URL, $call, $params);
|
121 |
-
// return $response;
|
122 |
-
// }
|
123 |
-
// throw new Exception('File exceeds 150MB upload limit');
|
124 |
-
// }
|
125 |
-
|
126 |
-
// // Throw an Exception if the file does not exist
|
127 |
-
// throw new Exception('Local file ' . $file . ' does not exist');
|
128 |
-
// }
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Not used
|
132 |
-
* Uploads file data from a stream
|
133 |
-
* Note: This function is experimental and requires further testing
|
134 |
-
* @todo Add filesize check
|
135 |
-
* @param resource $stream A readable stream created using fopen()
|
136 |
-
* @param string $filename The destination filename, including path
|
137 |
-
* @param boolean $overwrite Should the file be overwritten? (Default: true)
|
138 |
-
* @return array
|
139 |
-
*/
|
140 |
-
// public function putStream($stream, $filename, $overwrite = true)
|
141 |
-
// {
|
142 |
-
// $this->OAuth->setInFile($stream);
|
143 |
-
// $path = $this->encodePath($filename);
|
144 |
-
// $call = 'files_put/' . $this->root . '/' . $path;
|
145 |
-
// $params = array('overwrite' => (int) $overwrite);
|
146 |
-
// $response = $this->fetch('PUT', self::CONTENT_URL, $call, $params);
|
147 |
-
// return $response;
|
148 |
-
// }
|
149 |
-
|
150 |
/**
|
151 |
* Uploads large files to Dropbox in mulitple chunks
|
152 |
* @param string $file Absolute path to the file to be uploaded
|
@@ -158,6 +117,94 @@ class IWP_MMB_Dropbox_API {
|
|
158 |
* @param string|array function to call back to upon each chunk
|
159 |
* @return stdClass
|
160 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
public function chunkedUpload($file, $filename = false, $path = '', $overwrite = true, $offset = 0, $uploadID = null, $callback = null) {
|
162 |
|
163 |
if (file_exists($file)) {
|
@@ -174,8 +221,8 @@ class IWP_MMB_Dropbox_API {
|
|
174 |
|
175 |
// Read from the file handle until EOF, uploading each chunk
|
176 |
while ($data = fread($handle, $this->chunkSize)) {
|
177 |
-
|
178 |
-
|
179 |
$this->OAuth->setInFile($data);
|
180 |
|
181 |
if ($firstCommit) {
|
@@ -256,6 +303,8 @@ class IWP_MMB_Dropbox_API {
|
|
256 |
|
257 |
// $params['cursor']['offset'] = $responseCheck[1];
|
258 |
// $response = $this->append_upload($params, $last_call);
|
|
|
|
|
259 |
} else {
|
260 |
throw $e;
|
261 |
}
|
@@ -264,267 +313,102 @@ class IWP_MMB_Dropbox_API {
|
|
264 |
}
|
265 |
|
266 |
/**
|
267 |
-
*
|
268 |
-
*
|
269 |
-
* @param string $file Path to file, relative to root, including path
|
270 |
-
* @param
|
271 |
-
* @param
|
272 |
-
* @
|
273 |
-
* @return array
|
274 |
*/
|
275 |
-
public function
|
276 |
// Only allow php response format for this call
|
277 |
if ($this->responseFormat !== 'php') {
|
278 |
throw new Exception('This method only supports the `php` response format');
|
279 |
}
|
280 |
-
|
281 |
-
$
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
}
|
292 |
-
elseif (!$handle = fopen($outFile, 'w')) {
|
293 |
-
throw new Exception("Unable to open file handle for $outFile");
|
294 |
-
} else {
|
295 |
-
$this->OAuth->setOutFile($handle);
|
296 |
}
|
297 |
-
}
|
298 |
-
|
299 |
-
$file = $this->encodePath($file);
|
300 |
-
$call = 'files/download';
|
301 |
-
$params = array('path' => '/' . $file, 'api_v2' => true, 'content_download' => true);
|
302 |
-
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params);
|
303 |
-
|
304 |
-
// Close the file handle if one was opened
|
305 |
-
if ($handle) fclose($handle);
|
306 |
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
'
|
311 |
-
|
312 |
-
|
|
|
|
|
|
|
|
|
|
|
313 |
}
|
314 |
|
315 |
/**
|
316 |
-
*
|
317 |
-
* Retrieves file and folder metadata
|
318 |
-
* @param string $path The path to the file/folder, relative to root
|
319 |
-
* @param string $rev Return metadata for a specific revision (Default: latest rev)
|
320 |
-
* @param int $limit Maximum number of listings to return
|
321 |
-
* @param string $hash Metadata hash to compare against
|
322 |
-
* @param bool $list Return contents field with response
|
323 |
-
* @param bool $deleted Include files/folders that have been deleted
|
324 |
-
* @return object stdClass
|
325 |
-
*/
|
326 |
-
public function metaData($path = null, $rev = null, $limit = 10000, $hash = false, $list = true, $deleted = false) {
|
327 |
-
$call = '2/files/get_metadata' ;
|
328 |
-
$params = array(
|
329 |
-
'path' => '/' . $this->normalisePath($path),
|
330 |
-
'api_v2' => true
|
331 |
-
);
|
332 |
-
|
333 |
-
return $this->fetch('POST', self::API_URL_V2, $call, $params);
|
334 |
-
}
|
335 |
-
|
336 |
-
/**
|
337 |
-
* Not used
|
338 |
-
* Return "delta entries", intructing you how to update
|
339 |
-
* your application state to match the server's state
|
340 |
-
* Important: This method does not make changes to the application state
|
341 |
-
* @param null|string $cursor Used to keep track of your current state
|
342 |
-
* @return array Array of delta entries
|
343 |
-
*/
|
344 |
-
// public function delta($cursor = null)
|
345 |
-
// {
|
346 |
-
// $call = 'delta';
|
347 |
-
// $params = array('cursor' => $cursor);
|
348 |
-
// $response = $this->fetch('POST', self::API_URL, $call, $params);
|
349 |
-
// return $response;
|
350 |
-
// }
|
351 |
-
|
352 |
-
/**
|
353 |
-
* Not used
|
354 |
-
* Obtains metadata for the previous revisions of a file
|
355 |
-
* @param string Path to the file, relative to root
|
356 |
-
* @param integer Number of revisions to return (1-1000)
|
357 |
-
* @return array
|
358 |
-
*/
|
359 |
-
// public function revisions($file, $limit = 10)
|
360 |
-
// {
|
361 |
-
// $call = 'revisions/' . $this->root . '/' . $this->encodePath($file);
|
362 |
-
// $params = array(
|
363 |
-
// 'rev_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
|
364 |
-
// );
|
365 |
-
// $response = $this->fetch('GET', self::API_URL, $call, $params);
|
366 |
-
// return $response;
|
367 |
-
// }
|
368 |
-
|
369 |
-
/**
|
370 |
-
* Not used
|
371 |
-
* Restores a file path to a previous revision
|
372 |
-
* @param string $file Path to the file, relative to root
|
373 |
-
* @param string $revision The revision of the file to restore
|
374 |
-
* @return object stdClass
|
375 |
-
*/
|
376 |
-
// public function restore($file, $revision)
|
377 |
-
// {
|
378 |
-
// $call = 'restore/' . $this->root . '/' . $this->encodePath($file);
|
379 |
-
// $params = array('rev' => $revision);
|
380 |
-
// $response = $this->fetch('POST', self::API_URL, $call, $params);
|
381 |
-
// return $response;
|
382 |
-
// }
|
383 |
-
|
384 |
-
/**
|
385 |
-
* Returns metadata for all files and folders that match the search query
|
386 |
* @param mixed $query The search string. Must be at least 3 characters long
|
387 |
* @param string [$path=''] The path to the folder you want to search in
|
388 |
* @param integer [$limit=1000] Maximum number of results to return (1-1000)
|
389 |
-
* @param integer [$
|
390 |
* @return array
|
391 |
*/
|
392 |
-
public function search($query, $path = '', $limit = 1000, $
|
393 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
$path = $this->encodePath($path);
|
395 |
// APIv2 requires that the path match this regex: String(pattern="(/(.|[\r\n])*)?|(ns:[0-9]+(/.*)?)")
|
396 |
if ($path && '/' != substr($path, 0, 1)) $path = "/$path";
|
397 |
$params = array(
|
398 |
-
'path' => $path,
|
399 |
'query' => $query,
|
400 |
-
'
|
401 |
-
|
|
|
|
|
402 |
'api_v2' => true,
|
403 |
);
|
404 |
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
405 |
return $response;
|
406 |
}
|
407 |
-
|
408 |
-
/**
|
409 |
-
* Not used
|
410 |
-
* Creates and returns a shareable link to files or folders
|
411 |
-
* The link returned is for a preview page from which the user an choose to
|
412 |
-
* download the file if they wish. For direct download links, see media().
|
413 |
-
* @param string $path The path to the file/folder you want a sharable link to
|
414 |
-
* @return object stdClass
|
415 |
-
*/
|
416 |
-
// public function shares($path, $shortUrl = true)
|
417 |
-
// {
|
418 |
-
// $call = 'shares/' . $this->root . '/' .$this->encodePath($path);
|
419 |
-
// $params = array('short_url' => ($shortUrl) ? 1 : 0);
|
420 |
-
// $response = $this->fetch('POST', self::API_URL, $call, $params);
|
421 |
-
// return $response;
|
422 |
-
// }
|
423 |
-
|
424 |
-
/**
|
425 |
-
* Not used
|
426 |
-
* Returns a link directly to a file
|
427 |
-
* @param string $path The path to the media file you want a direct link to
|
428 |
-
* @return object stdClass
|
429 |
-
*/
|
430 |
-
// public function media($path)
|
431 |
-
// {
|
432 |
-
// $call = 'media/' . $this->root . '/' . $this->encodePath($path);
|
433 |
-
// $response = $this->fetch('POST', self::API_URL, $call);
|
434 |
-
// return $response;
|
435 |
-
// }
|
436 |
-
|
437 |
-
/**
|
438 |
-
* Not used
|
439 |
-
* Gets a thumbnail for an image
|
440 |
-
* @param string $file The path to the image you wish to thumbnail
|
441 |
-
* @param string $format The thumbnail format, either JPEG or PNG
|
442 |
-
* @param string $size The size of the thumbnail
|
443 |
-
* @return array
|
444 |
-
*/
|
445 |
-
// public function thumbnails($file, $format = 'JPEG', $size = 'small')
|
446 |
-
// {
|
447 |
-
// // Only allow php response format for this call
|
448 |
-
// if ($this->responseFormat !== 'php') {
|
449 |
-
// throw new Exception('This method only supports the `php` response format');
|
450 |
-
// }
|
451 |
-
|
452 |
-
// $format = strtoupper($format);
|
453 |
-
// // If $format is not 'PNG', default to 'JPEG'
|
454 |
-
// if ($format != 'PNG') $format = 'JPEG';
|
455 |
-
|
456 |
-
// $size = strtolower($size);
|
457 |
-
// $sizes = array('s', 'm', 'l', 'xl', 'small', 'medium', 'large');
|
458 |
-
// // If $size is not valid, default to 'small'
|
459 |
-
// if (!in_array($size, $sizes)) $size = 'small';
|
460 |
-
|
461 |
-
// $call = 'thumbnails/' . $this->root . '/' . $this->encodePath($file);
|
462 |
-
// $params = array('format' => $format, 'size' => $size);
|
463 |
-
// $response = $this->fetch('GET', self::CONTENT_URL, $call, $params);
|
464 |
-
|
465 |
-
// return array(
|
466 |
-
// 'name' => basename($file),
|
467 |
-
// 'mime' => $this->getMimeType($response['body']),
|
468 |
-
// 'meta' => json_decode($response['headers']['x-dropbox-metadata']),
|
469 |
-
// 'data' => $response['body'],
|
470 |
-
// );
|
471 |
-
// }
|
472 |
-
|
473 |
-
/**
|
474 |
-
* Not used
|
475 |
-
* THIS IS NOT AVAILABLE IN V2.
|
476 |
-
* Creates and returns a copy_ref to a file
|
477 |
-
* This reference string can be used to copy that file to another user's
|
478 |
-
* Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy
|
479 |
-
* @param $path File for which ref should be created, relative to root
|
480 |
-
* @return array
|
481 |
-
*/
|
482 |
-
// public function copyRef($path)
|
483 |
-
// {
|
484 |
-
// $call = 'copy_ref/' . $this->root . '/' . $this->encodePath($path);
|
485 |
-
// $response = $this->fetch('GET', self::API_URL, $call);
|
486 |
-
// return $response;
|
487 |
-
// }
|
488 |
-
|
489 |
-
/**
|
490 |
-
* Not used
|
491 |
-
* Copies a file or folder to a new location
|
492 |
-
* @param string $from File or folder to be copied, relative to root
|
493 |
-
* @param string $to Destination path, relative to root
|
494 |
-
* @param null|string $fromCopyRef Must be used instead of the from_path
|
495 |
-
* @return object stdClass
|
496 |
-
*/
|
497 |
-
// public function copy($from, $to, $fromCopyRef = null)
|
498 |
-
// {
|
499 |
-
// $call = 'fileops/copy';
|
500 |
-
// $params = array(
|
501 |
-
// 'root' => $this->root,
|
502 |
-
// 'from_path' => $this->normalisePath($from),
|
503 |
-
// 'to_path' => $this->normalisePath($to),
|
504 |
-
// );
|
505 |
-
|
506 |
-
// if ($fromCopyRef) {
|
507 |
-
// $params['from_path'] = null;
|
508 |
-
// $params['from_copy_ref'] = $fromCopyRef;
|
509 |
-
// }
|
510 |
-
|
511 |
-
// $response = $this->fetch('POST', self::API_URL, $call, $params);
|
512 |
-
// return $response;
|
513 |
-
// }
|
514 |
-
|
515 |
/**
|
516 |
-
*
|
517 |
-
*
|
518 |
-
* @param string
|
519 |
-
*
|
|
|
520 |
*/
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
|
|
|
|
528 |
|
529 |
/**
|
530 |
* Deletes a file or folder
|
@@ -532,31 +416,12 @@ class IWP_MMB_Dropbox_API {
|
|
532 |
* @return object stdClass
|
533 |
*/
|
534 |
public function delete($path) {
|
535 |
-
$call = '2/files/
|
536 |
$params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
|
537 |
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
538 |
return $response;
|
539 |
}
|
540 |
-
|
541 |
-
/**
|
542 |
-
* Not used
|
543 |
-
* Moves a file or folder to a new location
|
544 |
-
* @param string $from File or folder to be moved, relative to root
|
545 |
-
* @param string $to Destination path, relative to root
|
546 |
-
* @return object stdClass
|
547 |
-
*/
|
548 |
-
// public function move($from, $to)
|
549 |
-
// {
|
550 |
-
// $call = 'fileops/move';
|
551 |
-
// $params = array(
|
552 |
-
// 'root' => $this->root,
|
553 |
-
// 'from_path' => $this->normalisePath($from),
|
554 |
-
// 'to_path' => $this->normalisePath($to),
|
555 |
-
// );
|
556 |
-
// $response = $this->fetch('POST', self::API_URL, $call, $params);
|
557 |
-
// return $response;
|
558 |
-
// }
|
559 |
-
|
560 |
/**
|
561 |
* Intermediate fetch function
|
562 |
* @param string $method The HTTP method
|
@@ -618,6 +483,46 @@ class IWP_MMB_Dropbox_API {
|
|
618 |
public function setCallback($function) {
|
619 |
$this->callback = $function;
|
620 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
|
622 |
/**
|
623 |
* Get the mime type of downloaded file
|
@@ -658,4 +563,119 @@ class IWP_MMB_Dropbox_API {
|
|
658 |
// 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.
|
659 |
return $this->normalisePath($path);
|
660 |
}
|
661 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
*/
|
11 |
class IWP_MMB_Dropbox_API {
|
12 |
// API Endpoints
|
|
|
13 |
const API_URL_V2 = 'https://api.dropboxapi.com/';
|
|
|
14 |
const CONTENT_URL_V2 = 'https://content.dropboxapi.com/2/';
|
15 |
|
16 |
/**
|
69 |
$this->root = $root;
|
70 |
}
|
71 |
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* This function will make a request to refresh the access token
|
75 |
+
*
|
76 |
+
* @return void
|
77 |
+
*/
|
78 |
+
public function refreshAccessToken() {
|
79 |
+
$this->OAuth->refreshAccessToken();
|
80 |
+
}
|
81 |
|
82 |
/**
|
83 |
* Retrieves information about the user's account
|
92 |
|
93 |
/**
|
94 |
* Retrieves information about the user's quota
|
95 |
+
* @param array $options - valid keys are 'timeout'
|
96 |
* @return object stdClass
|
97 |
*/
|
98 |
+
public function quotaInfo($options = array()) {
|
99 |
$call = '2/users/get_space_usage';
|
100 |
+
// Cases have been seen (Apr 2019) where a response came back (HTTP/2.0 response header - suspected outgoing web hosting proxy, as everyone else seems to get HTTP/1.0 and I'm not aware that current Curl versions would do HTTP/2.0 without specifically being told to) after 180 seconds; a valid response, but took a long time.
|
101 |
+
$params = array(
|
102 |
+
'api_v2' => true,
|
103 |
+
'timeout' => isset($options['timeout']) ? $options['timeout'] : 20
|
104 |
+
);
|
105 |
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
106 |
return $response;
|
107 |
}
|
108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
/**
|
110 |
* Uploads large files to Dropbox in mulitple chunks
|
111 |
* @param string $file Absolute path to the file to be uploaded
|
117 |
* @param string|array function to call back to upon each chunk
|
118 |
* @return stdClass
|
119 |
*/
|
120 |
+
|
121 |
+
public function chunked_upload($file, $path = '', $overwrite = true, $uploadID = null, $offset = 0, $isCommit = false) {
|
122 |
+
$starting_backup_path_time = time();
|
123 |
+
|
124 |
+
$file = str_replace("\\", "/",$file);
|
125 |
+
if (!file_exists($file)) throw new Exception('Local file ' . $file . ' does not exist');
|
126 |
+
|
127 |
+
if (!($handle = @fopen($file, 'r'))) throw new Exception('Could not open ' . $file . ' for reading');
|
128 |
+
|
129 |
+
// Seek to the correct position on the file pointer
|
130 |
+
fseek($handle, $offset);
|
131 |
+
$to_exit = false;
|
132 |
+
|
133 |
+
//Set firstCommit to true so that the upload session start endpoint is called.
|
134 |
+
$firstCommit = (0 == $offset);
|
135 |
+
|
136 |
+
// Read from the file handle until EOF, uploading each chunk
|
137 |
+
if ($data = fread($handle, $this->chunkSize)) {
|
138 |
+
|
139 |
+
// Set the file, request parameters and send the request
|
140 |
+
$this->OAuth->setInFile($data);
|
141 |
+
|
142 |
+
if ($firstCommit) {
|
143 |
+
$params = array(
|
144 |
+
'close' => false,
|
145 |
+
'api_v2' => true,
|
146 |
+
'content_upload' => true
|
147 |
+
);
|
148 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
|
149 |
+
$firstCommit = false;
|
150 |
+
|
151 |
+
} else {
|
152 |
+
$params = array(
|
153 |
+
'cursor' => array(
|
154 |
+
'session_id' => $uploadID,
|
155 |
+
// If you send it as a string, Dropbox will be unhappy
|
156 |
+
'offset' => (int)$offset
|
157 |
+
),
|
158 |
+
'api_v2' => true,
|
159 |
+
'content_upload' => true
|
160 |
+
);
|
161 |
+
$response = $this->append_upload($params, false);
|
162 |
+
}
|
163 |
+
|
164 |
+
// On subsequent chunks, use the upload ID returned by the previous request
|
165 |
+
if (isset($response['body']->session_id)) {
|
166 |
+
$uploadID = $response['body']->session_id;
|
167 |
+
}
|
168 |
+
|
169 |
+
/*
|
170 |
+
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.
|
171 |
+
*/
|
172 |
+
if (!isset($response['body']->error)) {
|
173 |
+
$offset = ftell($handle);
|
174 |
+
$output['response']= $response;
|
175 |
+
if($isCommit ==false){
|
176 |
+
|
177 |
+
$output['offset']= $offset;
|
178 |
+
$output['upload_id']= $uploadID;
|
179 |
+
}
|
180 |
+
$this->OAuth->setInFile(null);
|
181 |
+
}
|
182 |
+
|
183 |
+
}
|
184 |
+
// Complete the chunked upload
|
185 |
+
if ($isCommit) {
|
186 |
+
$filename = (is_string($filename)) ? $filename : basename($file);
|
187 |
+
$params = array(
|
188 |
+
'cursor' => array(
|
189 |
+
'session_id' => $uploadID,
|
190 |
+
'offset' => (int)$offset
|
191 |
+
),
|
192 |
+
'commit' => array(
|
193 |
+
'path' => '/' . $this->encodePath($path .'/'. $filename),
|
194 |
+
'mode' => 'overwrite'
|
195 |
+
),
|
196 |
+
'api_v2' => true,
|
197 |
+
'content_upload' => true
|
198 |
+
);
|
199 |
+
$response = $this->append_upload($params, true);
|
200 |
+
$offset = ftell($handle);
|
201 |
+
$output['response']= $response;
|
202 |
+
}
|
203 |
+
|
204 |
+
fclose($handle);
|
205 |
+
return $output;
|
206 |
+
}
|
207 |
+
|
208 |
public function chunkedUpload($file, $filename = false, $path = '', $overwrite = true, $offset = 0, $uploadID = null, $callback = null) {
|
209 |
|
210 |
if (file_exists($file)) {
|
221 |
|
222 |
// Read from the file handle until EOF, uploading each chunk
|
223 |
while ($data = fread($handle, $this->chunkSize)) {
|
224 |
+
|
225 |
+
// Set the file, request parameters and send the request
|
226 |
$this->OAuth->setInFile($data);
|
227 |
|
228 |
if ($firstCommit) {
|
303 |
|
304 |
// $params['cursor']['offset'] = $responseCheck[1];
|
305 |
// $response = $this->append_upload($params, $last_call);
|
306 |
+
} elseif (isset($responseCheck) && strpos($responseCheck[0], 'closed') !== false) {
|
307 |
+
throw new Exception("Upload with upload_id {$params['cursor']['session_id']} already completed");
|
308 |
} else {
|
309 |
throw $e;
|
310 |
}
|
313 |
}
|
314 |
|
315 |
/**
|
316 |
+
* Chunked downloads a file from Dropbox, it will return false if a file handle is not passed and will return true if the call was successful.
|
317 |
+
*
|
318 |
+
* @param string $file Path - to file, relative to root, including path
|
319 |
+
* @param resource $outFile - the local file handle
|
320 |
+
* @param array $options - any extra options to be passed e.g headers
|
321 |
+
* @return boolean - a boolean to indicate success or failure
|
|
|
322 |
*/
|
323 |
+
public function download($file, $outFile = null, $options = array()) {
|
324 |
// Only allow php response format for this call
|
325 |
if ($this->responseFormat !== 'php') {
|
326 |
throw new Exception('This method only supports the `php` response format');
|
327 |
}
|
328 |
+
|
329 |
+
if ($outFile) {
|
330 |
+
$this->OAuth->setOutFile($outFile);
|
331 |
+
|
332 |
+
$params = array('path' => '/' . $file, 'api_v2' => true, 'content_download' => true);
|
333 |
+
|
334 |
+
if (isset($options['headers'])) {
|
335 |
+
foreach ($options['headers'] as $key => $header) {
|
336 |
+
$headers[] = $key . ': ' . $header;
|
337 |
+
}
|
338 |
+
$params['headers'] = $headers;
|
|
|
|
|
|
|
|
|
|
|
339 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
340 |
|
341 |
+
$file = $this->encodePath($file);
|
342 |
+
$call = 'files/download';
|
343 |
+
|
344 |
+
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params);
|
345 |
+
|
346 |
+
fclose($outFile);
|
347 |
+
|
348 |
+
return true;
|
349 |
+
} else {
|
350 |
+
return false;
|
351 |
+
}
|
352 |
}
|
353 |
|
354 |
/**
|
355 |
+
* Calls the relevant method to return metadata for all files and folders that match the search query
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
* @param mixed $query The search string. Must be at least 3 characters long
|
357 |
* @param string [$path=''] The path to the folder you want to search in
|
358 |
* @param integer [$limit=1000] Maximum number of results to return (1-1000)
|
359 |
+
* @param integer [$cursor=''] A Dropbox ID to start the search from
|
360 |
* @return array
|
361 |
*/
|
362 |
+
public function search($query, $path = '', $limit = 1000, $cursor = '') {
|
363 |
+
if (empty($cursor)) {
|
364 |
+
return $this->start_search($query, $path, $limit);
|
365 |
+
} else {
|
366 |
+
return $this->continue_search($cursor);
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* This method will start a search for all files and folders that match the search query
|
372 |
+
*
|
373 |
+
* @param mixed $query - the search string, must be at least 3 characters long
|
374 |
+
* @param string $path - the path to the folder you want to search in
|
375 |
+
* @param integer $limit - maximum number of results to return (1-1000)
|
376 |
+
*
|
377 |
+
* @return array - an array of search results
|
378 |
+
*/
|
379 |
+
private function start_search($query, $path, $limit) {
|
380 |
+
$call = '2/files/search_v2';
|
381 |
$path = $this->encodePath($path);
|
382 |
// APIv2 requires that the path match this regex: String(pattern="(/(.|[\r\n])*)?|(ns:[0-9]+(/.*)?)")
|
383 |
if ($path && '/' != substr($path, 0, 1)) $path = "/$path";
|
384 |
$params = array(
|
|
|
385 |
'query' => $query,
|
386 |
+
'options' => array(
|
387 |
+
'path' => $path,
|
388 |
+
'max_results' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
|
389 |
+
),
|
390 |
'api_v2' => true,
|
391 |
);
|
392 |
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
393 |
return $response;
|
394 |
}
|
395 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
/**
|
397 |
+
* This method will continue a previous search for all files and folders that match the previous search query
|
398 |
+
*
|
399 |
+
* @param string $cursor - a Dropbox ID to continue the search
|
400 |
+
*
|
401 |
+
* @return array - an array of search results
|
402 |
*/
|
403 |
+
private function continue_search($cursor) {
|
404 |
+
$call = '2/files/search/continue_v2';
|
405 |
+
$params = array(
|
406 |
+
'cursor' => $cursor,
|
407 |
+
'api_v2' => true,
|
408 |
+
);
|
409 |
+
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
410 |
+
return $response;
|
411 |
+
}
|
412 |
|
413 |
/**
|
414 |
* Deletes a file or folder
|
416 |
* @return object stdClass
|
417 |
*/
|
418 |
public function delete($path) {
|
419 |
+
$call = '2/files/delete_v2';
|
420 |
$params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
|
421 |
$response = $this->fetch('POST', self::API_URL_V2, $call, $params);
|
422 |
return $response;
|
423 |
}
|
424 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
/**
|
426 |
* Intermediate fetch function
|
427 |
* @param string $method The HTTP method
|
483 |
public function setCallback($function) {
|
484 |
$this->callback = $function;
|
485 |
}
|
486 |
+
|
487 |
+
public function getFile($file, $outFile = false, $revision = null, $allow_resume = false) {
|
488 |
+
// Only allow php response format for this call
|
489 |
+
if ($this->responseFormat !== 'php') {
|
490 |
+
throw new Exception('This method only supports the `php` response format');
|
491 |
+
}
|
492 |
+
|
493 |
+
$handle = null;
|
494 |
+
if ($outFile !== false) {
|
495 |
+
// Create a file handle if $outFile is specified
|
496 |
+
if ($allow_resume && file_exists($outFile)) {
|
497 |
+
if (!$handle = fopen($outFile, 'a')) {
|
498 |
+
throw new Exception("Unable to open file handle for $outFile");
|
499 |
+
} else {
|
500 |
+
$this->OAuth->setOutFile($handle);
|
501 |
+
$params['headers'] = array('Range: bytes='.filesize($outFile).'-');
|
502 |
+
}
|
503 |
+
}
|
504 |
+
elseif (!$handle = fopen($outFile, 'w')) {
|
505 |
+
throw new Exception("Unable to open file handle for $outFile");
|
506 |
+
} else {
|
507 |
+
$this->OAuth->setOutFile($handle);
|
508 |
+
}
|
509 |
+
}
|
510 |
+
|
511 |
+
$file = $this->encodePath($file);
|
512 |
+
$call = 'files/download';
|
513 |
+
$params = array('path' => '/' . $file, 'api_v2' => true, 'content_download' => true);
|
514 |
+
$response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params);
|
515 |
+
|
516 |
+
// Close the file handle if one was opened
|
517 |
+
if ($handle) fclose($handle);
|
518 |
+
|
519 |
+
return array(
|
520 |
+
'name' => ($outFile) ? $outFile : basename($file),
|
521 |
+
'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
|
522 |
+
'meta' => json_decode($response['headers']['dropbox-api-result']),
|
523 |
+
'data' => $response['body'],
|
524 |
+
);
|
525 |
+
}
|
526 |
|
527 |
/**
|
528 |
* Get the mime type of downloaded file
|
563 |
// 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.
|
564 |
return $this->normalisePath($path);
|
565 |
}
|
566 |
+
|
567 |
+
public function metaData($path = null, $rev = null, $limit = 10000, $hash = false, $list = true, $deleted = false) {
|
568 |
+
$call = '2/files/get_metadata' ;
|
569 |
+
$params = array(
|
570 |
+
'path' => '/' . $this->normalisePath($path),
|
571 |
+
'api_v2' => true
|
572 |
+
);
|
573 |
+
|
574 |
+
return $this->fetch('POST', self::API_URL_V2, $call, $params);
|
575 |
+
}
|
576 |
+
|
577 |
+
public function putFile($file, $path = '', $overwrite = true) {
|
578 |
+
if (!file_exists($file)) {
|
579 |
+
// Throw an Exception if the file does not exist
|
580 |
+
throw new Exception('Local file ' . $file . ' does not exist');
|
581 |
+
}
|
582 |
+
$filesize = iwp_mmb_get_file_size($file);
|
583 |
+
if ($filesize >= 157286400) {
|
584 |
+
$output = $this->chunked_upload_single_call_new($file, $path,$overwrite);
|
585 |
+
return $output;
|
586 |
+
|
587 |
+
}else{
|
588 |
+
$handle = @fopen($file, 'r');
|
589 |
+
//Set the file content to $this->InFile
|
590 |
+
$this->OAuth->setInFile(fread($handle, filesize($file)));
|
591 |
+
fclose($handle);
|
592 |
+
|
593 |
+
$filename = (is_string($filename)) ? $filename : basename($file);
|
594 |
+
$path = '/' . $this->encodePath($path .'/'. $filename);
|
595 |
+
$params = array(
|
596 |
+
'path' => $path,
|
597 |
+
'mute' => true,
|
598 |
+
'mode' => 'overwrite',
|
599 |
+
'api_v2' => true,
|
600 |
+
'content_upload' => true
|
601 |
+
);
|
602 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload', $params);
|
603 |
+
return $response;
|
604 |
+
}
|
605 |
+
|
606 |
+
}
|
607 |
+
|
608 |
+
public function chunked_upload_single_call_new($file, $path = '',$overwrite=true){
|
609 |
+
$file = str_replace("\\", "/",$file);
|
610 |
+
if (!is_readable($file) or !is_file($file))
|
611 |
+
throw new Exception("Error: File \"$file\" is not readable or doesn't exist.");
|
612 |
+
$file_handle=fopen($file,'r');
|
613 |
+
$uploadID=null;
|
614 |
+
$offset=0;
|
615 |
+
$ProgressFunction=null;
|
616 |
+
while ($data=fread($file_handle, (1024*1024*30))) { //1024*1024*30 = 30MB
|
617 |
+
$firstCommit = (0 == $offset);
|
618 |
+
iwp_mmb_auto_print('dropbox_chucked_upload');
|
619 |
+
$this->OAuth->setInFile($data);
|
620 |
+
|
621 |
+
if ($firstCommit) {
|
622 |
+
$params = array(
|
623 |
+
'close' => false,
|
624 |
+
'api_v2' => true,
|
625 |
+
'content_upload' => true
|
626 |
+
);
|
627 |
+
$response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
|
628 |
+
$firstCommit = false;
|
629 |
+
|
630 |
+
} else {
|
631 |
+
$params = array(
|
632 |
+
'cursor' => array(
|
633 |
+
'session_id' => $uploadID,
|
634 |
+
// If you send it as a string, Dropbox will be unhappy
|
635 |
+
'offset' => (int)$offset
|
636 |
+
),
|
637 |
+
'api_v2' => true,
|
638 |
+
'content_upload' => true
|
639 |
+
);
|
640 |
+
$response = $this->append_upload($params, false);
|
641 |
+
}
|
642 |
+
|
643 |
+
// On subsequent chunks, use the upload ID returned by the previous request
|
644 |
+
if (isset($response['body']->session_id)) {
|
645 |
+
$uploadID = $response['body']->session_id;
|
646 |
+
}
|
647 |
+
|
648 |
+
/*
|
649 |
+
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.
|
650 |
+
*/
|
651 |
+
if (!isset($response['body']->error)) {
|
652 |
+
$offset = ftell($file_handle);
|
653 |
+
$output['response']= $response;
|
654 |
+
if($isCommit ==false){
|
655 |
+
|
656 |
+
$output['offset']= $offset;
|
657 |
+
$output['upload_id']= $uploadID;
|
658 |
+
}
|
659 |
+
$this->OAuth->setInFile(null);
|
660 |
+
}
|
661 |
+
fseek($file_handle, $offset);
|
662 |
+
}
|
663 |
+
fclose($file_handle);
|
664 |
+
$filename = (is_string($filename)) ? $filename : basename($file);
|
665 |
+
$params = array(
|
666 |
+
'cursor' => array(
|
667 |
+
'session_id' => $uploadID,
|
668 |
+
'offset' => (int)$offset
|
669 |
+
),
|
670 |
+
'commit' => array(
|
671 |
+
'path' => '/' . $this->encodePath($path .'/'. $filename),
|
672 |
+
'mode' => 'overwrite'
|
673 |
+
),
|
674 |
+
'api_v2' => true,
|
675 |
+
'content_upload' => true
|
676 |
+
);
|
677 |
+
$response = $this->append_upload($params, true);
|
678 |
+
|
679 |
+
return $response;
|
680 |
+
}
|
681 |
+
}
|
lib/Dropbox2/OAuth/Consumer/ConsumerAbstract.php
CHANGED
@@ -20,14 +20,19 @@ abstract class Dropbox_ConsumerAbstract
|
|
20 |
const ACCESS_TOKEN_METHOD = 'oauth2/token';
|
21 |
// The next endpoint only exists with APIv1
|
22 |
const OAUTH_UPGRADE = 'oauth2/token_from_oauth1';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
* Signature method, either PLAINTEXT or HMAC-SHA1
|
26 |
* @var string
|
27 |
*/
|
28 |
private $sigMethod = 'PLAINTEXT';
|
29 |
-
|
30 |
-
private $token = null;
|
31 |
|
32 |
/**
|
33 |
* Output file handle
|
@@ -57,6 +62,10 @@ abstract class Dropbox_ConsumerAbstract
|
|
57 |
$this->upgradeOAuth();
|
58 |
$iwp_backup_core->log('OAuth token upgrade successful');
|
59 |
}
|
|
|
|
|
|
|
|
|
60 |
|
61 |
if (empty($access_token) || !isset($access_token->oauth_token)) {
|
62 |
try {
|
@@ -83,7 +92,7 @@ abstract class Dropbox_ConsumerAbstract
|
|
83 |
private function upgradeOAuth()
|
84 |
{
|
85 |
// N.B. This call only exists under API v1 - i.e. there is no APIv2 equivalent. Hence the APIv1 endpoint (API_URL) is used, and not the v2 (API_URL_V2)
|
86 |
-
$url =
|
87 |
$response = $this->fetch('POST', $url, '');
|
88 |
$token = new stdClass();
|
89 |
/*
|
@@ -126,17 +135,8 @@ abstract class Dropbox_ConsumerAbstract
|
|
126 |
$iwp_backup_core->log('Dropbox reauthorisation needed; but we are running from cron, AJAX or the CLI, so this is not possible');
|
127 |
$this->storage->do_unset('access_token');
|
128 |
throw new Dropbox_Exception(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'InfiniteWP'), 'Dropbox'));
|
129 |
-
|
130 |
return false;
|
131 |
}
|
132 |
-
|
133 |
-
public function setToken($token)
|
134 |
-
{
|
135 |
-
|
136 |
-
$this->token = $token;
|
137 |
-
|
138 |
-
return $this;
|
139 |
-
}
|
140 |
|
141 |
/**
|
142 |
* Build the user authorisation URL
|
@@ -150,11 +150,18 @@ abstract class Dropbox_ConsumerAbstract
|
|
150 |
*/
|
151 |
|
152 |
global $iwp_backup_core;
|
153 |
-
if (!function_exists('crypt_random_string')) $iwp_backup_core->ensure_phpseclib('Crypt_Random'
|
154 |
|
155 |
$CSRF = base64_encode(crypt_random_string(16));
|
156 |
$this->storage->set($CSRF,'CSRF');
|
157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
$appkey = $this->storage->get('appkey');
|
159 |
|
160 |
if (!empty($appkey) && 'dropbox:' == substr($appkey, 0, 8)) {
|
@@ -162,12 +169,16 @@ abstract class Dropbox_ConsumerAbstract
|
|
162 |
} else if (!empty($appkey)) {
|
163 |
$key = $appkey;
|
164 |
}
|
|
|
|
|
165 |
|
166 |
$params = array(
|
167 |
'client_id' => empty($key) ? $this->oauth2_id : $key,
|
168 |
'response_type' => 'code',
|
169 |
'redirect_uri' => empty($key) ? $this->callback : $this->callbackhome,
|
170 |
-
'state' => empty($key) ?
|
|
|
|
|
171 |
);
|
172 |
|
173 |
// Build the URL and redirect the user
|
@@ -216,7 +227,7 @@ abstract class Dropbox_ConsumerAbstract
|
|
216 |
|
217 |
} else {
|
218 |
$code = base64_decode($code);
|
219 |
-
$code = json_decode($code, true);
|
220 |
}
|
221 |
|
222 |
/*
|
@@ -226,13 +237,14 @@ abstract class Dropbox_ConsumerAbstract
|
|
226 |
as far as I can tell only the oauth token is used
|
227 |
after more testing token secret can be removed.
|
228 |
*/
|
229 |
-
|
230 |
$token = new stdClass();
|
231 |
$token->oauth_token_secret = $code['access_token'];
|
232 |
$token->oauth_token = $code['access_token'];
|
233 |
$token->account_id = $code['account_id'];
|
234 |
$token->token_type = $code['token_type'];
|
235 |
$token->uid = $code['uid'];
|
|
|
|
|
236 |
$this->storage->set($token, 'access_token');
|
237 |
$this->storage->do_unset('upgraded');
|
238 |
|
@@ -242,6 +254,49 @@ abstract class Dropbox_ConsumerAbstract
|
|
242 |
throw new Dropbox_BadRequestException("No Dropbox Code found, will try to get one now", 400);
|
243 |
}
|
244 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
/**
|
247 |
* Get the request/access token
|
@@ -250,10 +305,18 @@ abstract class Dropbox_ConsumerAbstract
|
|
250 |
* if we have not yet started the authentication process
|
251 |
* @return object stdClass
|
252 |
*/
|
253 |
-
|
254 |
{
|
255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
}
|
|
|
257 |
/**
|
258 |
* Generate signed request URL
|
259 |
* See inline comments for description
|
@@ -270,24 +333,40 @@ abstract class Dropbox_ConsumerAbstract
|
|
270 |
$token = $this->getToken();
|
271 |
|
272 |
// Prepare the standard request parameters differently for OAuth1 and OAuth2; we still need OAuth1 to make the request to the upgrade token endpoint
|
273 |
-
if (
|
274 |
-
$
|
275 |
-
|
276 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
|
278 |
/*
|
279 |
To keep this API backwards compatible with the API v1 endpoints all v2 endpoints will also send to this method a api_v2 parameter this will then return just the access token as the signed request is not needed for any calls.
|
280 |
*/
|
281 |
|
282 |
-
if (isset($additional['api_v2']) && $additional['api_v2'] == true) {
|
283 |
-
|
|
|
284 |
if (isset($additional['content_download']) && $additional['content_download'] == true) {
|
285 |
unset($additional['content_download']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
$headers = array(
|
287 |
'Authorization: Bearer '.$params['access_token'],
|
288 |
'Content-Type:',
|
289 |
'Dropbox-API-Arg: '.json_encode($additional),
|
290 |
);
|
|
|
|
|
291 |
$additional = '';
|
292 |
} else if (isset($additional['content_upload']) && $additional['content_upload'] == true) {
|
293 |
unset($additional['content_upload']);
|
@@ -308,6 +387,25 @@ abstract class Dropbox_ConsumerAbstract
|
|
308 |
'postfields' => $additional,
|
309 |
'headers' => $headers,
|
310 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
}
|
312 |
} else {
|
313 |
// Generate a random string for the request
|
20 |
const ACCESS_TOKEN_METHOD = 'oauth2/token';
|
21 |
// The next endpoint only exists with APIv1
|
22 |
const OAUTH_UPGRADE = 'oauth2/token_from_oauth1';
|
23 |
+
|
24 |
+
private $scopes = array(
|
25 |
+
'account_info.read',
|
26 |
+
'files.content.write',
|
27 |
+
'files.content.read',
|
28 |
+
'files.metadata.read',
|
29 |
+
);
|
30 |
|
31 |
/**
|
32 |
* Signature method, either PLAINTEXT or HMAC-SHA1
|
33 |
* @var string
|
34 |
*/
|
35 |
private $sigMethod = 'PLAINTEXT';
|
|
|
|
|
36 |
|
37 |
/**
|
38 |
* Output file handle
|
62 |
$this->upgradeOAuth();
|
63 |
$iwp_backup_core->log('OAuth token upgrade successful');
|
64 |
}
|
65 |
+
|
66 |
+
if (!empty($access_token) && isset($access_token->refresh_token) && isset($access_token->expires_in)) {
|
67 |
+
if ($access_token->expires_in < time()) $this->refreshAccessToken();
|
68 |
+
}
|
69 |
|
70 |
if (empty($access_token) || !isset($access_token->oauth_token)) {
|
71 |
try {
|
92 |
private function upgradeOAuth()
|
93 |
{
|
94 |
// N.B. This call only exists under API v1 - i.e. there is no APIv2 equivalent. Hence the APIv1 endpoint (API_URL) is used, and not the v2 (API_URL_V2)
|
95 |
+
$url = 'https://api.dropbox.com/1/' . self::OAUTH_UPGRADE;
|
96 |
$response = $this->fetch('POST', $url, '');
|
97 |
$token = new stdClass();
|
98 |
/*
|
135 |
$iwp_backup_core->log('Dropbox reauthorisation needed; but we are running from cron, AJAX or the CLI, so this is not possible');
|
136 |
$this->storage->do_unset('access_token');
|
137 |
throw new Dropbox_Exception(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'InfiniteWP'), 'Dropbox'));
|
|
|
138 |
return false;
|
139 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
/**
|
142 |
* Build the user authorisation URL
|
150 |
*/
|
151 |
|
152 |
global $iwp_backup_core;
|
153 |
+
if (!function_exists('crypt_random_string')) $iwp_backup_core->ensure_phpseclib('Crypt_Random');
|
154 |
|
155 |
$CSRF = base64_encode(crypt_random_string(16));
|
156 |
$this->storage->set($CSRF,'CSRF');
|
157 |
+
// Prepare request parameters
|
158 |
+
/*
|
159 |
+
For OAuth v2 Dropbox needs to use a authorisation url that matches one that is set inside the
|
160 |
+
Dropbox developer console. In order to check this it needs the client ID for the OAuth v2 app
|
161 |
+
This will use the default one unless the user is using their own Dropbox App
|
162 |
+
|
163 |
+
Check if the key has dropbox: if so then remove it to stop the request from being invalid
|
164 |
+
*/
|
165 |
$appkey = $this->storage->get('appkey');
|
166 |
|
167 |
if (!empty($appkey) && 'dropbox:' == substr($appkey, 0, 8)) {
|
169 |
} else if (!empty($appkey)) {
|
170 |
$key = $appkey;
|
171 |
}
|
172 |
+
|
173 |
+
if ('' != $this->instance_id) $this->instance_id = ':'.$this->instance_id;
|
174 |
|
175 |
$params = array(
|
176 |
'client_id' => empty($key) ? $this->oauth2_id : $key,
|
177 |
'response_type' => 'code',
|
178 |
'redirect_uri' => empty($key) ? $this->callback : $this->callbackhome,
|
179 |
+
'state' => empty($key) ? "POST:".$CSRF.$this->instance_id.$this->callbackhome : $CSRF.$this->instance_id,
|
180 |
+
'scope' => implode(' ', $this->scopes),
|
181 |
+
'token_access_type' => 'offline'
|
182 |
);
|
183 |
|
184 |
// Build the URL and redirect the user
|
227 |
|
228 |
} else {
|
229 |
$code = base64_decode($code);
|
230 |
+
$code = json_decode($code, true);
|
231 |
}
|
232 |
|
233 |
/*
|
237 |
as far as I can tell only the oauth token is used
|
238 |
after more testing token secret can be removed.
|
239 |
*/
|
|
|
240 |
$token = new stdClass();
|
241 |
$token->oauth_token_secret = $code['access_token'];
|
242 |
$token->oauth_token = $code['access_token'];
|
243 |
$token->account_id = $code['account_id'];
|
244 |
$token->token_type = $code['token_type'];
|
245 |
$token->uid = $code['uid'];
|
246 |
+
$token->refresh_token = $code['refresh_token'];
|
247 |
+
$token->expires_in = time() + $code['expires_in'] - 30;
|
248 |
$this->storage->set($token, 'access_token');
|
249 |
$this->storage->do_unset('upgraded');
|
250 |
|
254 |
throw new Dropbox_BadRequestException("No Dropbox Code found, will try to get one now", 400);
|
255 |
}
|
256 |
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* This function will make a request to the auth server sending the users refresh token to get a new access token
|
260 |
+
*
|
261 |
+
* @return void
|
262 |
+
*/
|
263 |
+
public function refreshAccessToken() {
|
264 |
+
global $iwp_backup_core;
|
265 |
+
|
266 |
+
$access_token = $this->storage->get('access_token');
|
267 |
+
|
268 |
+
$params = array(
|
269 |
+
'grant_type' => 'refresh_token',
|
270 |
+
'refresh_token' => $access_token->refresh_token,
|
271 |
+
);
|
272 |
+
|
273 |
+
$url = IWP_MMB_Dropbox_API::API_URL_V2 . self::ACCESS_TOKEN_METHOD;
|
274 |
+
|
275 |
+
$response = $this->fetch('POST', $url, '' , $params);
|
276 |
+
|
277 |
+
if ("200" != $response['code']) {
|
278 |
+
$iwp_backup_core->log('Failed to refresh access token error code: '.$response['code']);
|
279 |
+
return;
|
280 |
+
}
|
281 |
+
|
282 |
+
if (empty($response['body'])) {
|
283 |
+
$iwp_backup_core->log('Failed to refresh access token empty response body');
|
284 |
+
return;
|
285 |
+
}
|
286 |
+
|
287 |
+
$body = $response['body'];
|
288 |
+
|
289 |
+
if (isset($body->access_token) && isset($body->expires_in)) {
|
290 |
+
$access_token->oauth_token_secret = $body->access_token;
|
291 |
+
$access_token->oauth_token = $body->access_token;
|
292 |
+
$access_token->expires_in = time() + $body->expires_in - 30;
|
293 |
+
$this->storage->set($access_token, 'access_token');
|
294 |
+
$iwp_backup_core->log('Successfully updated and refreshed the access token');
|
295 |
+
} else {
|
296 |
+
$iwp_backup_core->log('Failed to refresh access token missing token and expiry: '.json_encode($body));
|
297 |
+
return;
|
298 |
+
}
|
299 |
+
}
|
300 |
|
301 |
/**
|
302 |
* Get the request/access token
|
305 |
* if we have not yet started the authentication process
|
306 |
* @return object stdClass
|
307 |
*/
|
308 |
+
private function getToken()
|
309 |
{
|
310 |
+
if (!$token = $this->storage->get('access_token')) {
|
311 |
+
if (!$token = $this->storage->get('request_token')) {
|
312 |
+
$token = new stdClass();
|
313 |
+
$token->oauth_token = null;
|
314 |
+
$token->oauth_token_secret = null;
|
315 |
+
}
|
316 |
+
}
|
317 |
+
return $token;
|
318 |
}
|
319 |
+
|
320 |
/**
|
321 |
* Generate signed request URL
|
322 |
* See inline comments for description
|
333 |
$token = $this->getToken();
|
334 |
|
335 |
// Prepare the standard request parameters differently for OAuth1 and OAuth2; we still need OAuth1 to make the request to the upgrade token endpoint
|
336 |
+
if (isset($token)) {
|
337 |
+
if (isset($token->oauth_token)) {
|
338 |
+
$params = array(
|
339 |
+
'access_token' => $token->oauth_token,
|
340 |
+
);
|
341 |
+
}else{
|
342 |
+
$params = array(
|
343 |
+
'access_token' => $token,
|
344 |
+
);
|
345 |
+
}
|
346 |
|
347 |
/*
|
348 |
To keep this API backwards compatible with the API v1 endpoints all v2 endpoints will also send to this method a api_v2 parameter this will then return just the access token as the signed request is not needed for any calls.
|
349 |
*/
|
350 |
|
351 |
+
if (isset($additional['api_v2']) && $additional['api_v2'] == true && !isset($additional['refresh_token'])) {
|
352 |
+
unset($additional['api_v2']);
|
353 |
+
if (isset($additional['timeout'])) unset($additional['timeout']);
|
354 |
if (isset($additional['content_download']) && $additional['content_download'] == true) {
|
355 |
unset($additional['content_download']);
|
356 |
+
$extra_headers = array();
|
357 |
+
if (isset($additional['headers'])) {
|
358 |
+
foreach ($additional['headers'] as $key => $header) {
|
359 |
+
$extra_headers[] = $header;
|
360 |
+
}
|
361 |
+
unset($additional['headers']);
|
362 |
+
}
|
363 |
$headers = array(
|
364 |
'Authorization: Bearer '.$params['access_token'],
|
365 |
'Content-Type:',
|
366 |
'Dropbox-API-Arg: '.json_encode($additional),
|
367 |
);
|
368 |
+
|
369 |
+
$headers = array_merge($headers, $extra_headers);
|
370 |
$additional = '';
|
371 |
} else if (isset($additional['content_upload']) && $additional['content_upload'] == true) {
|
372 |
unset($additional['content_upload']);
|
387 |
'postfields' => $additional,
|
388 |
'headers' => $headers,
|
389 |
);
|
390 |
+
} elseif (isset($additional['refresh_token'])) {
|
391 |
+
$extra_headers = array();
|
392 |
+
if (isset($additional['headers']) && !empty($additional['headers'])) {
|
393 |
+
foreach ($additional['headers'] as $key => $header) {
|
394 |
+
$extra_headers[] = $key.': '.$header;
|
395 |
+
}
|
396 |
+
unset($additional['headers']);
|
397 |
+
}
|
398 |
+
$headers = array();
|
399 |
+
$headers[] = 'Authorization: Basic ' . base64_encode($this->consumerKey . ':' . $this->consumerSecret);
|
400 |
+
// $headers[] = 'Content-Type: application/x-www-form-urlencoded';
|
401 |
+
// $headers[] = 'Content-Type: application/json';
|
402 |
+
$headers = array_merge($headers, $extra_headers);
|
403 |
+
|
404 |
+
return array(
|
405 |
+
'url' => $url . $call,
|
406 |
+
'postfields' => $additional,
|
407 |
+
'headers' => $headers,
|
408 |
+
);
|
409 |
}
|
410 |
} else {
|
411 |
// Generate a random string for the request
|
lib/Dropbox2/OAuth/Consumer/Curl.php
CHANGED
@@ -35,7 +35,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
35 |
* @param \Dropbox\OAuth\Consumer\StorageInterface $storage
|
36 |
* @param string $callback
|
37 |
*/
|
38 |
-
public function __construct($key, $oauth2_id, $secret, Dropbox_StorageInterface $storage, $callback = null, $callbackhome = null, $deauthenticate = false)
|
39 |
{
|
40 |
// Check the cURL extension is loaded
|
41 |
if (!extension_loaded('curl')) {
|
@@ -48,12 +48,15 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
48 |
$this->storage = $storage;
|
49 |
$this->callback = $callback;
|
50 |
$this->callbackhome = $callbackhome;
|
|
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
57 |
}
|
58 |
|
59 |
/**
|
@@ -65,11 +68,11 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
65 |
* @param array $additional Additional parameters
|
66 |
* @return string|object stdClass
|
67 |
*/
|
68 |
-
public function fetch($method, $url, $call, array $additional = array())
|
69 |
{
|
70 |
// Get the signed request URL
|
71 |
$request = $this->getSignedRequest($method, $url, $call, $additional);
|
72 |
-
|
73 |
// Initialise and execute a cURL request
|
74 |
$handle = curl_init($request['url']);
|
75 |
|
@@ -104,8 +107,6 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
104 |
}
|
105 |
}
|
106 |
}
|
107 |
-
|
108 |
-
// if (isset($request['headers'])) $options[CURLOPT_HTTPHEADER] = $request['headers'];
|
109 |
|
110 |
/*
|
111 |
Add check to see if it's an API v2 call if so then json encode the contents. This is so that it is backwards compatible with API v1 endpoints.
|
@@ -119,6 +120,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
119 |
$request['postfields'] = json_encode(null);
|
120 |
}
|
121 |
}
|
|
|
122 |
if (isset($request['headers']) && !empty($request['headers'])) $options[CURLOPT_HTTPHEADER] = $request['headers'];
|
123 |
|
124 |
if ($method == 'GET' && $this->outFile) { // GET
|
@@ -141,7 +143,15 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
141 |
$options[CURLOPT_POSTFIELDS] = $this->inFile;
|
142 |
} elseif ($method == 'POST') { // POST
|
143 |
$options[CURLOPT_POST] = true;
|
144 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
} elseif ($method == 'PUT' && $this->inFile) { // PUT
|
146 |
$options[CURLOPT_PUT] = true;
|
147 |
$options[CURLOPT_INFILE] = $this->inFile;
|
@@ -151,6 +161,10 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
151 |
$this->inFile = null;
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
154 |
// Set the cURL options at once
|
155 |
curl_setopt_array($handle, $options);
|
156 |
// Execute, get any error and close
|
@@ -167,7 +181,6 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
167 |
// Parse the response if it is a string
|
168 |
if (is_string($response)) {
|
169 |
$response = $this->parse($response);
|
170 |
-
$response['code'] = (!empty($response['code'])) ? $response['code'] : $getinfo['http_code'];
|
171 |
}
|
172 |
|
173 |
// Set the last response
|
@@ -191,12 +204,13 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
191 |
if (strpos($array[0] , 'incorrect_offset') !== false) {
|
192 |
$message = json_encode($array);
|
193 |
} elseif (strpos($array[0] , 'lookup_failed') !== false ) {
|
194 |
-
//re-structure the array so it is correctly formatted for API
|
195 |
-
//Note: Dropbox v2 returns different errors at different stages hence this fix
|
196 |
$correctOffset = array(
|
197 |
'0' => $array[1]->{'.tag'},
|
198 |
-
'1' => $array[1]->correct_offset
|
199 |
);
|
|
|
|
|
200 |
|
201 |
$message = json_encode($correctOffset);
|
202 |
} else {
|
@@ -216,6 +230,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
216 |
case 304:
|
217 |
throw new Dropbox_NotModifiedException($message, 304);
|
218 |
case 400:
|
|
|
219 |
throw new Dropbox_BadRequestException($message, 400);
|
220 |
case 404:
|
221 |
throw new Dropbox_NotFoundException($message, 404);
|
@@ -224,8 +239,8 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
224 |
case 415:
|
225 |
throw new Dropbox_UnsupportedMediaTypeException($message, 415);
|
226 |
case 401:
|
227 |
-
|
228 |
-
|
229 |
case 409:
|
230 |
//409 in API V2 every error will return with a 409 to find out what the error is the error description should be checked.
|
231 |
throw new Dropbox_Exception($message, $code);
|
@@ -253,14 +268,14 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
253 |
|
254 |
// If the status code is 100, the API server must send a final response
|
255 |
// We need to explode the response again to get the actual response
|
256 |
-
if (preg_match('#^HTTP/
|
257 |
list($headers, $response) = explode("\r\n\r\n", $response, 2);
|
258 |
$lines = explode("\r\n", $headers);
|
259 |
}
|
260 |
|
261 |
// Get the HTTP response code from the first line
|
262 |
$first = array_shift($lines);
|
263 |
-
$pattern = '#^HTTP/
|
264 |
preg_match($pattern, $first, $matches);
|
265 |
$code = $matches[1];
|
266 |
|
@@ -279,7 +294,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
|
|
279 |
|
280 |
if (is_string($body)) {
|
281 |
$body_lines = explode("\r\n", $body);
|
282 |
-
if (preg_match('#^HTTP/
|
283 |
return $this->parse($body);
|
284 |
}
|
285 |
}
|
35 |
* @param \Dropbox\OAuth\Consumer\StorageInterface $storage
|
36 |
* @param string $callback
|
37 |
*/
|
38 |
+
public function __construct($key, $oauth2_id, $secret, Dropbox_StorageInterface $storage, $callback = null, $callbackhome = null, $deauthenticate = false, $instance_id = '', $old_auth = false)
|
39 |
{
|
40 |
// Check the cURL extension is loaded
|
41 |
if (!extension_loaded('curl')) {
|
48 |
$this->storage = $storage;
|
49 |
$this->callback = $callback;
|
50 |
$this->callbackhome = $callbackhome;
|
51 |
+
$this->instance_id = $instance_id;
|
52 |
|
53 |
+
if ($old_auth == false) {
|
54 |
+
if ($deauthenticate) {
|
55 |
+
$this->deauthenticate();
|
56 |
+
} else {
|
57 |
+
$this->authenticate();
|
58 |
+
}
|
59 |
+
}
|
60 |
}
|
61 |
|
62 |
/**
|
68 |
* @param array $additional Additional parameters
|
69 |
* @return string|object stdClass
|
70 |
*/
|
71 |
+
public function fetch($method, $url, $call, array $additional = array(), $retry_with_header = false)
|
72 |
{
|
73 |
// Get the signed request URL
|
74 |
$request = $this->getSignedRequest($method, $url, $call, $additional);
|
75 |
+
|
76 |
// Initialise and execute a cURL request
|
77 |
$handle = curl_init($request['url']);
|
78 |
|
107 |
}
|
108 |
}
|
109 |
}
|
|
|
|
|
110 |
|
111 |
/*
|
112 |
Add check to see if it's an API v2 call if so then json encode the contents. This is so that it is backwards compatible with API v1 endpoints.
|
120 |
$request['postfields'] = json_encode(null);
|
121 |
}
|
122 |
}
|
123 |
+
|
124 |
if (isset($request['headers']) && !empty($request['headers'])) $options[CURLOPT_HTTPHEADER] = $request['headers'];
|
125 |
|
126 |
if ($method == 'GET' && $this->outFile) { // GET
|
143 |
$options[CURLOPT_POSTFIELDS] = $this->inFile;
|
144 |
} elseif ($method == 'POST') { // POST
|
145 |
$options[CURLOPT_POST] = true;
|
146 |
+
if (!empty($request['postfields'])) {
|
147 |
+
$options[CURLOPT_POSTFIELDS] = $request['postfields'];
|
148 |
+
} elseif (empty($additional['content_upload'])) {
|
149 |
+
// JSON representation of nullity
|
150 |
+
$options[CURLOPT_POSTFIELDS] = 'null';
|
151 |
+
} elseif ($retry_with_header) {
|
152 |
+
// It's a content upload, and there's no data. Versions of php-curl differ as to whether they add a Content-Length header automatically or not. Dropbox complains if it's not there. Here we have had a Dropbox 400 bad request returned so we try again with the header
|
153 |
+
$options[CURLOPT_HTTPHEADER] = array_merge($options[CURLOPT_HTTPHEADER], array('Content-Length: 0'));
|
154 |
+
}
|
155 |
} elseif ($method == 'PUT' && $this->inFile) { // PUT
|
156 |
$options[CURLOPT_PUT] = true;
|
157 |
$options[CURLOPT_INFILE] = $this->inFile;
|
161 |
$this->inFile = null;
|
162 |
}
|
163 |
|
164 |
+
if (isset($additional['timeout'])) {
|
165 |
+
$options[CURLOPT_TIMEOUT] = $additional['timeout'];
|
166 |
+
}
|
167 |
+
|
168 |
// Set the cURL options at once
|
169 |
curl_setopt_array($handle, $options);
|
170 |
// Execute, get any error and close
|
181 |
// Parse the response if it is a string
|
182 |
if (is_string($response)) {
|
183 |
$response = $this->parse($response);
|
|
|
184 |
}
|
185 |
|
186 |
// Set the last response
|
204 |
if (strpos($array[0] , 'incorrect_offset') !== false) {
|
205 |
$message = json_encode($array);
|
206 |
} elseif (strpos($array[0] , 'lookup_failed') !== false ) {
|
207 |
+
// re-structure the array so it is correctly formatted for API
|
208 |
+
// Note: Dropbox v2 returns different errors at different stages hence this fix
|
209 |
$correctOffset = array(
|
210 |
'0' => $array[1]->{'.tag'},
|
|
|
211 |
);
|
212 |
+
// the lookup_failed response doesn't always return a correct_offset this happens when the lookup fails because the session has been closed e.g the file has already been uploaded but the response didn't make it back to the client so we try again
|
213 |
+
if (isset($array[1]->correct_offset)) $correctOffset['1'] = $array[1]->correct_offset;
|
214 |
|
215 |
$message = json_encode($correctOffset);
|
216 |
} else {
|
230 |
case 304:
|
231 |
throw new Dropbox_NotModifiedException($message, 304);
|
232 |
case 400:
|
233 |
+
if (!$retry_with_header) return $this->fetch($method, $url, $call, $additional, true);
|
234 |
throw new Dropbox_BadRequestException($message, 400);
|
235 |
case 404:
|
236 |
throw new Dropbox_NotFoundException($message, 404);
|
239 |
case 415:
|
240 |
throw new Dropbox_UnsupportedMediaTypeException($message, 415);
|
241 |
case 401:
|
242 |
+
//401 means oauth token is expired continue to manually handle the exception depending on the situation
|
243 |
+
break;
|
244 |
case 409:
|
245 |
//409 in API V2 every error will return with a 409 to find out what the error is the error description should be checked.
|
246 |
throw new Dropbox_Exception($message, $code);
|
268 |
|
269 |
// If the status code is 100, the API server must send a final response
|
270 |
// We need to explode the response again to get the actual response
|
271 |
+
if (preg_match('#^HTTP/[\.\d]+ 100#i', $lines[0])) {
|
272 |
list($headers, $response) = explode("\r\n\r\n", $response, 2);
|
273 |
$lines = explode("\r\n", $headers);
|
274 |
}
|
275 |
|
276 |
// Get the HTTP response code from the first line
|
277 |
$first = array_shift($lines);
|
278 |
+
$pattern = '#^HTTP/[\.\d]+ ([0-9]{3})#i';
|
279 |
preg_match($pattern, $first, $matches);
|
280 |
$code = $matches[1];
|
281 |
|
294 |
|
295 |
if (is_string($body)) {
|
296 |
$body_lines = explode("\r\n", $body);
|
297 |
+
if (preg_match('#^HTTP/[\.\d]+ 100#i', $body_lines[0]) && preg_match('#^HTTP/\d#i', $body_lines[2])) {
|
298 |
return $this->parse($body);
|
299 |
}
|
300 |
}
|
lib/Dropbox2/OAuth/Consumer/WordPress.php
CHANGED
@@ -2,7 +2,6 @@
|
|
2 |
|
3 |
/**
|
4 |
* OAuth consumer using the WordPress API
|
5 |
-
* @author David Anderson <david@updraftplus.com>
|
6 |
* @link https://github.com/DavidAnderson684/Dropbox
|
7 |
* @package Dropbox\OAuth
|
8 |
* @subpackage Consumer
|
2 |
|
3 |
/**
|
4 |
* OAuth consumer using the WordPress API
|
|
|
5 |
* @link https://github.com/DavidAnderson684/Dropbox
|
6 |
* @package Dropbox\OAuth
|
7 |
* @subpackage Consumer
|
lib/Dropbox2/OAuth/Storage/Encrypter.php
CHANGED
@@ -9,14 +9,6 @@
|
|
9 |
* @subpackage Storage
|
10 |
*/
|
11 |
|
12 |
-
/*
|
13 |
-
Using this was fairly pointless (it encrypts storage credentials at rest). But, it's implemented now, so needs supporting.
|
14 |
-
Investigation shows that mcrypt and phpseclib native encryption using different padding schemes.
|
15 |
-
As a result, that which is encrypted by phpseclib native can be decrypted by mcrypt, but not vice-versa. Each can (as you'd expect) decrypt the results of their own encryption.
|
16 |
-
As a consequence, it makes sense to always encrypt with phpseclib native, and prefer decrypting with with mcrypt if it is available and otherwise fall back to phpseclib.
|
17 |
-
We could deliberately re-encrypt all loaded information with phpseclib native, but there seems little need for that yet. There can only be a problem if mcrypt is disabled - which pre-July-2015 meant that Dropbox wouldn't work at all. Now, it will force a re-authorisation.
|
18 |
-
*/
|
19 |
-
|
20 |
class Dropbox_Encrypter
|
21 |
{
|
22 |
// Encryption settings - default settings yield encryption to AES (256-bit) standard
|
@@ -57,12 +49,18 @@ class Dropbox_Encrypter
|
|
57 |
{
|
58 |
|
59 |
// Encryption: we always use phpseclib for this
|
60 |
-
|
61 |
global $iwp_backup_core;
|
62 |
-
$iwp_backup_core->ensure_phpseclib('Crypt_AES'
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
-
if (!function_exists('crypt_random_string')) require_once($GLOBALS['iwp_mmb_plugin_dir'].'/
|
66 |
|
67 |
$iv = crypt_random_string(self::IV_SIZE);
|
68 |
|
@@ -93,10 +91,11 @@ class Dropbox_Encrypter
|
|
93 |
$cipherText = substr($cipherText, self::IV_SIZE);
|
94 |
|
95 |
if (function_exists('mcrypt_decrypt')) {
|
|
|
96 |
$token = @mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key, $cipherText, MCRYPT_MODE_CBC, $iv);
|
97 |
} else {
|
98 |
global $iwp_backup_core;
|
99 |
-
$iwp_backup_core->ensure_phpseclib('Crypt_Rijndael'
|
100 |
|
101 |
$rijndael = new Crypt_Rijndael();
|
102 |
$rijndael->setKey($this->key);
|
9 |
* @subpackage Storage
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
class Dropbox_Encrypter
|
13 |
{
|
14 |
// Encryption settings - default settings yield encryption to AES (256-bit) standard
|
49 |
{
|
50 |
|
51 |
// Encryption: we always use phpseclib for this
|
|
|
52 |
global $iwp_backup_core;
|
53 |
+
$ensure_phpseclib = $iwp_backup_core->ensure_phpseclib('Crypt_AES');
|
54 |
+
|
55 |
+
if (is_wp_error($ensure_phpseclib)) {
|
56 |
+
$iwp_backup_core->log("Failed to load phpseclib classes (".$ensure_phpseclib->get_error_code()."): ".$ensure_phpseclib->get_error_message());
|
57 |
+
$iwp_backup_core->log("Failed to load phpseclib classes (".$ensure_phpseclib->get_error_code()."): ".$ensure_phpseclib->get_error_message(), 'error');
|
58 |
+
return false;
|
59 |
+
}
|
60 |
+
|
61 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Rijndael');
|
62 |
|
63 |
+
if (!function_exists('crypt_random_string')) require_once($GLOBALS['iwp_mmb_plugin_dir'].'/lib/phpseclib/phpseclib/phpseclib/Crypt/Random.php');
|
64 |
|
65 |
$iv = crypt_random_string(self::IV_SIZE);
|
66 |
|
91 |
$cipherText = substr($cipherText, self::IV_SIZE);
|
92 |
|
93 |
if (function_exists('mcrypt_decrypt')) {
|
94 |
+
// @codingStandardsIgnoreLine
|
95 |
$token = @mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key, $cipherText, MCRYPT_MODE_CBC, $iv);
|
96 |
} else {
|
97 |
global $iwp_backup_core;
|
98 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Rijndael');
|
99 |
|
100 |
$rijndael = new Crypt_Rijndael();
|
101 |
$rijndael->setKey($this->key);
|
lib/Dropbox2/OAuth/Storage/WordPress.php
CHANGED
@@ -4,8 +4,6 @@
|
|
4 |
* OAuth storage handler using WordPress options
|
5 |
* This can only be used if you have a WordPress environment loaded, such that the (get|update|delete)_option functions are available
|
6 |
* See an example usage in http://wordpress.org/extend/plugins/updraftplus
|
7 |
-
* @author David Anderson <david@updraftplus.com>
|
8 |
-
* @link https://updraftplus.com
|
9 |
* @package Dropbox\Oauth
|
10 |
* @subpackage Storage
|
11 |
*/
|
@@ -46,9 +44,7 @@ class Dropbox_WordPress implements Dropbox_StorageInterface
|
|
46 |
$this->encrypter = $encrypter;
|
47 |
}
|
48 |
|
49 |
-
|
50 |
-
$this->backup_module_object = $backup_module_object;
|
51 |
-
}
|
52 |
|
53 |
$this->option_name_prefix = $option_name_prefix;
|
54 |
$this->option_array = $option_array;
|
@@ -70,7 +66,11 @@ class Dropbox_WordPress implements Dropbox_StorageInterface
|
|
70 |
if ($type == 'request_token' || $type == 'access_token'){
|
71 |
if (!empty($opts[$this->option_name_prefix.$type])) {
|
72 |
$gettoken = $opts[$this->option_name_prefix.$type];
|
73 |
-
$
|
|
|
|
|
|
|
|
|
74 |
return $token;
|
75 |
}
|
76 |
} else {
|
@@ -99,7 +99,9 @@ class Dropbox_WordPress implements Dropbox_StorageInterface
|
|
99 |
$opts = $this->backup_module_object->get_options();
|
100 |
|
101 |
if ($type == 'access_token'){
|
102 |
-
|
|
|
|
|
103 |
$opts[$this->option_name_prefix.$type] = $token;
|
104 |
} else if ($type == 'request_token' ) {
|
105 |
$opts[$this->option_name_prefix.$type] = $token;
|
4 |
* OAuth storage handler using WordPress options
|
5 |
* This can only be used if you have a WordPress environment loaded, such that the (get|update|delete)_option functions are available
|
6 |
* See an example usage in http://wordpress.org/extend/plugins/updraftplus
|
|
|
|
|
7 |
* @package Dropbox\Oauth
|
8 |
* @subpackage Storage
|
9 |
*/
|
44 |
$this->encrypter = $encrypter;
|
45 |
}
|
46 |
|
47 |
+
$this->backup_module_object = $backup_module_object;
|
|
|
|
|
48 |
|
49 |
$this->option_name_prefix = $option_name_prefix;
|
50 |
$this->option_array = $option_array;
|
66 |
if ($type == 'request_token' || $type == 'access_token'){
|
67 |
if (!empty($opts[$this->option_name_prefix.$type])) {
|
68 |
$gettoken = $opts[$this->option_name_prefix.$type];
|
69 |
+
if (!empty($opts['email'])) {
|
70 |
+
$token = $this->decrypt($gettoken);
|
71 |
+
}else{
|
72 |
+
$token = $gettoken;
|
73 |
+
}
|
74 |
return $token;
|
75 |
}
|
76 |
} else {
|
99 |
$opts = $this->backup_module_object->get_options();
|
100 |
|
101 |
if ($type == 'access_token'){
|
102 |
+
if (!empty($opts['email'])) {
|
103 |
+
$token = $this->encrypt($token);
|
104 |
+
}
|
105 |
$opts[$this->option_name_prefix.$type] = $token;
|
106 |
} else if ($type == 'request_token' ) {
|
107 |
$opts[$this->option_name_prefix.$type] = $token;
|
lib/sftp.php
CHANGED
@@ -335,6 +335,8 @@ class IWP_MMB_RemoteStorage_sftp extends IWP_MMB_RemoteStorage_Extension {
|
|
335 |
}
|
336 |
}
|
337 |
|
|
|
|
|
338 |
if (!$this->ssh->login($user, $pass)) {
|
339 |
$error_data = null;
|
340 |
$message = 'SSH 2 login failed';
|
335 |
}
|
336 |
}
|
337 |
|
338 |
+
// Ensure phpseclib Crypt_Blowfish is loaded, over PEAR's
|
339 |
+
$iwp_backup_core->ensure_phpseclib('Crypt_Blowfish', 'Crypt/Blowfish');
|
340 |
if (!$this->ssh->login($user, $pass)) {
|
341 |
$error_data = null;
|
342 |
$message = 'SSH 2 login failed';
|
pclzip.class.php
CHANGED
@@ -3440,7 +3440,11 @@ endif;
|
|
3440 |
}
|
3441 |
|
3442 |
// ----- Read the file content
|
|
|
3443 |
$v_content = @fread($v_file, $p_header['size']);
|
|
|
|
|
|
|
3444 |
|
3445 |
// ----- Close the file
|
3446 |
@fclose($v_file);
|
3440 |
}
|
3441 |
|
3442 |
// ----- Read the file content
|
3443 |
+
if ($p_header['size'] > 0) {
|
3444 |
$v_content = @fread($v_file, $p_header['size']);
|
3445 |
+
}else{
|
3446 |
+
$v_content = '';
|
3447 |
+
}
|
3448 |
|
3449 |
// ----- Close the file
|
3450 |
@fclose($v_file);
|
plugin.compatibility.class.php
CHANGED
@@ -139,9 +139,9 @@ class IWP_MMB_FixCompatibility
|
|
139 |
return null;
|
140 |
}
|
141 |
|
142 |
-
public function
|
143 |
{
|
144 |
-
if (!
|
145 |
$GLOBALS['hook_suffix'] = null;
|
146 |
}
|
147 |
}
|
139 |
return null;
|
140 |
}
|
141 |
|
142 |
+
public function fixGlobals()
|
143 |
{
|
144 |
+
if (!isset($GLOBALS['hook_suffix'])) {
|
145 |
$GLOBALS['hook_suffix'] = null;
|
146 |
}
|
147 |
}
|
readme.txt
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
=== InfiniteWP Client ===
|
2 |
-
Contributors: infinitewp
|
3 |
Tags: admin, administration, amazon, api, authentication, automatic, dashboard, dropbox, events, integration, manage, multisite, multiple, notification, performance, s3, security, seo, stats, tracking, infinitewp, updates, backup, restore, iwp, infinite
|
4 |
Requires at least: 3.1
|
5 |
-
Tested up to: 5.
|
6 |
Stable tag: trunk
|
7 |
|
8 |
Install this plugin on unlimited sites and manage them all from a central dashboard.
|
@@ -48,6 +48,16 @@ Credits: [Vladimir Prelovac](http://prelovac.com/vladimir) for his worker plugin
|
|
48 |
|
49 |
== Changelog ==
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
= 1.9.4.11 - Jun 16th 2021 =
|
52 |
* Improvement: Amazon s3 library updated.
|
53 |
* Improvement: Wordfence data not correctly showing in Client report due to the Wordfence recent release.
|
1 |
=== InfiniteWP Client ===
|
2 |
+
Contributors: infinitewp, amritanandh, rajkuppus
|
3 |
Tags: admin, administration, amazon, api, authentication, automatic, dashboard, dropbox, events, integration, manage, multisite, multiple, notification, performance, s3, security, seo, stats, tracking, infinitewp, updates, backup, restore, iwp, infinite
|
4 |
Requires at least: 3.1
|
5 |
+
Tested up to: 5.9
|
6 |
Stable tag: trunk
|
7 |
|
8 |
Install this plugin on unlimited sites and manage them all from a central dashboard.
|
48 |
|
49 |
== Changelog ==
|
50 |
|
51 |
+
= 1.9.6 - Feb 14th 2022 =
|
52 |
+
* Feature: Added support for Litespeed Cache.
|
53 |
+
* Improvement: Ensure phpseclib Crypt_Blowfish is loaded over PEAR’s version.
|
54 |
+
* Improvement: Enabled support for new Dropbox OAuth Authentication.
|
55 |
+
* Fix: Enabled version number for InfiniteWP MU plugin loader.
|
56 |
+
* Fix: Undefined array key “hook_suffix” warning.
|
57 |
+
* Fix: Delete SFTP test backup file on the remote server.
|
58 |
+
* Fix: PPL addon editor image not uploaded. (issue happening from 1.9.4.9).
|
59 |
+
* Fix: Fatal error while backing up a 0kb file using the single call method on site installed on site with php8 server.
|
60 |
+
|
61 |
= 1.9.4.11 - Jun 16th 2021 =
|
62 |
* Improvement: Amazon s3 library updated.
|
63 |
* Improvement: Wordfence data not correctly showing in Client report due to the Wordfence recent release.
|