slug = $slug; $this->title = $title; $this->mother = $mother; // We are called in admin_menu // $this->options_menu(); // New actions to output the tab title and content // add_action('updraftplus_settings_afternavtabs', array($this, 'settings_afternavtabs')); add_filter('updraftplus_addonstab_content', array($this, 'updraftplus_addonstab_content')); add_filter('updraftplus_com_login_options', array($this, 'updraftplus_com_login_options')); add_action('admin_init', array($this, 'show_admin_notices')); add_action('admin_init', array($this, 'options_init')); register_activation_hook(UDADDONS2_SLUG, array($this, 'options_setdefaults')); add_filter((is_multisite() ? 'network_admin_' : '').'plugin_action_links', array($this, 'action_links'), 10, 2); global $updraftplus_addons2; $this->options = $updraftplus_addons2; } /** * Return the content of the addons tab * * @param string $content - the addons tab content * @return string - the addons tab content */ public function updraftplus_addonstab_content($content) { ob_start(); $this->options_printpage(); echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escape late; we don't do it here because we want it to happen at caller's side return ob_get_clean(); } /** * Registers any admin page notices. Runs upon admin_init. */ public function show_admin_notices() { global $pagenow; if (apply_filters('updraftplus_settings_page_render', true)) { $options = $this->options->get_option(UDADDONS2_SLUG.'_options'); if (empty($options['email']) && UpdraftPlus_Options::user_can_manage() && isset($_REQUEST['page']) && 'updraftplus' == $_REQUEST['page']) { add_action('all_admin_notices', array($this, 'show_admin_warning_notconnected')); } } if ((is_multisite() && 'settings.php' == $pagenow) || (!is_multisite() && 'options-general.php' == $pagenow) && isset($_REQUEST['page']) && (UDADDONS2_PAGESLUG == $_REQUEST['page'] || $_REQUEST['page'] == $this->slug)) { $updates_available = get_site_transient('update_plugins'); global $updraftplus_addons2; if (is_object($updates_available) && isset($updates_available->response) && isset($updraftplus_addons2->plug_updatechecker) && isset($updraftplus_addons2->plug_updatechecker->pluginFile) && isset($updates_available->response[$updraftplus_addons2->plug_updatechecker->pluginFile])) { $file = $updraftplus_addons2->plug_updatechecker->pluginFile; $this->plugin_update_url = wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&updraftplus_noautobackup=1&plugin=').$file, 'upgrade-plugin_'.$file); add_action('all_admin_notices', array($this, 'show_admin_warning_update')); } } } /** * Echoes a div with a WP dashboard admin message in it * * @param String $message - the message text (this is unescaped string which allows HTML tags to be included but only tags that are allowed by wp_kses_post()) * @param String $class - the CSS class for the div */ private function show_admin_warning($message, $class = "updated") { echo '
'."

".wp_kses_post($message)."

