'.__('This file is not an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').'
'.apply_filters('updraftplus_if_foreign_then_premium_message', ''), 'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)', 'updraftplus'), 'uploaderror' => __('Upload error:', 'updraftplus'), 'notdba' => __('This file is not an UpdraftPlus encrypted database archive (such files are .gz.crypt files which have a name like: backup_(time)_(site name)_(code)_db.crypt.gz).', 'updraftplus'), 'uploaderr' => __('Upload error', 'updraftplus'), 'followlink' => __('Follow this link to attempt decryption and download the database file to your computer.', 'updraftplus'), 'thiskey' => __('This decryption key will be attempted:', 'updraftplus'), 'unknownresp' => __('Unknown server response:', 'updraftplus'), 'ukrespstatus' => __('Unknown server response status:', 'updraftplus'), 'uploaded' => __('The file was uploaded.', 'updraftplus'), // One of the translators has erroneously changed "Backup" into "Back up" (which means, "reverse" !) 'backupnow' => str_ireplace('Back Up', 'Backup', __('Backup Now', 'updraftplus')), 'cancel' => __('Cancel', 'updraftplus'), 'deletebutton' => __('Delete', 'updraftplus'), 'createbutton' => __('Create', 'updraftplus'), 'uploadbutton' => __('Upload', 'updraftplus'), 'youdidnotselectany' => __('You did not select any components to restore.', 'updraftplus').' '.__('Please select at least one, and then try again.', 'updraftplus'), 'restoreactivitylogfullscreen' => __('Full-screen', 'updraftplus'), 'restoreactivitylogscreenexit' => __('Exit full-screen', 'updraftplus'), 'proceedwithupdate' => __('Proceed with update', 'updraftplus'), 'close' => __('Close', 'updraftplus'), 'restore' => __('Restore', 'updraftplus'), 'downloadlogfile' => __('Download log file', 'updraftplus'), 'automaticbackupbeforeupdate' => __('Automatic backup before update', 'updraftplus'), 'unsavedsettings' => __('You have made changes to your settings, and not saved.', 'updraftplus'), 'saving' => __('Saving...', 'updraftplus'), 'connect' => __('Connect', 'updraftplus'), 'connecting' => __('Connecting...', 'updraftplus'), 'disconnect' => __('Disconnect', 'updraftplus'), 'disconnecting' => __('Disconnecting...', 'updraftplus'), 'counting' => __('Counting...', 'updraftplus'), 'updatequotacount' => __('Update quota count', 'updraftplus'), 'addingsite' => __('Adding...', 'updraftplus'), 'addsite' => __('Add site', 'updraftplus'), // 'resetting' => __('Resetting...', 'updraftplus'), 'creating_please_allow' => __('Creating...', 'updraftplus').(function_exists('openssl_encrypt') ? '' : ' ('.__('your PHP install lacks the openssl module; as a result, this can take minutes; if nothing has happened by then, then you should either try a smaller key size, or ask your web hosting company how to enable this PHP module on your setup.', 'updraftplus').')'), 'sendtosite' => __('Send to site:', 'updraftplus'), /* translators: %s: Minimum required UpdraftPlus version */ 'checkrpcsetup' => sprintf(__('You should check that the remote site is online, not firewalled, 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'), 'pleasenamekey' => __('Please give this key a name (e.g. indicate the site it is for):', 'updraftplus'), 'key' => __('Key', 'updraftplus'), 'nokeynamegiven' => sprintf( /* translators: %s: Missing key name */ __("Failure: No %s was given.", 'updraftplus'), __('key name', 'updraftplus') ), 'deleting' => __('Deleting...', 'updraftplus'), 'enter_mothership_url' => __('Please enter a valid URL', 'updraftplus'), 'delete_response_not_understood' => __("We requested to delete the file, but could not understand the server's response", 'updraftplus'), 'testingconnection' => __('Testing connection...', 'updraftplus'), 'send' => __('Send', 'updraftplus'), 'migratemodalheight' => class_exists('UpdraftPlus_Addons_Migrator') ? 555 : 300, 'migratemodalwidth' => class_exists('UpdraftPlus_Addons_Migrator') ? 770 : 500, 'download' => _x('Download', '(verb)', 'updraftplus'), 'browse_download_link' => apply_filters('updraftplus_browse_download_link', ''.__("With UpdraftPlus Premium, you can directly download individual files from here.", "updraftplus").''), 'unsavedsettingsbackup' => __('You have made changes to your settings, and not saved.', 'updraftplus')."\n".__('You should save your changes to ensure that they are used for making your backup.', 'updraftplus'), 'unsaved_settings_export' => __('You have made changes to your settings, and not saved.', 'updraftplus')."\n".__('Your export file will be of your displayed settings, not your saved ones.', 'updraftplus'), 'dayselector' => $day_selector, 'mdayselector' => $mday_selector, 'day' => __('day', 'updraftplus'), 'inthemonth' => __('in the month', 'updraftplus'), 'days' => __('day(s)', 'updraftplus'), 'hours' => __('hour(s)', 'updraftplus'), 'weeks' => __('week(s)', 'updraftplus'), 'forbackupsolderthan' => __('For backups older than', 'updraftplus'), 'ud_url' => UPDRAFTPLUS_URL, 'processing' => __('Processing...', 'updraftplus'), 'loading' => __('Loading...', 'updraftplus'), 'pleasefillinrequired' => __('Please fill in the required information.', 'updraftplus'), /* translators: %s: Settings type */ 'test_settings' => __('Test %s Settings', 'updraftplus'), /* translators: %s: Settings type */ 'testing_settings' => __('Testing %s Settings...', 'updraftplus'), /* translators: %s: Settings type */ 'settings_test_result' => __('%s settings test result:', 'updraftplus'), 'nothing_yet_logged' => __('Nothing yet logged', 'updraftplus'), 'import_select_file' => __('You have not yet selected a file to import.', 'updraftplus'), 'import_invalid_json_file' => __('Error: The chosen file is corrupt.', 'updraftplus').' '.__('Please choose a valid UpdraftPlus export file.', 'updraftplus'), 'updraft_settings_url' => UpdraftPlus_Options::admin_page_url().'?page=updraftplus', 'network_site_url' => network_site_url(), 'importing' => __('Importing...', 'updraftplus'), 'importing_data_from' => __('This will import data from:', 'updraftplus'), 'exported_on' => __('Which was exported on:', 'updraftplus'), 'continue_import' => __('Do you want to carry out the import?', 'updraftplus'), 'complete' => __('Complete', 'updraftplus'), 'backup_complete' => __('The backup has finished running', 'updraftplus'), 'backup_aborted' => __('The backup was aborted', 'updraftplus'), 'remote_delete_limit' => defined('UPDRAFTPLUS_REMOTE_DELETE_LIMIT') ? UPDRAFTPLUS_REMOTE_DELETE_LIMIT : 25, // this used to be number of files but now the value of this constant is in seconds 'remote_files_deleted' => __('remote files deleted', 'updraftplus'), 'http_code' => __('HTTP code:', 'updraftplus'), 'makesure2' => __('The file failed to upload.', 'updraftplus').' '.__('Please check the following:', 'updraftplus')."\n\n - ".__('Any settings in your .htaccess or web.config file that affects the maximum upload or post size.', 'updraftplus')."\n - ".__('The available memory on the server.', 'updraftplus')."\n - ".__('That you are attempting to upload a zip file previously created by UpdraftPlus.', 'updraftplus')."\n\n".__('Further information may be found in the browser JavaScript console, and the server PHP error logs.', 'updraftplus'), 'zip_file_contents' => __('Browsing zip file', 'updraftplus'), 'zip_file_contents_info' => __('Select a file to view information about it', 'updraftplus'), 'search' => __('Search', 'updraftplus'), 'download_timeout' => __('Unable to download file.', 'updraftplus').' '.__('This could be caused by a timeout.', 'updraftplus').' '.__('It would be best to download the zip to your computer.', 'updraftplus'), 'loading_log_file' => __('Loading log file', 'updraftplus'), 'updraftplus_version' => $updraftplus->version, 'updraftcentral_wizard_empty_url' => __('Please enter the URL where your UpdraftCentral dashboard is hosted.', 'updraftplus'), 'updraftcentral_wizard_invalid_url' => __('Please enter a valid URL e.g http://example.com', 'updraftplus'), 'export_settings_file_name' => 'updraftplus-settings-'.sanitize_title(get_bloginfo('name')).'.json', // For remote storage handlebarsjs template 'remote_storage_options' => $remote_storage_options_and_templates['options'], 'remote_storage_templates' => $remote_storage_options_and_templates['templates'], 'remote_storage_partial_templates' => $remote_storage_options_and_templates['partial_templates'], 'remote_storage_methods' => $backup_methods, 'instance_enabled' => __('Currently enabled', 'updraftplus'), 'instance_disabled' => __('Currently disabled', 'updraftplus'), 'local_upload_started' => __('Local backup upload has started; please check the log file to see the upload progress', 'updraftplus'), 'local_upload_error' => __('You must select at least one remote storage destination to upload this backup set to.', 'updraftplus'), 'already_uploaded' => __('(already uploaded)', 'updraftplus'), 'onedrive_folder_url_warning' => __('Please specify the Microsoft OneDrive folder name, not the URL.', 'updraftplus'), 'updraftcentral_cloud' => __('UpdraftCentral Cloud', 'updraftplus'), 'udc_cloud_connected' => __('Connected.', 'updraftplus').' '.__('Requesting UpdraftCentral Key.', 'updraftplus'), 'udc_cloud_key_created' => __('Key created.', 'updraftplus').' '.__('Adding site to UpdraftCentral Cloud.', 'updraftplus'), 'login_successful' => __('Login successful.', 'updraftplus').' '. /* translators: %s: Name of the service to be opened in a new window.*/ __('Please follow this link to open %s in a new window.', 'updraftplus'), 'login_successful_short' => __('Login successful; reloading information.', 'updraftplus'), 'registration_successful' => __('Registration successful.', 'updraftplus').' '. /* translators: %s: Name of the service to be opened in a new window.*/ __('Please follow this link to open %s in a new window.', 'updraftplus'), 'username_password_required' => __('Both email and password fields are required.', 'updraftplus'), 'valid_email_required' => __('An email is required and needs to be in a valid format.', 'updraftplus'), 'trouble_connecting' => __('Trouble connecting? Try using an alternative method in the advanced security options.', 'updraftplus'), 'checking_tfa_code' => __('Verifying one-time password...', 'updraftplus'), 'perhaps_login' => __('Perhaps you would want to login instead.', 'updraftplus'), 'generating_key' => __('Please wait while the system generates and registers an encryption key for your website with UpdraftCentral Cloud.', 'updraftplus'), 'updraftcentral_cloud_redirect' => __('Please wait while you are redirected to UpdraftCentral Cloud.', 'updraftplus'), 'data_consent_required' => __('You need to read and accept the UpdraftCentral Cloud data and privacy policies before you can proceed.', 'updraftplus'), 'close_wizard' => __('You can also close this wizard.', 'updraftplus'), 'control_udc_connections' => __('For future control of all your UpdraftCentral connections, go to the "Advanced Tools" tab.', 'updraftplus'), 'main_tabs_keys' => array_keys($main_tabs), 'clone_version_warning' => __('Warning: you have selected a lower version than your currently installed version.', 'updraftplus').' '.__('This may fail if you have components that are incompatible with earlier versions.', 'updraftplus'), 'clone_backup_complete' => __('The clone has been provisioned, and its data has been sent to it.', 'updraftplus').' '.__('Once the clone has finished deploying it, you will receive an email.', 'updraftplus'), 'clone_backup_aborted' => __('The preparation of the clone data has been aborted.', 'updraftplus'), 'current_clean_url' => esc_url(UpdraftPlus::get_current_clean_url()), 'exclude_rule_remove_conformation_msg' => __('Are you sure you want to remove this exclusion rule?', 'updraftplus'), 'exclude_select_file_or_folder_msg' => __('Please select a file/folder which you would like to exclude', 'updraftplus'), 'exclude_select_folder_wildcards_msg' => __('Please select a folder in which the files/directories you would like to exclude are located', 'updraftplus'), 'exclude_type_ext_msg' => __('Please enter a file extension, like zip', 'updraftplus'), 'exclude_ext_error_msg' => __('Please enter a valid file extension', 'updraftplus'), 'exclude_type_prefix_msg' => __('Please enter characters that begin the filename which you would like to exclude', 'updraftplus'), 'exclude_prefix_error_msg' => __('Please enter a valid file name prefix', 'updraftplus'), 'exclude_contain_error_msg' => __('Please enter part of the file name', 'updraftplus'), 'duplicate_exclude_rule_error_msg' => __('The exclusion rule which you are trying to add already exists', 'updraftplus'), 'clone_key_required' => __('UpdraftClone key is required.', 'updraftplus'), 'files_new_backup' => __('Include your files in the backup', 'updraftplus'), 'files_incremental_backup' => __('File backup options', 'updraftplus'), 'ajax_restore_invalid_response' => __('HTML was detected in the response.', 'updraftplus').' '.__('You may have a security module on your webserver blocking the restoration operation.', 'updraftplus'), 'emptyrestorepath' => __('You have not selected a restore path for your chosen backups', 'updraftplus'), 'updraftvault_info' => ''.__('UpdraftVault is our remote storage which works seamlessly with UpdraftPlus.', 'updraftplus') .' '.__('Find out more here.', 'updraftplus').'' .'
' .''.__('Try it - 1 month for $1!', 'updraftplus').'
', 'login_udc_no_licences_short' => __('No UpdraftCentral licences were available.', 'updraftplus').' '.__('Continuing to connect to account.', 'updraftplus'), 'credentials' => __('credentials', 'updraftplus'), 'username' => __('Username', 'updraftplus'), 'password' => __('Password', 'updraftplus'), /* translators: %d: Seconds ago */ 'last_activity' => __('last activity: %d seconds ago', 'updraftplus'), /* translators: %d: Seconds until resumption */ 'no_recent_activity' => __('no recent activity; will offer resumption after: %d seconds', 'updraftplus'), 'restore_files_progress' => __('Restoring %s1 files out of %s2', 'updraftplus'), /* translators: %s: Database table name */ 'restore_db_table_progress' => __('Restoring table: %s', 'updraftplus'), /* translators: %s: Stored routine name */ 'restore_db_stored_routine_progress' => __('Restoring stored routine: %s', 'updraftplus'), 'finished' => __('Finished', 'updraftplus'), 'begun' => __('Begun', 'updraftplus'), 'maybe_downloading_entities' => __('Downloading backup files if needed', 'updraftplus'), 'preparing_backup_files' => __('Preparing backup files', 'updraftplus'), 'ajax_restore_contact_failed' => __('Attempts by the browser to contact the website failed.', 'updraftplus'), 'ajax_restore_error' => __('Restore error:', 'updraftplus'), 'ajax_restore_404_detected' => ''. __('Warning:', 'updraftplus') . '
' . __('Attempts by the browser to access some pages have returned a "not found (404)" error.', 'updraftplus').' '.__('This could mean that your .htaccess file has incorrect contents, is missing, or that your webserver is missing an equivalent mechanism.', 'updraftplus'). '
'.__('Missing pages:', 'updraftplus').'
'.esc_html__('Backup directory could not be created', 'updraftplus').'...
';
echo '
'.esc_html__('Backup directory successfully created.', 'updraftplus').'
'.sprintf(__('You have an unfinished restoration operation, begun %s ago.', 'updraftplus'), $time_ago).'
'; $html .= '|
|
|
...
'.esc_html(__('Your WordPress install has old folders from its state before you restored/migrated (technical information: these are suffixed with -old).', 'updraftplus').' '.__('You should press this button to delete them as soon as you have verified that the restoration worked.', 'updraftplus')).'
'; } ?> '; } /** * Return cron status information about a specified in-progress job * * @param Boolean|String $job_id - the job to get information about; or, if not specified, all jobs * * @return Array|Boolean - the requested information, or false if it was not found. Format differs depending on whether info on all jobs, or a single job, was requested. */ public function get_cron($job_id = false) { $cron = get_option('cron'); if (!is_array($cron)) $cron = array(); if (false === $job_id) return $cron; foreach ($cron as $time => $job) { if (!isset($job['updraft_backup_resume'])) continue; foreach ($job['updraft_backup_resume'] as $info) { if (isset($info['args'][1]) && $job_id == $info['args'][1]) { global $updraftplus; $jobdata = $updraftplus->jobdata_getarray($job_id); return is_array($jobdata) ? array($time, $jobdata) : false; } } } } /** * Gets HTML describing the active jobs * * @param Boolean $this_job_only A value for $this_job_only also causes something non-empty to always be returned (to allow detection of the job having started on the front-end) * * @return String - the HTML */ private function print_active_jobs($this_job_only = false) { $cron = $this->get_cron(); $ret = ''; foreach ($cron as $time => $job) { if (!isset($job['updraft_backup_resume'])) continue; foreach ($job['updraft_backup_resume'] as $info) { if (isset($info['args'][1])) { $job_id = $info['args'][1]; if (false === $this_job_only || $job_id == $this_job_only) { $ret .= $this->print_active_job($job_id, false, $time, $info['args'][0]); } } } } // A value for $this_job_only implies that output is required if (false !== $this_job_only && !$ret) { $ret = $this->print_active_job($this_job_only); if ('' == $ret) { global $updraftplus; $log_file = $updraftplus->get_logfile_name($this_job_only); // if the file exists, the backup was booted. Check if the information about completion is found in the log, or if it was modified at least 2 minutes ago. if (file_exists($log_file) && ($updraftplus->found_backup_complete_in_logfile($this_job_only) || (time() - filemtime($log_file)) > 120)) { // The presence of the exact ID matters to the front-end - indicates that the backup job has at least begun $ret = ''.esc_html__('Old folders successfully removed.', 'updraftplus').'
'.esc_html__('Old folder removal failed for some reason.', 'updraftplus').' '.esc_html__('You may want to do this manually.', 'updraftplus').'
'.esc_html__('The folder was created, but we had to change its file permissions to 777 (world-writable) to be able to write to it.', 'updraftplus').' '.esc_html__('You should check with your hosting provider that this will not cause any problems', 'updraftplus').'
'; return true; } else { @$wp_filesystem->chmod($default_backup_dir, 0775);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the method. $show_dir = (0 === strpos($default_backup_dir, ABSPATH)) ? substr($default_backup_dir, strlen(ABSPATH)) : $default_backup_dir; return new WP_Error('writable_error', __('The folder exists, but your webserver does not have permission to write to it.', 'updraftplus').' '.__('You will need to consult with your web hosting provider to find out how to set permissions for a WordPress plugin to write to the directory.', 'updraftplus').' ('.$show_dir.')'); } } return true; } /** * scans the content dir to see if any -old dirs are present * * @param Boolean $print_as_comment Echo information in an HTML comment * @return Boolean */ private function scan_old_dirs($print_as_comment = false) { global $updraftplus; $dirs = scandir(untrailingslashit(WP_CONTENT_DIR)); if (!is_array($dirs)) $dirs = array(); foreach ($dirs as $dir) { if (preg_match('/-old$/', $dir)) { if ($print_as_comment) echo ''; return true; } } $backups_dir_location = $updraftplus->backups_dir_location(); $dirs = @scandir($backups_dir_location);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function. if (!is_array($dirs)) $dirs = array(); foreach ($dirs as $dir) { if (preg_match('/-old$/', $dir)) { if ($print_as_comment) echo ''; return true; } } // No need to scan ABSPATH - we don't backup there if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) { if ($print_as_comment) echo ''; return true; } if (is_file(ABSPATH.'wp-config-pre-ud-restore-backup.php')) { if ($print_as_comment) echo ''; return true; } return false; } /** * Outputs html for a storage method using the parameters passed in, this version should be removed when all remote storages use the multi version * * @param String $method a list of methods to be used when * @param String $header the table header content * @param String $contents the table contents */ public function storagemethod_row($method, $header, $contents) { ?>$text
$text
'.__('Warning', 'updraftplus').': '.__("Your web server's PHP/Curl installation does not support https access.", 'updraftplus').' '.sprintf(__("Communications with %s will be unencrypted.", 'updraftplus'), $service).' '.__("Ask your web host to install Curl/SSL in order to gain the ability for encryption (via an add-on).", 'updraftplus').'
'; } else { $ret .= $this->show_double_warning(''.__('Warning', 'updraftplus').': '.__("Your web server's PHP/Curl installation does not support https access.", 'updraftplus').' '.sprintf(__("We cannot access %s without this support.", 'updraftplus'), $service).' '.__("Please contact your web hosting provider's support.", 'updraftplus').' '.sprintf(__("%s requires Curl+https.", 'updraftplus'), $service).' '.__("Please do not file any support requests; there is no alternative.", 'updraftplus').'
', $extraclass, false); } } else { $ret .= ''.sprintf(__("Good news: Your site's communications with %s can be encrypted.", 'updraftplus'), $service).' '.__("If you see any errors to do with encryption, then look in the 'Expert Settings' for more help.", 'updraftplus').'
'; } } if ($echo_instead_of_return) { echo wp_kses_post($ret); } else { return $ret; } } /** * Get backup information in HTML format for a specific backup * * @param Array $backup_history all backups history * @param String $key backup timestamp * @param String $nonce backup nonce (job ID) * @param Array|Null $job_data if an array, then use this as the job data (if null, then it will be fetched directly) * * @return string HTML-formatted backup information */ public function raw_backup_info($backup_history, $key, $nonce, $job_data = null) { global $updraftplus; $backup = $backup_history[$key]; $only_remote_sent = !empty($backup['service']) && (array('remotesend') === $backup['service'] || 'remotesend' === $backup['service']); $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int) $key), 'M d, Y G:i'); $rawbackup = "'; $backupable_entities = $updraftplus->get_backupable_file_entities(true, true); $checksums = $updraftplus->which_checksums(); foreach ($backupable_entities as $type => $info) { if (!isset($backup[$type])) continue; $rawbackup .= $updraftplus->printfile($info['description'], $backup, $type, $checksums, $job_data, true); } $total_size = 0; foreach ($backup as $ekey => $files) { if ('db' == strtolower(substr($ekey, 0, 2)) && '-size' != substr($ekey, -5, 5)) { $rawbackup .= $updraftplus->printfile(__('Database', 'updraftplus'), $backup, $ekey, $checksums, $job_data, true); } if (!isset($backupable_entities[$ekey]) && ('db' != substr($ekey, 0, 2) || '-size' == substr($ekey, -5, 5))) continue; if (is_string($files)) $files = array($files); foreach ($files as $findex => $file) { $size_key = (0 == $findex) ? $ekey.'-size' : $ekey.$findex.'-size'; $total_size = (false === $total_size || !isset($backup[$size_key]) || !is_numeric($backup[$size_key])) ? false : $total_size + $backup[$size_key]; } } $services = empty($backup['service']) ? array('none') : $backup['service']; if (!is_array($services)) $services = array('none'); $rawbackup .= ''.__('Uploaded to:', 'updraftplus').' '; $show_services = ''; foreach ($services as $serv) { if ('none' == $serv || '' == $serv) { $add_none = true; } elseif (isset($updraftplus->backup_methods[$serv])) { $show_services .= $show_services ? ', '.$updraftplus->backup_methods[$serv] : $updraftplus->backup_methods[$serv]; } else { $show_services .= $show_services ? ', '.$serv : $serv; } } if ('' == $show_services && $add_none) $show_services .= __('None', 'updraftplus'); $rawbackup .= $show_services; if (false !== $total_size) { $rawbackup .= '
'.__('Total backup size:', 'updraftplus').' '.UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($total_size).''; } $rawbackup .= '
'.print_r($backup, true).''; if (!empty($job_data) && is_array($job_data)) { $rawbackup .= '
'.htmlspecialchars(print_r($job_data, true)).''; } return esc_attr($rawbackup); } /** * Display button to download the DB backup in the existing backups table. * * @param string $bkey Backup type. * @param string $key Backup timestamp (epoch time). * @param string $esc_pretty_date Escaped pretty date. * @param array $backup Backup Instance. * @param array $accept Accepted archive names. * @return void - Display download button for DB backup. */ private function download_db_button($bkey, $key, $esc_pretty_date, $backup, $accept = array()) { if (!empty($backup['meta_foreign']) && isset($accept[$backup['meta_foreign']])) { $desc_source = $accept[$backup['meta_foreign']]['desc']; } else { $desc_source = __('unknown source', 'updraftplus'); } if ('db' == $bkey) { $dbt = empty($backup['meta_foreign']) ? esc_attr(__('Database', 'updraftplus')) : esc_attr(sprintf(__('Database (created by %s)', 'updraftplus'), $desc_source)); } else { $dbt = __('External database', 'updraftplus').' ('.substr($bkey, 2).')'; } $this->download_button($bkey, $key, 0, null, '', $dbt, $esc_pretty_date, '0'); } /** * Go through each of the file entities * * @param Array $backup An array of meta information * @param Integer $key Backup timestamp (epoch time) * @param Array $accept An array of values to be accepted from values within $backup * @param String $entities Entities to be added * @param String $esc_pretty_date Escaped pretty date * @return Void - Display download buttons in existing backups table */ public function download_buttons($backup, $key, $accept, &$entities, $esc_pretty_date) { global $updraftplus; $backupable_entities = $updraftplus->get_backupable_file_entities(true, true); $first_entity = true;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- template foreach ($backupable_entities as $type => $info) { if (!empty($backup['meta_foreign']) && 'wpcore' != $type) continue; $ide = ''; if (empty($backup['meta_foreign'])) { $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']); if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription']; } else { $info['description'] = 'WordPress'; if (isset($accept[$backup['meta_foreign']])) { $desc_source = $accept[$backup['meta_foreign']]['desc']; $ide .= sprintf(__('Backup created by: %s.', 'updraftplus'), $accept[$backup['meta_foreign']]['desc']).' '; } else { $desc_source = __('unknown source', 'updraftplus'); $ide .= __('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus').' '; } $sdescrip = (empty($accept[$backup['meta_foreign']]['separatedb'])) ? sprintf(__('Files and database WordPress backup (created by %s)', 'updraftplus'), $desc_source) : sprintf(__('Files backup (created by %s)', 'updraftplus'), $desc_source); } if (isset($backup[$type])) { if (!is_array($backup[$type])) $backup[$type] = array($backup[$type]); $howmanyinset = count($backup[$type]); $expected_index = 0; $index_missing = false; $set_contents = ''; $entities .= "/$type="; $whatfiles = $backup[$type]; ksort($whatfiles); $total_file_size = 0; foreach ($whatfiles as $findex => $bfile) { $set_contents .= ('' == $set_contents) ? $findex : ",$findex"; if ($findex != $expected_index) $index_missing = true; $expected_index++; if ($howmanyinset > 0) { if (!empty($backup[$type.(($findex > 0) ? $findex : '')."-size"]) && $findex < $howmanyinset) $total_file_size += $backup[$type.(($findex > 0) ? $findex : '')."-size"]; } } $ide .= __('Press here to download or browse', 'updraftplus').' '.strtolower($info['description']); $ide .= ' '.sprintf(__('(%d archive(s) in set, total %s).', 'updraftplus'), $howmanyinset, UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($total_file_size)); if ($index_missing) $ide .= ' '.__('You are missing one or more archives from this multi-archive set.', 'updraftplus'); $entities .= $set_contents.'/'; if (!empty($backup['meta_foreign'])) { $entities .= '/plugins=0//themes=0//uploads=0//others=0/'; } $this->download_button($type, $key, 0, null, $ide, $sdescrip, $esc_pretty_date, $set_contents); } } } /** * Function to get the download button data from a list of backups * * @param Array $backup_history the backup history. * @return Array An array of download button data from the passed in backup history. */ public function get_download_buttons_data($backup_history) { global $updraftplus; $accept = apply_filters('updraftplus_accept_archivename', array()); if (!is_array($accept)) $accept = array(); $backupable_entities = $updraftplus->get_backupable_file_entities(true, true); $button_data = array(); foreach ($backup_history as $key => $backup) { $remote_sent = !empty($backup['service']) && ((is_array($backup['service']) && in_array('remotesend', $backup['service'])) || 'remotesend' === $backup['service']); $button_data[$key] = array( 'remote_sent' => $remote_sent, 'downloads' => array(), ); // Just skip if remote sent is true. if ($remote_sent) { continue; } // https://core.trac.wordpress.org/ticket/25331 explains why the following line is wrong // $pretty_date = date_i18n('Y-m-d G:i',$key); // Convert to blog time zone // $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$key), 'Y-m-d G:i'); $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int) $key), 'M d, Y G:i'); if (empty($backup['meta_foreign']) || !empty($accept[$backup['meta_foreign']]['separatedb'])) { if (isset($backup['db'])) { $entities = '/db=0/'; // Set a flag according to whether or not $backup['db'] ends in .crypt, then pick this up in the display of the decrypt field. $db = is_array($backup['db']) ? $backup['db'][0] : $backup['db']; if (UpdraftPlus_Encryption::is_file_encrypted($db)) $entities .= '/dbcrypted=1/'; $button_data[$key]['downloads']['db'] = array( 'pretty_date' => $pretty_date, 'entities' => $entities, 'set_contents' => '0', 'title' => __('Database', 'updraftplus'), ); } // External databases foreach ($backup as $bkey => $binfo) { if ('db' == $bkey || 'db' != substr($bkey, 0, 2) || '-size' == substr($bkey, -5, 5)) continue; $entities = '/'.$bkey.'=0/'; $button_data[$key]['downloads'][$bkey] = array( 'pretty_date' => $pretty_date, 'entities' => $entities, 'set_contents' => '0', 'title' => __('External database', 'updraftplus').' ('.substr($bkey, 2).')', ); } } else { // Foreign without separate db $entities = '/db=0/meta_foreign=1/'; $button_data[$key]['downloads']['db'] = array( 'pretty_date' => $pretty_date, 'entities' => $entities, 'set_contents' => '0', 'title' => __('Database', 'updraftplus'), ); } if (!empty($backup['meta_foreign']) && !empty($accept[$backup['meta_foreign']]) && !empty($accept[$backup['meta_foreign']]['separatedb'])) { $entities = '/db=0/meta_foreign=2/'; $button_data[$key]['downloads']['db'] = array( 'pretty_date' => $pretty_date, 'entities' => $entities, 'set_contents' => '0', 'title' => __('Database', 'updraftplus'), ); } foreach ($backupable_entities as $type => $info) { if (!empty($backup['meta_foreign']) && 'wpcore' != $type) continue; $ide = ''; if (empty($backup['meta_foreign'])) { $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']); if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription']; } else { $info['description'] = 'WordPress'; if (isset($accept[$backup['meta_foreign']])) { $desc_source = $accept[$backup['meta_foreign']]['desc']; $ide .= sprintf(__('Backup created by: %s.', 'updraftplus'), $accept[$backup['meta_foreign']]['desc']).' '; } else { $desc_source = __('unknown source', 'updraftplus'); $ide .= __('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus').' '; } $sdescrip = (empty($accept[$backup['meta_foreign']]['separatedb'])) ? sprintf(__('Files and database WordPress backup (created by %s)', 'updraftplus'), $desc_source) : sprintf(__('Files backup (created by %s)', 'updraftplus'), $desc_source); } if (isset($backup[$type])) { if (!is_array($backup[$type])) $backup[$type] = array($backup[$type]); $howmanyinset = count($backup[$type]); $expected_index = 0; $index_missing = false; $set_contents = ''; $entities = "/$type="; $whatfiles = $backup[$type]; ksort($whatfiles); $total_file_size = 0; foreach ($whatfiles as $findex => $bfile) { $set_contents .= ('' == $set_contents) ? $findex : ",$findex"; if ($findex != $expected_index) $index_missing = true; $expected_index++; if ($howmanyinset > 0) { if (!empty($backup[$type.(($findex > 0) ? $findex : '')."-size"]) && $findex < $howmanyinset) $total_file_size += $backup[$type.(($findex > 0) ? $findex : '')."-size"]; } } $ide .= __('Press here to download or browse', 'updraftplus').' '.strtolower($info['description']); $ide .= ' '.sprintf(__('(%d archive(s) in set, total %s).', 'updraftplus'), $howmanyinset, UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($total_file_size)); if ($index_missing) $ide .= ' '.__('You are missing one or more archives from this multi-archive set.', 'updraftplus'); $entities .= $set_contents.'/'; if (!empty($backup['meta_foreign'])) { $entities .= '/plugins=0//themes=0//uploads=0//others=0/'; } $button_data[$key]['downloads'][$type] = array( 'pretty_date' => $pretty_date, 'entities' => $entities, 'set_contents' => $set_contents, 'title' => $sdescrip, 'ide' => $ide, ); } } } return $button_data; } /** * Return HTML for 'Backup date' column in existing backups data table. * * @param string $pretty_date Pretty date. * @param string $key Backup timestamp (epoch time). * @param array $backup Backup instance. * @param array $jobdata Job data. * @param string $nonce Nonce. * @param bool $simple_format Whether to display simple format or not. Default false. * @return string - Return HTML for date label. */ public function date_label($pretty_date, $key, $backup, $jobdata, $nonce, $simple_format = false) { $pretty_date = $simple_format ? $pretty_date : '
'; $updraftplus->log_e('Restore successful!'); echo '
'; $updraftplus->log('Restore successful'); $s_val = 1; if (!empty($this->entities_to_restore) && is_array($this->entities_to_restore)) { foreach ($this->entities_to_restore as $v) { if ('db' != $v) $s_val = 2; } } $pval = $updraftplus->have_addons ? 1 : 0; echo ''.esc_html__('Actions', 'updraftplus').': '.esc_html__('Return to UpdraftPlus configuration', 'updraftplus').''; return; } elseif (is_wp_error($backup_success)) { echo ''; $updraftplus->log_e('Restore failed...'); echo '
'; $updraftplus->log_wp_error($backup_success); $updraftplus->log('Restore failed'); echo ''; $updraftplus->log_e('Restore failed...'); echo '
'; $updraftplus->log("Restore failed"); echo ''.esc_html__('Warning: If you can still read these words after the page finishes loading, then there is a JavaScript or jQuery problem in the site.', 'updraftplus').' '.esc_html__('This may prevent the restore procedure from being able to proceed.', 'updraftplus').''; echo ' '.esc_html__('Go here for more information.', 'updraftplus').'
'; echo ''.sprintf(esc_html__('The restore operation has begun (%s).', 'updraftplus'), $updraftplus->nonce).' '. esc_html__('Do not close this page until it reports itself as having finished.', 'updraftplus').'
'; echo ''.esc_html__('This backup does not exist in the backup history - restoration aborted.', 'updraftplus').' '.esc_html__('Timestamp:', 'updraftplus').' '.esc_html($timestamp).'
'.esc_html__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'
'.esc_html__('If making a request for support, please include this information:', 'updraftplus').' '.count($restore_jobdata).' : '.esc_html(serialize($restore_jobdata)).'
'; return new WP_Error('missing_info', 'Backup information not found'); } // This is used in painting the admin page after a successful restore $this->entities_to_restore = $entities_to_restore; $error_levels = version_compare(PHP_VERSION, '8.4.0', '>=') ? E_ALL : E_ALL & ~E_STRICT; // This will be removed by Updraft_Restorer::post_restore_clean_up() set_error_handler(array($updraftplus, 'php_error'), $error_levels); // Set $restore_options, either from the continuation data, or from $_POST if (!empty($continuation_data['restore_options'])) { $restore_options = $continuation_data['restore_options']; } else { // Gather the restore options into one place - code after here should read the options $restore_options = $this->get_restore_options_from_jobdata(); $updraftplus->jobdata_set('restore_options', $restore_options); } add_action('updraftplus_restoration_title', array($this, 'restoration_title')); $updraftplus->log_restore_update(array('type' => 'state', 'stage' => 'started', 'data' => array())); // We use a single object for each entity, because we want to store information about the backup set $updraftplus_restorer = new Updraft_Restorer(new Updraft_Restorer_Skin, $backup_set, false, $restore_options, $continuation_data); $restore_result = $updraftplus_restorer->perform_restore($entities_to_restore, $restore_options); $updraftplus_restorer->post_restore_clean_up($restore_result); $pval = $updraftplus->have_addons ? 1 : 0; $sval = (true === $restore_result) ? 1 : 0; $pages = get_pages(array('number' => 2)); $page_urls = array( 'home' => get_home_url(), ); foreach ($pages as $page_info) { $page_urls[$page_info->post_name] = get_page_link($page_info->ID); } $updraftplus->log_restore_update( array( 'type' => 'state', 'stage' => 'finished', 'data' => array( 'actions' => array( __('Return to UpdraftPlus configuration', 'updraftplus') => UpdraftPlus_Options::admin_page_url() . '?page=updraftplus&updraft_restore_success=' . $sval . '&pval=' . $pval ), 'urls' => $page_urls, ) ) ); return $restore_result; } /** * Called when the restore process wants to print a title * * @param String $title - title */ public function restoration_title($title) { echo ''.__('No remote storage locations with valid options found.', 'updraftplus').'
'; } return ' (...)'; ob_start(); $history = UpdraftPlus_Backup_History::get_history(); var_dump($history); $response["html"] .= ob_get_clean(); $response['html'] .= ''; $response['html'] .= '
';
$updraft_dir = $updraftplus->backups_dir_location();
$raw_output = array();
$d = dir($updraft_dir);
while (false !== ($entry = $d->read())) {
$fp = $updraft_dir.'/'.$entry;
$mtime = filemtime($fp);
if (is_dir($fp)) {
$size = ' d';
} elseif (is_link($fp)) {
$size = ' l';
} elseif (is_file($fp)) {
$size = sprintf("%8.1f", round(filesize($fp)/1024, 1)).' '.gmdate('r', $mtime);
} else {
$size = ' ?';
}
if (preg_match('/^log\.(.*)\.txt$/', $entry, $lmatch)) $entry = ''.$entry.'';
$raw_output[$mtime] = empty($raw_output[$mtime]) ? sprintf("%s %s\n", $size, $entry) : $raw_output[$mtime].sprintf("%s %s\n", $size, $entry);
}
@$d->close();// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the method.
krsort($raw_output, SORT_NUMERIC);
foreach ($raw_output as $line) {
$response['html'] .= $line;
}
$response['html'] .= '';
$response['html'] .= '| '.htmlspecialchars($opt).' | '.htmlspecialchars(print_r(UpdraftPlus_Options::get_updraft_option($opt), true)).' | '; } // Get the option saved by yahnis-elsts/plugin-update-checker $response['html'] .= '
| external_updates-updraftplus | '.htmlspecialchars(print_r(get_site_option('external_updates-updraftplus'), true)).' | ';
$response['html'] .= '
', '', $response['html']);
$response['html'] = str_replace('', '', $response['html']);
}
return $response;
}
/**
* This will call any wp_action
*
* @param Array|Null $data The array of data with the values for wpaction
* @param Callable|Boolean $close_connection_callable A callable to call to close the browser connection, or true for a default suitable for internal use, or false for none
* @return Array - results
*/
public function call_wp_action($data = null, $close_connection_callable = false) {
global $updraftplus;
ob_start();
$res = 'Request received: ';
if (preg_match('/^([^:]+)+:(.*)$/', $data['wpaction'], $matches)) {
$action = $matches[1];
if (null === ($args = json_decode($matches[2], true))) {
$res .= "The parameters (should be JSON) could not be decoded";
$action = false;
} else {
if (is_string($args)) $args = array($args);
$res .= "Will despatch action: ".htmlspecialchars($action).", parameters: ".htmlspecialchars(implode(',', $args));
}
} else {
$action = $data['wpaction'];
$res .= "Will despatch action: ".htmlspecialchars($action).", no parameters";
}
ob_get_clean();
// Need to add this as the close browser should only work for UDP
if ($close_connection_callable) {
if (is_callable($close_connection_callable)) {
call_user_func($close_connection_callable, array('r' => $res));
} else {
$updraftplus->close_browser_connection(json_encode(array('r' => $res)));
}
}
if (!empty($action)) {
if (!empty($args)) {
ob_start();
$returned = do_action_ref_array($action, $args);
$output = ob_get_clean();
$res .= " - do_action_ref_array Trigger ";
} else {
ob_start();
do_action($action);
$output = ob_get_contents();
ob_end_clean();
$res .= " - do_action Trigger ";
}
}
$response = array();
$response['response'] = $res;
$response['log'] = $output;
// Check if response is empty
if (!empty($returned)) $response['status'] = $returned;
return $response;
}
/**
* Enqueue JSTree JavaScript and CSS, taking into account whether it is already enqueued, and current debug settings
*/
public function enqueue_jstree() {
global $updraftplus;
static $already_enqueued = false;
if ($already_enqueued) return;
$already_enqueued = true;
$jstree_enqueue_version = $updraftplus->use_unminified_scripts() ? '3.3.12-rc.0'.'.'.time() : '3.3.12-rc.0';
$min_or_not = $updraftplus->use_unminified_scripts() ? '' : '.min';
wp_enqueue_script('jstree', UPDRAFTPLUS_URL.'/includes/jstree/jstree'.$min_or_not.'.js', array('jquery'), $jstree_enqueue_version);
wp_enqueue_style('jstree', UPDRAFTPLUS_URL.'/includes/jstree/themes/default/style'.$min_or_not.'.css', array(), $jstree_enqueue_version);
}
/**
* Detects byte-order mark at the start of common files and change waning message texts
*
* @return string|boolean BOM warning text or false if not bom characters detected
*/
public function get_bom_warning_text() {
$files_to_check = array(
ABSPATH.'wp-config.php',
get_template_directory().DIRECTORY_SEPARATOR.'functions.php',
);
if (is_child_theme()) {
$files_to_check[] = get_stylesheet_directory().DIRECTORY_SEPARATOR.'functions.php';
}
$corrupted_files = array();
foreach ($files_to_check as $file) {
if (!file_exists($file)) continue;
if (false === ($fp = fopen($file, 'r'))) continue;
if (false === ($file_data = fread($fp, 8192)));
fclose($fp);
$substr_file_data = array();
for ($substr_length = 2; $substr_length <= 5; $substr_length++) {
$substr_file_data[$substr_length] = substr($file_data, 0, $substr_length);
}
// Detect UTF-7, UTF-8, UTF-16 (BE), UTF-16 (LE), UTF-32 (BE) & UTF-32 (LE) Byte order marks (BOM)
$bom_decimal_representations = array(
array(43, 47, 118, 56), // UTF-7 (Hexadecimal: 2B 2F 76 38)
array(43, 47, 118, 57), // UTF-7 (Hexadecimal: 2B 2F 76 39)
array(43, 47, 118, 43), // UTF-7 (Hexadecimal: 2B 2F 76 2B)
array(43, 47, 118, 47), // UTF-7 (Hexadecimal: 2B 2F 76 2F)
array(43, 47, 118, 56, 45), // UTF-7 (Hexadecimal: 2B 2F 76 38 2D)
array(239, 187, 191), // UTF-8 (Hexadecimal: 2B 2F 76 38 2D)
array(254, 255), // UTF-16 (BE) (Hexadecimal: FE FF)
array(255, 254), // UTF-16 (LE) (Hexadecimal: FF FE)
array(0, 0, 254, 255), // UTF-32 (BE) (Hexadecimal: 00 00 FE FF)
array(255, 254, 0, 0), // UTF-32 (LE) (Hexadecimal: FF FE 00 00)
);
foreach ($bom_decimal_representations as $bom_decimal_representation) {
$no_of_chars = count($bom_decimal_representation);
array_unshift($bom_decimal_representation, 'C*');
$binary = call_user_func_array('pack', $bom_decimal_representation);
if ($binary == $substr_file_data[$no_of_chars]) {
$corrupted_files[] = $file;
break;
}
}
}
if (empty($corrupted_files)) {
return false;
} else {
$corrupted_files_count = count($corrupted_files);
/* translators: %s: List of corrupted files */
return ''.__('Warning', 'updraftplus').': '.
sprintf(_n('The file %s has a "byte order mark" (BOM) at its beginning.', 'The files %s have a "byte order mark" (BOM) at their beginning.', $corrupted_files_count, 'updraftplus'), ''.implode(', ', $corrupted_files).'').
' '.__('Follow this link for more information', 'updraftplus').'';
}
}
/**
* Gets an instance of the "UpdraftPlus_UpdraftCentral_Cloud" class which will be
* used to login or register the user to the UpdraftCentral cloud
*
* @return object
*/
public function get_updraftcentral_cloud() {
if (!class_exists('UpdraftPlus_UpdraftCentral_Cloud')) updraft_try_include_file('includes/updraftcentral.php', 'include_once');
return new UpdraftPlus_UpdraftCentral_Cloud();
}
/**
* This function will build and return the UpdraftPlus temporary clone ui widget
*
* @param boolean $include_testing_ui - a boolean to indicate if testing-only UI elements should be shown (N.B. they can only work if the user also has testing permissions)
* @param array $supported_wp_versions - an array of supported WordPress versions
* @param array $supported_packages - an array of supported clone packages
* @param array $supported_regions - an array of supported clone regions
* @param string $nearest_region - the user's nearest region
* @param array $supported_packages_label - an array of supported clone packages label
*
* @return string - the clone UI widget
*/
public function updraftplus_clone_ui_widget($include_testing_ui, $supported_wp_versions, $supported_packages, $supported_regions, $nearest_region = '', $supported_packages_label = array()) {
global $updraftplus;
$output = ''; /* translators: %s: PHP version label */ $output .= ''.sprintf(__('%s version:', 'updraftplus'), 'PHP').' '; $output .= $this->output_select_data($this->clone_php_versions, 'php'); $output .= '
'; $output .= ''; /* translators: %s: WordPress version label */ $output .= ' '.sprintf(__('%s version:', 'updraftplus'), 'WordPress').' '; $output .= $this->output_select_data($this->get_wordpress_versions($supported_wp_versions), 'wp'); $output .= '
'; $output .= ''; $output .= ' '.__('Clone region:', 'updraftplus').' '; $output .= $this->output_select_data($supported_regions, 'region', $nearest_region); $output .= '
'; $backup_history = UpdraftPlus_Backup_History::get_history(); foreach ($backup_history as $key => $backup) { $backup_complete = $this->check_backup_is_complete($backup, false, true, false); $remote_sent = !empty($backup['service']) && ((is_array($backup['service']) && in_array('remotesend', $backup['service'])) || 'remotesend' === $backup['service']); if (!$backup_complete || $remote_sent) unset($backup_history[$key]); } $output .= ''; $output .= ' '.__('Clone:', 'updraftplus').' '; $output .= ''; $output .= '
'; $output .= ''; $output .= ' '.__('Clone package', 'updraftplus').' ('.__('more info', 'updraftplus').'): '; $output .= ''; $output .= '
'; if ((defined('UPDRAFTPLUS_UPDRAFTCLONE_DEVELOPMENT') && UPDRAFTPLUS_UPDRAFTCLONE_DEVELOPMENT) || $include_testing_ui) { $output .= ''; $output .= ' UpdraftClone Branch: '; $output .= ''; $output .= '
'; $output .= ''; $output .= ' UpdraftPlus Branch: '; $output .= ''; $output .= '
'; $output .= ''; } $output .= ''; $output .= ''; $output .= ''; $output .= '
'; $output = apply_filters('updraftplus_clone_additional_ui', $output); return $output; } /** * This function will output a select input using the passed in values. * * @param array $data - the keys and values for the select * @param string $name - the name of the items in the select input * @param string $selected - the value we want selected by default * * @return string - the output of the select input */ public function output_select_data($data, $name, $selected = '') { $name_version = empty($selected) ? $this->get_current_version($name) : $selected; $output = ''; return $output; } /** * This function will output the clones network information * * @param string $url - the clone URL * * @return string - the clone network information */ public function updraftplus_clone_info($url) { global $updraftplus; if (!empty($url)) { $content = '' . __('Your clone has started and will be available at the following URLs once it is ready.', 'updraftplus') . '
'; $content .= '' . __('Front page:', 'updraftplus') . ' ' . esc_html($url) . '
'; $content .= '' . __('Dashboard:', 'updraftplus') . ' ' . esc_html(trailingslashit($url)) . 'wp-admin
'; $content .= '' . __('Your clone has started, network information is not yet available but will be displayed here and at your teamupdraft.com account once it is ready.', 'updraftplus') . '
'; $content .= ''; } return $content; } /** * This function will build and return an array of major WordPress versions, the array is built by calling the WordPress version API once every 24 hours and adding any new entries to our existing array of versions. * * @param array $supported_wp_versions - an array of supported WordPress versions * * @return array - an array of WordPress major versions */ private function get_wordpress_versions($supported_wp_versions) { if (empty($supported_wp_versions)) $supported_wp_versions[] = $this->get_current_version('wp'); $key = array_search($this->get_current_version('wp'), $supported_wp_versions); if ($key) { $supported_wp_versions = array_slice($supported_wp_versions, $key); } $version_array = $supported_wp_versions; return $version_array; } /** * This function will get the current version the server is running for the passed in item e.g WordPress or PHP * * @param string $name - the thing we want to get the version for e.g WordPress or PHP * * @return string - returns the current version of the passed in item */ public function get_current_version($name) { $version = ''; if ('php' == $name) { $parts = explode(".", PHP_VERSION); $version = $parts[0] . "." . $parts[1]; } elseif ('wp' == $name) { global $updraftplus; $wp_version = $updraftplus->get_wordpress_version(); $parts = explode(".", $wp_version); $version = $parts[0] . "." . $parts[1]; } return $version; } /** * Show which remote storage settings are partially setup error, or if manual auth is supported show the manual auth UI */ public function show_admin_warning_if_remote_storage_with_partial_settings() { if ((isset($_REQUEST['page']) && 'updraftplus' == $_REQUEST['page']) || (defined('DOING_AJAX') && DOING_AJAX)) { $enabled_services = UpdraftPlus_Storage_Methods_Interface::get_enabled_storage_objects_and_ids(array_keys($this->storage_service_with_partial_settings)); foreach ($this->storage_service_with_partial_settings as $method => $method_name) { if (empty($enabled_services[$method]['object']) || empty($enabled_services[$method]['instance_settings']) || !$enabled_services[$method]['object']->supports_feature('manual_authentication')) { /* translators: %s: Remote storage method */ $this->show_admin_warning(sprintf(__('The following remote storage (%s) has only been partially configured, manual authorization is not supported with this remote storage, please try again and if the problem persists contact support.', 'updraftplus'), $method), 'error'); } else { $this->show_admin_warning($enabled_services[$method]['object']->get_manual_authorisation_template(), 'error'); } } } else { $this->show_admin_warning( /* translators: %s: List of storage services */ 'UpdraftPlus: '.sprintf(__('The following remote storage (%s) has only been partially configured, if you are having problems you can try to manually authorise at the UpdraftPlus settings page.', 'updraftplus'), implode(', ', $this->storage_service_with_partial_settings)). ' '.__('Return to UpdraftPlus configuration', 'updraftplus').'', 'error' ); } } /** * Show remote storage settings are empty warning */ public function show_admin_warning_if_remote_storage_setting_are_empty() { if ((isset($_REQUEST['page']) && 'updraftplus' == $_REQUEST['page']) || (defined('DOING_AJAX') && DOING_AJAX)) { /* translators: %s: List of storage services */ $this->show_admin_warning(sprintf(__('You have requested saving to remote storage (%s), but without entering any settings for that storage.', 'updraftplus'), implode(', ', $this->storage_service_without_settings)), 'error'); } else { $this->show_admin_warning( /* translators: %s: List of storage services */ 'UpdraftPlus: '.sprintf(__('You have requested saving to remote storage (%s), but without entering any settings for that storage.', 'updraftplus'), implode(', ', $this->storage_service_without_settings)). ' '.__('Return to UpdraftPlus configuration', 'updraftplus').'', 'error' ); } } /** * Show remote storage warning when one or more cloud storage options are selected but the add-ons are not installed */ public function show_admin_warning_if_remote_storage_without_addons() { global $updraftplus; $storage_service_without_addons = implode(', ', $this->storage_service_without_addons_settings); /* translators: %s: UpdraftPlus */ $notice_label1 = sprintf(__('You have selected storage options which are not part of your version of %s.', 'updraftplus'), 'UpdraftPlus'); /* translators: 1: Storage service name, 2: Link to UpdraftPlus Premium upgrade */ $notice_label2 = sprintf(__('To backup to %1$s, please upgrade to %2$s.', 'updraftplus'), $storage_service_without_addons, 'UpdraftPlus Premium'); /* translators: %s: UpdraftPlus */ $notice_label3 = sprintf(__('Where are my %s backups stored?', 'updraftplus'), 'UpdraftPlus'); /* translators: %s: UpdraftPlus */ $notice_label4 = ''.sprintf(__('Return to %s configuration', 'updraftplus'), 'UpdraftPlus').''; /* translators: %s: Link to storage comparison */ $notice_label5 = sprintf(__('To see which remote storage locations are included in free and premium, please see here: %s', 'updraftplus'), ''.$notice_label3.''); if ((isset($_REQUEST['page']) && 'updraftplus' == $_REQUEST['page']) || (defined('DOING_AJAX') && DOING_AJAX)) { $this->show_admin_warning($notice_label1.' '.$notice_label2.' '.$notice_label5, 'error'); } else { $this->show_admin_warning('UpdraftPlus: '.$notice_label1.' '.$notice_label2.' '.$notice_label5.' '.$notice_label4, 'error'); } } /** * Receive Heartbeat data and respond. * * Processes data received via a Heartbeat request, and returns additional data to pass back to the front end. * * @param array $response - Heartbeat response data to pass back to front end. * @param array $data - Data received from the front end (unslashed). */ public function process_status_in_heartbeat($response, $data) { if (!UpdraftPlus_Options::user_can_manage() || !is_array($response) || empty($data['updraftplus'])) return $response; try { $response['updraftplus'] = $this->get_activejobs_list(UpdraftPlus_Manipulation_Functions::wp_unslash($data['updraftplus'])); } catch (Exception $e) { $log_message = 'PHP Fatal Exception error ('.get_class($e).') has occurred during get active job list. Error Message: '.$e->getMessage().' (Code: '.$e->getCode().', line '.$e->getLine().' in '.$e->getFile().')'; error_log($log_message); $response['updraftplus'] = array( 'fatal_error' => true, 'fatal_error_message' => $log_message ); // @codingStandardsIgnoreLine } catch (Error $e) { $log_message = 'PHP Fatal error ('.get_class($e).') has occurred during get active job list. Error Message: '.$e->getMessage().' (Code: '.$e->getCode().', line '.$e->getLine().' in '.$e->getFile().')'; error_log($log_message); $response['updraftplus'] = array( 'fatal_error' => true, 'fatal_error_message' => $log_message ); } if (isset($data['updraftplus']['updraft_credentialtest_nonce'])) { if (!wp_verify_nonce($data['updraftplus']['updraft_credentialtest_nonce'], 'updraftplus-credentialtest-nonce')) { $response['updraftplus']['updraft_credentialtest_nonce'] = wp_create_nonce('updraftplus-credentialtest-nonce'); } } $response['updraftplus']['time_now'] = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i'); return $response; } /** * Show warning about restriction implied by the hosting company (can only perform a full backup once per month, incremental backup should not go above one per day) */ public function show_admin_warning_one_backup_per_month() { global $updraftplus; $hosting_company = $updraftplus->get_hosting_info(); /* translators: 1: Hosting company name, 2: Website link */ $txt1 = sprintf(__('Your website is hosted with %1$s (%2$s).', 'updraftplus'), $hosting_company['name'], $hosting_company['website']); /* translators: %s: Hosting company name */ $txt2 = sprintf(__('%s permits UpdraftPlus to perform only one backup per month.', 'updraftplus'), $hosting_company['name']).' '. __('Thus, we recommend you choose a full backup when performing a manual backup and to use that option when creating a scheduled backup.', 'updraftplus'); $txt3 = __('Due to the restriction, some settings can be automatically adjusted, disabled or not available.', 'updraftplus'); $this->show_plugin_page_admin_warning(''.__('Warning', 'updraftplus').': '.$txt1.' '.$txt2.' '.$txt3, 'update-nag notice notice-warning', true); } /** * Find out if the current request is a backup download request, and proceed with the download if it is */ public function maybe_download_backup_from_email() { global $pagenow; if (UpdraftPlus_Options::user_can_manage() && (!defined('DOING_AJAX') || !DOING_AJAX) && UpdraftPlus_Options::admin_page() === $pagenow && isset($_REQUEST['page']) && 'updraftplus' === $_REQUEST['page'] && isset($_REQUEST['action']) && 'updraft_download_backup' === $_REQUEST['action']) { $findexes = empty($_REQUEST['findex']) ? array(0) : $_REQUEST['findex']; $timestamp = empty($_REQUEST['timestamp']) ? '' : $_REQUEST['timestamp']; $nonce = empty($_REQUEST['nonce']) ? '' : $_REQUEST['nonce']; $type = empty($_REQUEST['type']) ? '' : $_REQUEST['type']; if (empty($timestamp) || empty($nonce) || empty($type)) wp_die(esc_html__('The download link is broken, you may have clicked the link from untrusted source', 'updraftplus'), '', array('back_link' => true)); $backup_history = UpdraftPlus_Backup_History::get_history(); if (!isset($backup_history[$timestamp]['nonce']) || $backup_history[$timestamp]['nonce'] !== $nonce) wp_die(esc_html__("The download link is broken or the backup file is no longer available", 'updraftplus'), '', array('back_link' => true)); $this->do_updraft_download_backup($findexes, $type, $timestamp, 2, false, ''); exit; // we don't need anything else but an exit } } /** * Print the phpseclib-notice-related scripts */ public function print_phpseclib_notice_scripts() { static $printed = false; if ($printed) return; $printed = true; ?> > An associative array where the keys are HTML tag names * and the values are arrays of allowed attributes for * each tag. The attribute arrays use attribute names * as keys and `true` as the value to indicate the attribute * is allowed. */ public function kses_allow_tags() { return array( 'div' => array( 'id' => true, 'class' => true, 'style' => true, ), 'h3' => array( 'style' => true, ), 'input' => array( 'id' => true, 'class' => true, 'type' => true, 'name' => true, 'value' => true, 'checked' => true, 'style' => true, 'min' => true, 'step' => true, ), 'select' => array( 'id' => true, 'class' => true, 'name' => true, 'value' => true, 'style' => true, ), 'option' => array( 'value' => true, 'selected' => true, ), 'label' => array( 'id' => true, 'class' => true, 'style' => true, 'for' => true, ), 'br' => array(), 'em' => array(), 'a' => array( 'id' => true, 'class' => true, 'style' => true, 'href' => true, 'target' => true, 'onclick' => true, 'data-type' => true, 'data-incremental' => true, ), 'span' => array( 'id' => true, 'class' => true, 'style' => true, ), 'img' => array( 'id' => true, 'class' => true, 'style' => true, 'src' => true, 'width' => true, 'height' => true, 'alt' => true, ), 'p' => array( 'id' => true, 'class' => true, 'style' => true, ), ); } /** * Print the unfinished restoration dialog scripts */ public function print_unfinished_restoration_dialog_scripts() { ?>