'.__('Backup data will be sent to:', 'updraftplus').' '.htmlspecialchars($jobdata['remotesend_info']['url']).'
'; } return $ret; } public function updraft_remote_ping_test($data) { if (!isset($data['id']) || !is_numeric($data['id']) || empty($data['url'])) die; $remote_indicator = $data['id']; $ping_result = $this->do_ping_test($remote_indicator, $data['url']); die(json_encode($ping_result)); } /** * Do an RPC ping test * * @param String $remote_indicator * @param String $url * * @return Array - results */ public function do_ping_test($remote_indicator, $url) { global $updraftplus; $remotesites = UpdraftPlus_Options::get_updraft_option('updraft_remotesites'); if (!is_array($remotesites)) $remotesites = array(); if (empty($remotesites[$remote_indicator]) || $url != $remotesites[$remote_indicator]['url'] || empty($remotesites[$remote_indicator]['key']) || empty($remotesites[$remote_indicator]['name_indicator'])) { return array('e' => 1, 'r' => __('Error:', 'updraftplus').' '.__('site not found', 'updraftplus')); } try { $updraftplus->error_reporting_stop_when_logged = true; $error_levels = version_compare(PHP_VERSION, '8.4.0', '>=') ? E_ALL : E_ALL & ~E_STRICT; set_error_handler(array($updraftplus, 'php_error'), $error_levels); $this->php_events = array(); add_filter('updraftplus_logline', array($this, 'updraftplus_logline'), 10, 4); $opts = $remotesites[$remote_indicator]; $ud_rpc = $updraftplus->get_udrpc($opts['name_indicator']); $send_data = null; if (!empty($opts['format_support']) && 2 == $opts['format_support']) { if (empty($opts['remote_got_public'])) { // Can't upgrade to format 2 until we know the other end has our public key $use_format = 1; $send_data = array('sender_public' => $opts['local_public']); } else { $use_format = 2; } } else { $use_format = 1; } $ud_rpc->set_message_format($use_format); if (2 == $use_format) { $ud_rpc->set_key_remote($opts['key']); $ud_rpc->set_key_local($opts['local_private']); } else { $ud_rpc->set_key_local($opts['key']); } $ud_rpc->set_destination_url($url); $ud_rpc->activate_replay_protection(); do_action('updraftplus_remotesend_udrpc_object_obtained', $ud_rpc, $opts); $response = $ud_rpc->send_message('ping', $send_data); restore_error_handler(); if (is_wp_error($response)) { $err_msg = __('Error:', 'updraftplus').' '.$response->get_error_message(); $err_data = $response->get_error_data(); $err_code = $response->get_error_code(); if (!is_numeric($err_code) && isset($err_data['response']['code'])) { $err_code = $err_data['response']['code']; $err_msg = __('Error:', 'updraftplus').' '.UpdraftPlus_HTTP_Error_Descriptions::get_http_status_code_description($err_code); } elseif (is_string($err_data) && preg_match('/captcha|verify.*human|turnstile/i', $err_data)) { $err_msg = __('Error:', 'updraftplus').' '.__('We are unable to proceed with the process due to a bot verification requirement', 'updraftplus'); } } elseif (!is_array($response) || empty($response['response']) || 'pong' != $response['response']) { $err_msg = __('Error:', 'updraftplus').' '.sprintf(__('You should check that the remote site is online, not firewalled, bot verification setting is disabled, does not have security modules that may be blocking access, has UpdraftPlus version %s or later active and that the keys have been entered correctly.', 'updraftplus'), '2.10.3'); $err_data = $response; $err_code = 'no_pong'; } elseif (!empty($response['data']['got_public'])) { $remotesites[$remote_indicator]['remote_got_public'] = 1; UpdraftPlus_Options::update_updraft_option('updraft_remotesites', $remotesites); } if (isset($err_msg)) { $res = array('e' => 1, 'r' => $err_msg); if ($this->url_looks_internal($url)) { $res['moreinfo'] = ''.sprintf(__('The site URL you are sending to (%s) looks like a local development website.', 'updraftplus'), htmlspecialchars($url)).' '.__('If you are sending from an external network, it is likely that a firewall will be blocking this.', 'updraftplus').'
'; } // We got several support requests from people who didn't seem to be aware of other methods $msg_try_other_method = ''.__('If sending directly from site to site does not work for you, then there are three other methods - please try one of these instead.', 'updraftplus').' '.__('For longer help, including screenshots, follow this link.', 'updraftplus').'
'; $res['moreinfo'] = isset($res['moreinfo']) ? $res['moreinfo'].$msg_try_other_method : $msg_try_other_method; if (isset($err_data)) $res['data'] = $err_data; if (isset($err_code)) $res['code'] = $err_code; if (!empty($this->php_events)) $res['php_events'] = $this->php_events; return $res; } $ret = ''.__('Testing connection...', 'updraftplus').' '.__('OK', 'updraftplus').'
'; global $updraftplus_admin; $ret .= ''; $ret .= ''; $ret .= $updraftplus_admin->files_selector_widgetry('remotesend_', false, false); $service = $updraftplus->just_one(UpdraftPlus_Options::get_updraft_option('updraft_service')); if (is_string($service)) $service = array($service); if (is_array($service) && !empty($service) && array('none') !== $service) { $first_one = true; foreach ($service as $s) { if (!$s) continue; if (isset($updraftplus->backup_methods[$s])) { if ($first_one) { $first_one = false; $ret .= ''; $ret .= '
'; } $ret .= apply_filters('updraft_backupnow_modal_afteroptions', '', 'remotesend_'); $ret .= ''; return array('success' => 1, 'r' => $ret); } catch (Exception $e) { return array('e' => 1, 'r' => __('Error:', 'updraftplus').' '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')'); } } /** * This is used only for an advisory warning - does not have to be able to always detect * * @param string $url */ protected function url_looks_internal($url) { $url_host = strtolower(parse_url($url, PHP_URL_HOST)); if ('localhost' == $url_host || strpos($url_host, '127.') === 0 || strpos($url_host, '10.') === 0 || '::1' == $url_host || strpos($url_host, 'localhost') !== false || substr($url_host, -4, 4) == '.dev') return true; return false; } public function updraft_migrate_key_delete($data) { if (empty($data['keyid'])) die; $our_keys = UpdraftPlus_Options::get_updraft_option('updraft_migrator_localkeys'); if (!is_array($our_keys)) $our_keys = array(); unset($our_keys[$data['keyid']]); UpdraftPlus_Options::update_updraft_option('updraft_migrator_localkeys', $our_keys); echo json_encode(array('ourkeys' => $this->list_our_keys($our_keys))); die; } /** * This function is a wrapper for updraft_migrate_key_create when being called from WP_CLI it allows us to return the created key rather than echo it, by passing return_instead_of_echo as part of $data. * * @param string $string - empty string to filter on * @param array $data - an array of data needed to create the RSA keypair should also include return_instead_of_echo to return the result * * @return string - the RSA remote key */ public function updraft_migrate_key_create_return($string, $data) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- Unused parameter is present because the method is used as a WP filter. return $this->updraft_migrate_key_create($data); } /** * Called upon the WP action updraft_s3_newuser. Dies. * * @param array $data - the posted data * * @return void */ public function updraft_migrate_key_create($data) { if (empty($data['name'])) die; $name = stripslashes($data['name']); $size = (empty($data['size']) || !is_numeric($data['size']) || $data['size'] < 1024) ? 2048 : (int) $data['size']; $name_hash = md5($name); // 32 characters $indicator_name = $name_hash.'.migrator.updraftplus.com'; $our_keys = UpdraftPlus_Options::get_updraft_option('updraft_migrator_localkeys'); if (!is_array($our_keys)) $our_keys = array(); if (isset($our_keys[$name_hash])) { echo json_encode(array('e' => 1, 'r' => __('Error:', 'updraftplus').' '.__('A key with this name already exists; you must use a unique name.', 'updraftplus'))); die; } global $updraftplus; $ud_rpc = $updraftplus->get_udrpc($indicator_name); if (is_object($ud_rpc) && $ud_rpc->generate_new_keypair($size)) { $local_bundle = $ud_rpc->get_portable_bundle('base64_with_count'); $our_keys[$name_hash] = array('name' => $name, 'key' => $ud_rpc->get_key_local()); UpdraftPlus_Options::update_updraft_option('updraft_migrator_localkeys', $our_keys); if (isset($data['return_instead_of_echo']) && $data['return_instead_of_echo']) return $local_bundle; echo json_encode(array( 'bundle' => $local_bundle, 'r' => __('Key created successfully.', 'updraftplus').' '.__('You must copy and paste this key on the sending site now - it cannot be shown again.', 'updraftplus'), 'selector' => $this->get_remotesites_selector(), 'ourkeys' => $this->list_our_keys($our_keys), )); die; } if (extension_loaded('mbstring')) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated -- Commented out as this flags as not compatible with PHP 5.2 if (ini_get('mbstring.func_overload') & 2) { echo json_encode(array('e' => 1, 'r' => __('Error:', 'updraftplus').' '.sprintf(__('The setting %s is turned on in your PHP settings.', 'updraftplus'), 'mbstring.func_overload').' '.__('It is deprecated, causes encryption to malfunction, and should be turned off.', 'updraftplus'))); die; } } echo json_encode(array('e' => 1)); die; } public function updraft_migrate_newdestination($data) { global $updraftplus; $ret = array(); if (empty($data['key'])) { $ret['e'] = sprintf(__("Failure: No %s was given.", 'updraftplus'), __('key', 'updraftplus')); } else { // The indicator isn't really needed - we won't be receiving on it $our_indicator = md5(network_site_url()).'.migrator.updraftplus.com'; $ud_rpc = $updraftplus->get_udrpc($our_indicator); $ud_rpc->set_can_generate(true); // A bundle has these keys: key, name_indicator, url $decode_bundle = $ud_rpc->decode_portable_bundle($data['key'], 'base64_with_count'); if (!is_array($decode_bundle) || !empty($decode_bundle['code'])) { $ret['e'] = __('Error:', 'updraftplus'); if (!empty($decode_bundle['code']) && 'invalid_wrong_length' == $decode_bundle['code']) { $ret['e'] .= ' '.__('The entered key was the wrong length - please try again.', 'updraftplus'); } elseif (!empty($decode_bundle['code']) && 'invalid_corrupt' == $decode_bundle['code']) { $ret['e'] .= ' '.__('The entered key was corrupt - please try again.', 'updraftplus').' ('.$decode_bundle['data'].')'; } elseif (empty($decode_bundle['key']) || empty($decode_bundle['url'])) { $ret['e'] .= ' '.__('The entered key was corrupt - please try again.', 'updraftplus'); $ret['data'] = $decode_bundle; } } elseif (empty($decode_bundle['key']) || empty($decode_bundle['url'])) { $ret['e'] = __('Error:', 'updraftplus').' '.__('The entered key was corrupt - please try again.', 'updraftplus'); $ret['data'] = $decode_bundle; } else { if (trailingslashit(network_site_url()) == $decode_bundle['url']) { $ret['e'] = __('Error:', 'updraftplus').' '.__('The entered key does not belong to a remote site (it belongs to this one).', 'updraftplus'); } else { // Store the information $remotesites = UpdraftPlus_Options::get_updraft_option('updraft_remotesites'); if (!is_array($remotesites)) $remotesites = array(); foreach ($remotesites as $k => $rsite) { if (!is_array($rsite)) continue; if ($rsite['url'] == $decode_bundle['url']) unset($remotesites[$k]); } if (false == $ud_rpc->generate_new_keypair()) { $ret['e'] = __('Error:', 'updraftplus').' An error occurred when attempting to generate a new key-pair'; } else { $decode_bundle['local_private'] = $ud_rpc->get_key_local(); $decode_bundle['local_public'] = $ud_rpc->get_key_remote(); $remotesites[] = $decode_bundle; UpdraftPlus_Options::update_updraft_option('updraft_remotesites', $remotesites); $ret['selector'] = $this->get_remotesites_selector($remotesites); // Return the new HTML widget to the front end $ret['r'] = __('The key was successfully added.', 'updraftplus').' '.__('It is for sending backups to the following site: ', 'updraftplus').htmlspecialchars($decode_bundle['url']); } } } } echo json_encode($ret); die; } /** * Display or return html for selecting receiving remote site. * * @param bool|array $remotesites Remote sites. Default false for fetching from options. * @param bool $echo_instead_of_return Whether to display html or return it. * @return void|string Display or return HTML for selecting remotesites. */ protected function get_remotesites_selector($remotesites = false, $echo_instead_of_return = false) { if (false === $remotesites) { $remotesites = UpdraftPlus_Options::get_updraft_option('updraft_remotesites'); if (!is_array($remotesites)) $remotesites = array(); } if (!$echo_instead_of_return) ob_start(); if (empty($remotesites)) { ?>
$key) { if (!is_array($key)) continue; if ($first_one) { $first_one = false; ?>
"; // Handling the edge case where no
tag was opened earlier. } if (!$echo_instead_of_return) return ob_get_clean(); } /** * Delete the list of existing remote sites from the database * * @return String The JSON format of the response of the deletion process */ public function updraft_migrate_delete_existingsites() { global $wpdb; $ret = array(); $old_val = $wpdb->suppress_errors(); UpdraftPlus_Options::delete_updraft_option('updraft_remotesites'); $remote_sites = UpdraftPlus_Options::get_updraft_option('updraft_remotesites'); if (is_array($remote_sites) && !empty($remote_sites)) { $err_msg = __('There was an error while trying to remove the list of existing sites.', 'updraftplus'); $err_db = !empty($wpdb->last_error) ? ' ('.$wpdb->last_error.' - '.$wpdb->last_query.')' : ''; $ret['error'] = $err_msg.$err_db; } else { $ret['success'] = __('The list of existing sites has been removed', 'updraftplus'); $ret['html'] = $this->get_remotesites_selector(); } $wpdb->suppress_errors($old_val); echo json_encode($ret); } }