"; } /** * Show an administrative warning about the available updates of UpdraftPlus */ public function show_admin_warning_update() { global $updraftplus_addons2; if ($updraftplus_addons2->connection_status()) { $msg = ''.esc_html__('An update is available for UpdraftPlus - please follow this link to get it.', 'updraftplus').''; } else { $msg = ''.esc_html__('An update is available for UpdraftPlus - please connect here to gain access to it.', 'updraftplus').''; } $this->show_admin_warning($msg); } public function show_admin_warning_notconnected() { $this->show_admin_warning(esc_html(__('You have not yet connected the UpdraftPlus plugin to your UpdraftPlus licence.', 'updraftplus')).' '.esc_html__('Connect to your account.', 'updraftplus').''); } public function show_admin_warning_noupdraftplus() { if (is_file(WP_PLUGIN_DIR.'/updraftplus/updraftplus.php')) { global $pagenow; $msg = esc_html__('UpdraftPlus is not yet activated.', 'updraftplus'); if ('plugins.php' != $pagenow) $msg .= ' '.esc_html__('Go here to activate it.', 'updraftplus').''; $this->show_admin_warning($msg); } else { $warning = esc_html__('UpdraftPlus is not yet installed.', 'updraftplus').' '.esc_html__('Go here to begin installing it.', 'updraftplus').''; if (file_exists(WP_PLUGIN_DIR.'/updraft')) $warning .= ' '.esc_html__('You do seem to have the obsolete Updraft plugin installed - perhaps you got them confused?', 'updraftplus'); $this->show_admin_warning($warning); } } /** * Output a notice suitable for the dashboard warning that PHP is too old. */ public function show_admin_warning_php() { $this->show_admin_warning(esc_html(sprintf(__("Your web server's version of PHP is too old (%s) - UpdraftPlus expects at least %s.", 'updraftplus'), PHP_VERSION, '5.2.4').' '.__("You can try it, but don't be surprised if it does not work.", 'updraftplus').' '.__("To fix this problem, contact your web hosting company.", 'updraftplus')), 'error'); } /** * Registered under admin_init */ public function options_init() { // Register a new set of options, named $slug_options, stored in the database entry $slug_options // We register and use the printing facilities for multisite too register_setting(UDADDONS2_SLUG.'_options', UDADDONS2_SLUG.'_options', array($this, 'options_validate')); if (is_multisite() && (isset($_POST['action']) && 'update' == $_POST['action']) && !empty($_POST['updraftplus-addons_options'])) { $this->update_wpmu_options(); } } public function options_setdefaults() { $tmp = $this->options->get_option(UDADDONS2_SLUG.'_options'); if (!is_array($tmp)) { $arr = array( "email" => "", "password" => "" ); $this->options->update_option(UDADDONS2_SLUG.'_options', $arr); } } /** * This function is registered via register_setting. It is intended to return sanitised output, and can optionally call add_settings_error to whinge about anything faulty * * @param array $input * @return array */ public function options_validate($input) { // When the options are re-saved, clear any previous cache of the connection status $ehash = substr(md5($input['email']), 0, 23); delete_site_transient('udaddons_connect_'.$ehash); return $input; } /** * Return an array of errors (if any); * * @return array */ public function update_wpmu_options() { if (!UpdraftPlus_Options::user_can_manage()) return; $options = $this->options->get_option(UDADDONS2_SLUG.'_options'); if (!is_array($options)) $options = array(); foreach ($_POST as $key => $value) { if ('updraftplus-addons_options' == $key && is_array($value) && isset($value['email']) && isset($value['password'])) { $options['email'] = $value['email']; $options['password'] = $value['password']; } } $options = $this->options_validate($options); $this->options->update_option(UDADDONS2_SLUG.'_options', $options); } /** * This function will return the saved options and if there are none returns the default options passed in. * * @param array $default_options - an array that includes the default options * * @return array - returns an array of options */ public function updraftplus_com_login_options($default_options) { $options = $this->options->get_option(UDADDONS2_SLUG.'_options'); return is_array($options) ? $options : $default_options; } /** * This is the function outputting the HTML for our options page */ public function options_printpage() { if (!UpdraftPlus_Options::user_can_manage()) wp_die(esc_html__('You do not have sufficient permissions to access this page.')); $options = $this->options->get_option(UDADDONS2_SLUG.'_options'); echo "\t
\n"; global $updraftplus_addons2, $updraftplus_admin, $updraftplus; $this->connected = !empty($options['email']) ? $updraftplus_addons2->connection_status() : false; if (true !== $this->connected) { if (is_wp_error($this->connected)) { $connection_errors = array(); foreach ($this->connected->get_error_messages() as $key => $msg) { $connection_errors[] = $msg; } } else { if (!empty($options['email']) && !empty($options['password'])) $connection_errors = array(esc_html__('An unknown error occurred when trying to connect to UpdraftPlus.Com', 'updraftplus')); } $this->connected = false; } if ('updraftplus' != basename(dirname(dirname(__FILE__)))) { echo '

'.esc_html__('Error', 'updraftplus').': '.sprintf(esc_html__("You have installed this plugin in your plugins folder (%s) with a non-default name %s which is different to %s.", 'updraftplus'), esc_html(WP_PLUGIN_DIR), ''.esc_html(basename(dirname(dirname(__FILE__)))).'', 'updraftplus').' '.esc_html__("This is incompatible with WordPress's updates mechanism; you will not be able to receive updates.", 'updraftplus').'

'; } if (defined('WP_HTTP_BLOCK_EXTERNAL') && WP_HTTP_BLOCK_EXTERNAL) { echo '

'.sprintf(esc_html__('Please make sure that %s is not set to "true" in your wp-config file - this ensures UpdraftPlus can connect and update.', 'updraftplus'), 'WP_HTTP_BLOCK_EXTERNAL').'

'; } $wp_http = new WP_Http(); if (is_callable(array($wp_http, 'block_request')) && $wp_http->block_request($updraftplus_addons2->url)) { echo '

