UPDRAFTPLUS_URL.'/images/pcloud-logo.png',
'storage_image_title' => __(sprintf(__('%s logo', 'updraftplus'), $updraftplus->backup_methods[$this->get_id()])),
'storage_long_description' => wp_kses(sprintf(__('Please read %s for use of our %s authorization app (none of your backup data is sent to us).', 'updraftplus'), ''.__('this privacy policy', 'updraftplus').'', $updraftplus->backup_methods[$this->get_id()]), $this->allowed_html_for_content_sanitisation()),
'authentication_label' => sprintf(__('Authenticate with %s', 'updraftplus'), $updraftplus->backup_methods[$this->get_id()]),
'already_authenticated_label' => __('(You are already authenticated).', 'updraftplus'),
'deauthentication_link_text' => sprintf(__("Follow this link to remove these settings for %s.", 'updraftplus'), $updraftplus->backup_methods[$this->get_id()]),
'authentication_link_text' => wp_kses(sprintf(__("After you have saved your settings (by clicking 'Save Changes' below), then come back here and follow this link to complete authentication with %s.", 'updraftplus'), $updraftplus->backup_methods[$this->get_id()]), $this->allowed_html_for_content_sanitisation()),
'deauthentication_nonce' => wp_create_nonce($this->get_id().'_deauth_nonce'),
);
return wp_parse_args($properties, $this->get_persistent_variables_and_methods());
}
/**
* Modifies handerbar template options
*
* @param array $opts
* @return Array - Modified handerbar template options
*/
public function transform_options_for_template($opts) {
if (!empty($opts['pclauth'])) {
$opts['ownername'] = empty($opts['ownername']) ? '' : $opts['ownername'];
if ($opts['ownername']) {
$opts['ownername_sentence'] = sprintf(__("Account holder's name: %s.", 'updraftplus'), $opts['ownername']).' ';
}
$opts['is_authenticated'] = true;
}
$opts['folder_path'] = apply_filters('updraftplus_pcloud_backup_dir', 'UpdraftPlus').'/';
$opts = apply_filters("updraftplus_options_pcloud_options", $opts);
return $opts;
}
/**
* Gives settings keys which values should not passed to handlebarsjs context.
* The settings stored in UD in the database sometimes also include internal information that it would be best not to send to the front-end (so that it can't be stolen by a man-in-the-middle attacker)
*
* @return Array - Settings array keys which should be filtered
*/
public function filter_frontend_settings_keys() {
return array(
'ownername',
'pclauth',
);
}
/**
* Over-rides the parent to allow this method to output extra information about using the correct account for OAuth authentication
*
* @return false
*/
public function output_account_warning() {
return false;
}
/**
* Handles various URL actions, as indicated by the updraftplus_pcloudauth URL parameter
*
* @return null
*/
public function action_auth() {
if (isset($_GET['updraftplus_pcloudauth'])) {
if ('doit' == stripslashes($_GET['updraftplus_pcloudauth'])) {
$this->action_authenticate_storage();
return;
} elseif ('deauth' == stripslashes($_GET['updraftplus_pcloudauth'])) {
$this->action_deauthenticate_storage();
return;
}
} elseif (isset($_REQUEST['state'])) {
$parts = explode(':', stripslashes($_GET['state']));
$state = $parts[0];
if ('success' == $state) {
$raw_state = stripslashes($_GET['state']);
if (isset($_GET['code'])) $raw_code = urldecode(stripslashes($_GET['code']));
$this->do_complete_authentication($raw_state, $raw_code);
}
}
}
/**
* Acquire single-use authorization code from pCloud via OAuth 2.0
*
* @param String $instance_id - the instance id of the settings we want to authenticate
*/
public function do_authenticate_storage($instance_id) {
$opts = $this->get_options();
// Set a flag so we know this authentication is in progress
$opts['auth_in_progress'] = true;
$this->set_options($opts, true);
$prefixed_instance_id = ':' . $instance_id;
$token = 'token'.$prefixed_instance_id.UpdraftPlus_Options::admin_page_url().'?action=updraftmethod-pcloud-auth';
$params = array(
'response_type' => 'code',
'client_id' => $this->client_id,
'redirect_uri' => $this->callback_url,
'state' => $token,
'access_type' => 'offline',
'force_reapprove' => 'true',
'returnqueryparams' => 1
);
if (headers_sent()) {
$this->log(sprintf(__('The %s authentication could not go ahead, because something else on your site is breaking it. Try disabling your other plugins and switching to a default theme. (Specifically, you are looking for the component that sends output (most likely PHP warnings/errors) before the page begins. Turning off any debugging settings may also help).', ''), 'pCloud'), 'error');
} else {
header('Location: https://my.pcloud.com/oauth2/authorize?'.http_build_query($params, null, '&'));
}
}
/**
* This function will complete the oAuth flow, if return_instead_of_echo is true then add the action to display the authed admin notice, otherwise echo this notice to page.
*
* @param string $state - the state
* @param string $code - the oauth code
* @param boolean $return_instead_of_echo - a boolean to indicate if we should return the result or echo it
*
* @return void|string - returns the authentication message if return_instead_of_echo is true
*/
public function do_complete_authentication($state, $code, $return_instead_of_echo = false) {
$code = json_decode(base64_decode($code), true);
if (!is_bool($code) && isset($code['access_token']) && 30 < strlen($code['access_token']) && isset($code['locationid'])) {
$opts = $this->get_options();
$opts['pclauth'] = $code['access_token'];
$opts['pcllocation'] = $code['locationid'];
// remove our flag so we know this authentication is complete
if (isset($opts['auth_in_progress'])) unset($opts['auth_in_progress']);
$this->set_options($opts, true);
}
if ($return_instead_of_echo) {
return $this->show_authed_admin_success($return_instead_of_echo);
} else {
add_action('all_admin_notices', array($this, 'show_authed_admin_success'));
}
}
/**
* This method will setup the authenticated admin notice, it can either return this or echo it
*
* @param boolean $return_instead_of_echo - a boolean to indicate if we should return the result or echo it
*
* @return void|string - returns the authentication message if return_instead_of_echo is true
*/
public function show_authed_admin_success($return_instead_of_echo) {
global $updraftplus_admin;
try {
$pcloud = $this->bootstrap();
$info = $pcloud->account_info();
if (is_wp_error($info)) {
$this->log('pCloud ('.$info->get_error_code().'): '.$info->get_error_message(), 'error');
}
} catch (Exception $e) {
$accountinfo_err = sprintf(__("%s error: %s", 'updraftplus'), 'pCloud', $e->getMessage()).' ('.$e->getCode().')';
$this->log('pCloud error: ' . $e->getMessage() . ' (line: ' . $e->getLine() . ', file: ' . $e->getFile() . ')');
$this->log(sprintf(__('error: %s (see log file for more)', 'updraftplus'), $e->getMessage()), 'error');
}
$message = "".__('Success:', 'updraftplus').' '.sprintf(__('you have authenticated your %s account', 'updraftplus'), 'pCloud');
if (isset($info['quota']) || isset($info['usedquota']) || isset($info['email'])) {
$available_quota = $info['quota'] - $info['usedquota'];
$used_perc = round($info['usedquota']*100/$info['quota'], 1);
$opts = $this->get_options();
$opts['ownername'] = $info['email'];
$this->set_options($opts, true);
$message .= ". ".sprintf(__('Your %s account name: %s', 'updraftplus'), 'pCloud', htmlspecialchars($info['email']));
$message .= ' '.sprintf(__('Your %s quota usage: %s %% used, %s available', 'updraftplus'), 'pCloud', $used_perc, round($available_quota/1048576, 1).' MB');
} else {
$message .= " (".__('though part of the returned information was not as expected - whether this indicates a real problem cannot be determined', 'updraftplus').")";
if (!empty($accountinfo_err)) $message .= " ".htmlspecialchars($accountinfo_err);
}
if ($return_instead_of_echo) {
return "
{$message}
";
} else {
$updraftplus_admin->show_admin_warning($message);
}
}
/**
* This basically reproduces the relevant bits of bootstrap.php from the SDK
*
* @return object
* @throws Exception Throws standart exception.
*/
public function bootstrap() {
if (!class_exists('UpdraftPlus_Pcloud_API')) {
include_once UPDRAFTPLUS_DIR . '/includes/pcloud/UpdraftPlus_Pcloud_API.php';
}
// if (false === $opts) $opts = $this->options;
// $opts = $this->get_options();
$storage = $this->get_storage();
if (!empty($storage) && !is_wp_error($storage)) {
return $storage;
}
$opts = $this->get_options();
$pclauth = !empty($opts['pclauth']) ? $opts['pclauth'] : '';
$pcllocation = !empty($opts['pcllocation']) ? intval($opts['pcllocation']) : '';
if (empty($pclauth) || 20 > strlen($pclauth)) {
throw new Exception('You are not logged in.');
}
$storage = new UpdraftPlus_Pcloud_API();
$storage->set_auth($pclauth);
$storage->set_location($pcllocation);
$storage->set_folder($opts['folder']);
if (empty($opts['folderid'])) {
$folder_id = $storage->get_upload_dir_id();
if (is_wp_error($folder_id)) $this->log('pCloud ('.$folder_id->get_error_code().'): '.$folder_id->get_error_message(), 'error');
if (is_numeric($folder_id) && 0 < $folder_id) {
$opts['folderid'] = $folder_id;
}
$this->set_options($opts, true);
} else {
$folder_id = intval($opts['folderid']);
}
if (empty($folder_id) || 10 > $folder_id) $this->log('pCloud error: Failed to get folder id; backup will be uploaded to the root directory');
$this->set_storage($storage);
return $storage;
}
}