'.sprintf(esc_html__('Please list %s in the %s constant.', 'updraftplus'), 'updraftplus.com', 'WP_ACCESSIBLE_HOSTS').' '.sprintf(esc_html__('This ensures %s can connect and update.', 'updraftplus'), 'UpdraftPlus').'

'; } if ($this->connected) { /* translators: %s: Plugin's connection status (it's either connected or not connected) */ echo '

'.sprintf(esc_html__('You are presently %s to a TeamUpdraft account.', 'updraftplus'), ''. esc_html__('connected', 'updraftplus').'').'

'; echo '

'; // Not translated; it's only seen in development if (false === strpos($this->mother, '//updraftplus.com')) echo ' (Updates URL: '.esc_url($this->mother).').'; echo ' '.esc_html__('If you bought new add-ons, then follow this link to refresh your connection', 'updraftplus').'.'; if (!empty($options['password'])) echo ' '.esc_html__("Note that after you have claimed your add-ons, you can remove your password (but not the email address) from the settings below, without affecting this site's access to updates.", 'updraftplus'); echo '

'; echo '
'; } else { /* translators: %s: Plugin's connection status (it's either connected or not connected) */ echo "

".sprintf(esc_html__('You are presently %s to a TeamUpdraft account.', 'updraftplus'), ''. esc_html__('not connected', 'updraftplus').'').'

'; } if (isset($connection_errors)) { echo '

'.esc_html__('Errors occurred when trying to connect to your TeamUpdraft account:', 'updraftplus').'

'; } if (UpdraftPlus_Options::get_updraft_option('updraftplus_com_and_udc_connection_success', false)) { UpdraftPlus_Options::delete_updraft_option('updraftplus_com_and_udc_connection_success'); echo '
'; echo '

'; echo esc_html__('You successfully logged in to UpdraftPlus and connected this site to UpdraftCentral Cloud.', 'updraftplus'); echo '
'.esc_html__('Go to your UpdraftCentral Cloud dashboard', 'updraftplus').''; echo '

'; echo '
'; } $sid = $updraftplus_addons2->siteid(); $home_url = home_url(); // Enumerate possible unclaimed/re-claimable purchases, and what should be active on this site $unclaimed_available = array(); $assigned = array(); $have_all = false; if ($this->connected && isset($updraftplus_addons2->user_addons) && is_array($updraftplus_addons2->user_addons)) { foreach ($updraftplus_addons2->user_addons as $akey => $addon) { // Keys: site, sitedescription, key, status if (isset($addon['status']) && 'active' == $addon['status'] && isset($addon['site']) && ('unclaimed' == $addon['site'] || 'unlimited' == $addon['site'])) { $key = $addon['key']; $unclaimed_available[$key] = array('eid' => $akey, 'status' => 'available'); } elseif (isset($addon['status']) && 'active' == $addon['status'] && isset($addon['site']) && $addon['site'] == $sid) { $key = $addon['key']; $assigned[$key] = $akey; if ('all' == $key) $have_all = true; } elseif (isset($addon['sitedescription']) && ($this->normalise_url($home_url) === $this->normalise_url($addon['sitedescription']) || 0 === strpos($addon['sitedescription'], $home_url.' - '))) { // Is assigned to a site with the same URL as this one - allow a reclaim $key = $addon['key']; $unclaimed_available[$key] = array('eid' => $akey, 'status' => 'reclaimable'); } } } if (!$this->connected) $updraftplus_admin->build_credentials_form(UDADDONS2_SLUG, true); $ourpageslug = UDADDONS2_PAGESLUG; $href = UpdraftPlus_Options::admin_page_url(); if (count($unclaimed_available) > 0) { $nonce = wp_create_nonce('udmanager-nonce'); $pleasewait = htmlspecialchars(esc_html__('Please wait whilst we make the claim...', 'updraftplus')); $notgranted = esc_js(__('Claim not granted - perhaps you have already used this purchase somewhere else, or your paid period for downloading from updraftplus.com has expired?', 'updraftplus')); $notgrantedlogin = esc_js(__('Claim not granted - your account login details were wrong', 'updraftplus')); $ukresponse = esc_js(__('An unknown response was received.', 'updraftplus').' '.esc_html__('Response was:', 'updraftplus')); $addon_installed = esc_html__('The claim and installation was successful.', 'updraftplus').' '.esc_html__('You can now use your purchase!', 'updraftplus'); echo << function udm_claim(key) { if (jQuery('#addon-'+key).children('.addon-activation-notice').length) { return false; } var data = { action: 'udaddons_claimaddon', nonce: '$nonce', key: key }; jQuery('#addon-'+key).prepend('
$pleasewait
'); jQuery.post(ajaxurl, data, function(resp) { var response_code; var addons_written = false; try { response = ud_parse_json(resp); response_code = response.hasOwnProperty('code') ? response.code : 'UNKNOWN'; addons_written = response.hasOwnProperty('addons_written') ? response.addons_written : false; } catch (e) { console.log(e); response_code = 'PARSE_ERROR'; } if ('ERR' == response_code) { alert("$notgranted"); } else if ('OK' == response_code) { // We used to force udm_refresh to 1, before (Oct 2017) the possibility that there was already an updates result in the claim response var new_location = '$href?page=$ourpageslug&tab=addons'; // Aug 2018: The check updates process does not refresh the user_addons list, so the plugin does not recognise the claim was granted. We need to force a refresh when a claim is activated if (addons_written) { alert("$addon_installed"); } // Still do the page refresh so that the version number + other UI elements update new_location += '&udm_refresh=1'; window.location.href = new_location; } else if ('BADAUTH' == response_code) { alert("$notgrantedlogin"); } else { alert("$ukresponse "+response); } }); return false; } ENDHERE; } $addons = $updraftplus_addons2->get_available_addons(); $this->plugin_update_url = 'update-core.php'; // Can we get a direct update URL? $updates_available = get_site_transient('update_plugins'); if (is_object($updates_available) && isset($updates_available->response) && isset($updraftplus_addons2->plug_updatechecker) && isset($updraftplus_addons2->plug_updatechecker->pluginFile) && isset($updates_available->response[$updraftplus_addons2->plug_updatechecker->pluginFile])) { $file = $updraftplus_addons2->plug_updatechecker->pluginFile; $this->plugin_update_url = wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&updraftplus_noautobackup=1&plugin=').$file, 'upgrade-plugin_'.$file); $this->update_js = true; } $first = ''; $second = ''; $third = ''; if (is_array($addons)) { // Making $addons['installed'] = true manually. // FIX: It's the "All add-ons" link that was always show as available for activation, because there's no particular "all-addons" add-on. $does_all_addons_installed = true; foreach ($addons as $key => $addon) { if ('all' == $key) continue; if (empty($addon['installed'])) { $does_all_addons_installed = false; break; } } if ($does_all_addons_installed) { $addons['all']['installed'] = true; if (empty($addons['all']['name'])) { $addons['all']['name'] = 'UpdraftPlus Premium'; $addons['all']['shopurl'] = $updraftplus->get_url('premium'); $addons['all']['description'] = 'UpdraftPlus Premium'; } } foreach ($addons as $key => $addon) { // check if premium add-on is purchased. If it is then don't display other add-ons. if (!empty($addons['all']['installed']) && ('all' != $key)) continue; $latestversion = empty($addon['latestversion']) ? false : $addon['latestversion']; $installedversion = empty($addon['installedversion']) ? false : $addon['installedversion']; $installed = (empty($addon['installed']) && false == $installedversion) ? false : $addon['installed']; $unclaimed = (isset($unclaimed_available[$key])) ? $unclaimed_available[$key] : false; $is_assigned = (isset($assigned[$key])) ? $assigned[$key] : false; $box = $this->addonbox($key, $addon['name'], $addon['shopurl'], $addon['description'], trim($installedversion), trim($latestversion), $installed, $unclaimed, $is_assigned, $have_all); if ($is_assigned) { $first .= $box; } elseif (!empty($unclaimed)) { $second .= $box; } else { $third .= $box; } } } else { $first = "".esc_html__('An error occurred when trying to retrieve your add-ons.', 'updraftplus').""; } $addon_boxes = $first.$second.$third; // Hide header if no addon box is visible or no error trying to retrieve add-ons. if (!empty($addon_boxes)) { echo '

'.esc_html__('UpdraftPlus Premium', 'updraftplus').'

'; echo $addon_boxes;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- contains HTML tags that has inline onclick event echo '
'; } if ($this->update_js) { ?> user_support)) { // Keys: } echo '

'.esc_html__('UpdraftPlus Support', 'updraftplus').'

"; if ($this->connected) { echo "
"; $updraftplus_admin->build_credentials_form(UDADDONS2_SLUG, true); } echo '
'; } /** * This may produce a URL that does not actually reference the same location; its purpose is to use in comparisons of two URLs that *both* go through this function, only * * @param string $url * @return string */ private function normalise_url($url) { if (preg_match('/^(\S+) - /', ltrim($url), $matches)) $url = $matches[1]; $parsed_descrip_url = parse_url($url); if (is_array($parsed_descrip_url) && isset($parsed_descrip_url['host'])) { if (preg_match('/^www\./i', $parsed_descrip_url['host'], $matches)) $parsed_descrip_url['host'] = substr($parsed_descrip_url['host'], 4); $normalised_descrip_url = 'http://'.strtolower($parsed_descrip_url['host']); if (!empty($parsed_descrip_url['port'])) $normalised_descrip_url .= ':'.$parsed_descrip_url['port']; if (!empty($parsed_descrip_url['path'])) $normalised_descrip_url .= untrailingslashit($parsed_descrip_url['path']); } else { $normalised_descrip_url = untrailingslashit($url); } return $normalised_descrip_url; } private function addonbox($key, $name, $shopurl, $description, $installedversion, $latestversion = false, $installed = false, $unclaimed = false, $is_assigned = false, $have_all = false) { $urlbase = UPDRAFTPLUS_URL.'/images/addons-images'; $mother = $this->mother; $extra_description = ''; // Remove pCloud from the individual add-ons list. if ('pcloud' == $key) { return; } elseif ('all' == $key) { $name = esc_html('Get every feature of UpdraftPlus Premium', 'updraftplus'); $description = esc_html__('Reduce server load by backing up only incremental changes made to your website or by backing up at set times, like overnight when server resources are high.', 'updraftplus'); $extra_description = esc_html(__('Back up automatically before updates and protect more of your hard work by backing up more files and more databases.', 'updraftplus').' '.__('Anonymise personal backup data, encrypt the database and more.', 'updraftplus')); } if ($installed && ($is_assigned || ($have_all && 'all' != $key))) { if ('all' === $key) return; $blurb = "

"; $preblurb = "

\"".esc_html__("You've
"; if ('all' != $key) { $blurb .= sprintf(esc_html__('Your version: %s', 'updraftplus'), $installedversion); if (!empty($latestversion) && $latestversion == $installedversion) { $blurb .= " (".esc_html__('latest', 'updraftplus').')'; } elseif (!empty($latestversion) && version_compare($latestversion, $installedversion, '>')) { $blurb .= " (".esc_html__('latest', 'updraftplus').": $latestversion - plugin_update_url."\">update)"; } else { $blurb .= " ".esc_html__('(apparently a pre-release or withdrawn release)', 'updraftplus'); } } $blurb .= "

"; } else { if ('all' == $key && $is_assigned && false === $unclaimed) return; if ($have_all && 'all' != $key) { $blurb = '

'.esc_html__('Available for this site (via your all-addons purchase)', 'updraftplus').' - '.esc_html__('please follow this link to update the plugin in order to get it', 'updraftplus').'

'; $preblurb = "
"; } elseif ($is_assigned) { $blurb = '

'.esc_html__('Assigned to this site', 'updraftplus').' - '.esc_html__('please follow this link to update the plugin in order to activate it', 'updraftplus').'

'; $preblurb = "
"; } elseif (is_array($unclaimed)) { // Keys: eid = unique ID, status = available|reclaimable // Value of $unclaimed is a unique id, though we won't particularly use it if (isset($unclaimed['status']) && 'reclaimable' == $unclaimed['status']) { $blurb ='

'.esc_html__('Available to claim on this site', 'updraftplus').' - '.esc_html__('activate it on this site', 'updraftplus').'

'; } else { $blurb ='

'.esc_html__('You have an inactive purchase', 'updraftplus').' - '.esc_html__('activate it on this site', 'updraftplus').'

'; } $preblurb = "
"; } else { /* translators: %s: Add-on name */ $blurb = '

'.esc_html__('Get it from teamupdraft.com', 'updraftplus').''.(($this->connected) ? '' : ' '.esc_html__('(or connect using the login form on this page if you have already bought it)', 'updraftplus')).'

'; $preblurb = "
\"".esc_html__('Buy
"; } } if ($extra_description) $extra_description = '

'.$extra_description.'

'; return <<

$name

$description

$extra_description$blurb
$preblurb ENDHERE; } /** * Adds links to the plugin on the 'Plugins' dashboard page, via hooking the appropriate filter. * * @param Array $links - current array of links * @param String $file - the current file that links are being fetched for */ public function action_links($links, $file) { if ('updraftplus/updraftplus.php' == $file) { array_unshift($links, ''.esc_html__('Manage Addons', 'updraftplus').''); } return $links; } }