PATH:
home
/
thebhoeo
/
.trash
/
backwpup
/
inc
<?php use Inpsyde\Restore\ViewLoader; /** * Class For BackWPup Jobs page. */ class BackWPup_Page_Jobs extends WP_List_Table { /** * Nonce action for list filters and sorting. */ private const LIST_NONCE_ACTION = 'backwpup_jobs_list'; /** * Log file path. * * @var string */ public static $logfile; /** * List table object * * @var self */ private static $listtable; /** * Job object. * * @var bool|object */ private $job_object; /** * Job types. * * @var array */ private $job_types; /** * Destinations array. * * @var array */ private $destinations; /** * Constructor. */ public function __construct() { parent::__construct( [ 'plural' => 'jobs', 'singular' => 'job', 'ajax' => true, ] ); } /** * Check if the current user has backwpup capability. * * @return bool */ public function ajax_user_can() { return current_user_can( 'backwpup' ); } /** * Get filtered jobs based on the status UI filter. * * @return array */ private function get_filtered_jobs() { $jobs = array_filter( BackWPup_Option::get_job_ids(), function ( $job_id ) { return BackWPup_Option::get( $job_id, 'legacy', false ); } ); // Get the "status" filter value from the GET request. $status_filter = ''; $nonce = $this->get_list_nonce(); if ( $nonce && wp_verify_nonce( $nonce, self::LIST_NONCE_ACTION ) ) { $status_filter = filter_input( INPUT_GET, 'status', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); if ( null === $status_filter && isset( $_GET['status'] ) ) { $status_filter = sanitize_text_field( wp_unslash( $_GET['status'] ) ); } else { $status_filter = $status_filter ? sanitize_text_field( $status_filter ) : ''; } } if ( empty( $status_filter ) ) { return $jobs; } return array_filter( $jobs, function ( $job_id ) use ( $status_filter ) { switch ( $status_filter ) { case 'disabled': return empty( BackWPup_Option::get( $job_id, 'activetype', '' ) ); } return true; } ); } /** * Prepares the list of items for displaying. * * @return void */ public function prepare_items() { $this->items = $this->get_filtered_jobs(); $this->job_object = BackWPup_Job::get_working_data(); $this->job_types = BackWPup::get_job_types(); $this->destinations = BackWPup::get_registered_destinations(); $order_param = ''; $orderby_param = ''; $nonce = $this->get_list_nonce(); if ( $nonce && wp_verify_nonce( $nonce, self::LIST_NONCE_ACTION ) ) { $order_param = filter_input( INPUT_GET, 'order', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); if ( null === $order_param && isset( $_GET['order'] ) ) { $order_param = sanitize_text_field( wp_unslash( $_GET['order'] ) ); } else { $order_param = $order_param ? sanitize_text_field( $order_param ) : ''; } $order_param = $order_param ? sanitize_key( $order_param ) : ''; $orderby_param = filter_input( INPUT_GET, 'orderby', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); if ( null === $orderby_param && isset( $_GET['orderby'] ) ) { $orderby_param = sanitize_text_field( wp_unslash( $_GET['orderby'] ) ); } else { $orderby_param = $orderby_param ? sanitize_text_field( $orderby_param ) : ''; } $orderby_param = $orderby_param ? sanitize_key( $orderby_param ) : ''; } if ( empty( $order_param ) || empty( $orderby_param ) ) { return; } if ( 'asc' === strtolower( (string) $order_param ) ) { $order = SORT_ASC; } else { $order = SORT_DESC; } if ( empty( $orderby_param ) || ! in_array( strtolower( (string) $orderby_param ), [ 'jobname', 'type', 'dest', 'next', 'last' ], true ) ) { $orderby = 'jobname'; } else { $orderby = strtolower( (string) $orderby_param ); } // Sorting. $job_configs = []; $i = 0; foreach ( $this->items as $item ) { $job_configs[ $i ]['jobid'] = $item; $job_configs[ $i ]['jobname'] = BackWPup_Option::get( $item, 'name' ); $job_configs[ $i ]['type'] = BackWPup_Option::get( $item, 'type' ); $job_configs[ $i ]['dest'] = BackWPup_Option::get( $item, 'destinations' ); if ( SORT_ASC === $order ) { sort( $job_configs[ $i ]['type'] ); sort( $job_configs[ $i ]['dest'] ); } else { rsort( $job_configs[ $i ]['type'] ); rsort( $job_configs[ $i ]['dest'] ); } $job_configs[ $i ]['type'] = array_shift( $job_configs[ $i ]['type'] ); $job_configs[ $i ]['dest'] = array_shift( $job_configs[ $i ]['dest'] ); $job_configs[ $i ]['next'] = (int) wp_next_scheduled( 'backwpup_cron', [ 'arg' => $item ] ); $job_configs[ $i ]['last'] = BackWPup_Option::get( $item, 'lastrun' ); ++$i; } $tmp = []; foreach ( $job_configs as &$ma ) { $tmp[] = &$ma[ $orderby ]; } array_multisort( $tmp, $order, $job_configs ); $this->items = []; foreach ( $job_configs as $item ) { $this->items[] = $item['jobid']; } } /** * Message to be displayed when there are no items. * * @return void */ public function no_items() { esc_html_e( 'No Legacy Jobs.', 'backwpup' ); } /** * Retrieves the list of bulk actions available for this table. * * @return array */ public function get_bulk_actions() { if ( ! $this->has_items() ) { return []; } $actions = []; $actions['delete'] = __( 'Delete', 'backwpup' ); return wpm_apply_filters_typed( 'array', 'backwpup_page_jobs_get_bulk_actions', $actions ); } /** * Gets a list of columns. * * @return array */ public function get_columns() { $jobs_columns = []; $jobs_columns['cb'] = '<input type="checkbox" />'; $jobs_columns['jobname'] = __( 'Job Name', 'backwpup' ); $jobs_columns['type'] = __( 'Type', 'backwpup' ); $jobs_columns['dest'] = __( 'Destinations', 'backwpup' ); $jobs_columns['next'] = __( 'Next Run', 'backwpup' ); $jobs_columns['last'] = __( 'Last Run', 'backwpup' ); return $jobs_columns; } /** * Gets a list of sortable columns. * * @return array */ public function get_sortable_columns() { return [ 'jobname' => 'jobname', 'type' => 'type', 'dest' => 'dest', 'next' => 'next', 'last' => 'last', ]; } /** * Retrieves the table classes for the job page. * * This method constructs an array of CSS classes to be applied to the table * on the job page. The 'fixed' class is intentionally omitted from the default * classes. * * @return array An array of CSS classes for the table. */ protected function get_table_classes() { // Remove 'fixed' from the default classes. $classes = [ 'widefat', 'striped', $this->_args['plural'] ]; return $classes; } /** * The checkbox column. * * @param int $item Job ID. * * @return string */ public function column_cb( $item ) { return '<input type="checkbox" name="jobs[]" value="' . esc_attr( $item ) . '" />'; } /** * The job name column. * * @param int $item Job ID. * * @return string */ public function column_jobname( $item ) { $job_normal_hide = ''; if ( is_object( $this->job_object ) ) { $job_normal_hide = ' style="display:none;"'; } $r = '<strong title="' . sprintf( /* translators: %d: job ID. */ __( 'Job ID: %d', 'backwpup' ), $item ) . '">' . esc_html( BackWPup_Option::get( $item, 'name' ) ) . '</strong>'; $actions = []; if ( current_user_can( 'backwpup_jobs_edit' ) ) { $actions['edit'] = '<a href="' . wp_nonce_url( network_admin_url( 'admin.php' ) . '?page=backwpupeditjob&jobid=' . $item, 'edit-job' ) . '">' . esc_html__( 'Edit', 'backwpup' ) . '</a>'; $actions['delete'] = '<a class="submitdelete" href="' . wp_nonce_url( network_admin_url( 'admin.php' ) . '?page=backwpupjobs&action=delete&jobs[]=' . $item, 'bulk-jobs' ) . '" onclick="return showNotice.warn();">' . esc_html__( 'Delete', 'backwpup' ) . '</a>'; } if ( current_user_can( 'backwpup_jobs_start' ) ) { $url = BackWPup_Job::get_jobrun_url( 'runnowlink', $item ); $actions['runnow'] = '<a href="' . esc_attr( $url['url'] ) . '">' . esc_html__( 'Run now', 'backwpup' ) . '</a>'; } if ( current_user_can( 'backwpup_logs' ) && BackWPup_Option::get( $item, 'logfile' ) ) { $logfile = basename( (string) BackWPup_Option::get( $item, 'logfile' ) ); if ( is_object( $this->job_object ) && (int) $this->job_object->job['jobid'] === (int) $item ) { $logfile = basename( (string) $this->job_object->logfile ); } $log_name = str_replace( [ '.html', '.gz' ], '', basename( $logfile ) ); $actions['lastlog'] = '<a href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&log=' . $log_name . '&_ajax_nonce=' . wp_create_nonce( 'view-log_' . $log_name ) . '&TB_iframe=true&width=640&height=440\" title="' . esc_attr( $logfile ) . '" class="thickbox">' . __( 'Last log', 'backwpup' ) . '</a>'; } $actions = wpm_apply_filters_typed( 'array', 'backwpup_page_jobs_actions', $actions, $item, false ); $r .= '<div class="job-normal"' . $job_normal_hide . '>' . $this->row_actions( $actions ) . '</div>'; if ( is_object( $this->job_object ) ) { $actionsrun = []; $actionsrun = wpm_apply_filters_typed( 'array', 'backwpup_page_jobs_actions', $actionsrun, $item, true ); $r .= '<div class="job-run">' . $this->row_actions( $actionsrun ) . '</div>'; } return $r; } /** * The type column. * * @param int $item Job ID. * * @return string */ public function column_type( $item ) { $r = ''; $types = BackWPup_Option::get( $item, 'type' ); if ( $types ) { foreach ( $types as $type ) { if ( isset( $this->job_types[ $type ] ) ) { $r .= $this->job_types[ $type ]->info['name'] . '<br />'; } else { $r .= $type . '<br />'; } } } return $r; } /** * The destination column. * * @param int $item Job ID. * * @return string */ public function column_dest( $item ) { $r = ''; $backup_to = false; foreach ( BackWPup_Option::get( $item, 'type' ) as $typeid ) { if ( isset( $this->job_types[ $typeid ] ) && $this->job_types[ $typeid ]->creates_file() ) { $backup_to = true; break; } } if ( $backup_to ) { foreach ( BackWPup_Option::get( $item, 'destinations' ) as $destid ) { if ( isset( $this->destinations[ $destid ]['info']['name'] ) ) { $r .= $this->destinations[ $destid ]['info']['name'] . '<br />'; } else { $r .= $destid . '<br />'; } } } else { $r .= '<i>' . __( 'Not needed or set', 'backwpup' ) . '</i><br />'; } return $r; } /** * The next column. * * @param int $item Job ID. * * @return string */ public function column_next( $item ) { $r = ''; $job_normal_hide = ''; if ( is_object( $this->job_object ) ) { $job_normal_hide = ' style="display:none;"'; } if ( is_object( $this->job_object ) && $this->job_object->job['jobid'] === $item ) { $current_timestamp = time() + (int) ( (float) get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); $runtime = $current_timestamp - $this->job_object->start_time; $r .= '<div class="job-run">' . sprintf( /* translators: %s: runtime in seconds. */ esc_html__( 'Running for: %s seconds', 'backwpup' ), '<span id="runtime">' . $runtime . '</span>' ) . '</div>'; } if ( is_object( $this->job_object ) && (int) $this->job_object->job['jobid'] === (int) $item ) { $r .= '<div class="job-normal"' . $job_normal_hide . '>'; } if ( 'wpcron' === BackWPup_Option::get( $item, 'activetype' ) ) { $nextrun = wp_next_scheduled( 'backwpup_cron', [ 'arg' => $item ] ) + ( get_option( 'gmt_offset' ) * 3600 ); if ( $nextrun ) { // translators: %s: cron expression. $title = sprintf( esc_html__( 'Cron: %s', 'backwpup' ), BackWPup_Option::get( $item, 'cron' ) ); // translators: %1$s: date, %2$s: time. $content = sprintf( __( '%1$s at %2$s', 'backwpup' ), wp_date( get_option( 'date_format' ), $nextrun ), wp_date( get_option( 'time_format' ), $nextrun ) ); $r .= '<span title="' . $title . '">' . $content . '</span><br />'; } else { $r .= __( 'Not scheduled!', 'backwpup' ) . '<br />'; } } elseif ( 'link' === BackWPup_Option::get( $item, 'activetype' ) ) { $r .= __( 'External link', 'backwpup' ) . '<br />'; } else { $r .= __( 'Inactive', 'backwpup' ); } if ( is_object( $this->job_object ) && (int) $this->job_object->job['jobid'] === (int) $item ) { $r .= '</div>'; } return $r; } /** * The last column. * * @param int $item Job ID. * * @return string */ public function column_last( $item ) { $r = ''; if ( BackWPup_Option::get( $item, 'lastrun' ) ) { $lastrun = BackWPup_Option::get( $item, 'lastrun' ); $r .= sprintf( // translators: %1$s: date, %2$s: time. __( '%1$s at %2$s', 'backwpup' ), wp_date( get_option( 'date_format' ), $lastrun ), wp_date( get_option( 'time_format' ), $lastrun ) ); if ( BackWPup_Option::get( $item, 'lastruntime' ) ) { $r .= '<br />' . sprintf( // translators: %d: seconds. __( 'Runtime: %d seconds', 'backwpup' ), BackWPup_Option::get( $item, 'lastruntime' ) ); } } else { $r .= __( 'not yet', 'backwpup' ); } $r .= '<br /><span class="last-action-links">'; $download_url = BackWPup_Option::get( $item, 'lastbackupdownloadurl' ); if ( current_user_can( 'backwpup_backups_download' ) && ! empty( $download_url ) ) { // If it's not a direct link, but will be run through the downloader, then process differently. if ( strpos( $download_url, 'backwpupbackups' ) === false ) { $r .= '<a href="' . wp_nonce_url( $download_url, 'backwpup_action_nonce' ) . '" title="' . esc_attr( __( 'Download last backup', 'backwpup' ) ) . '">' . esc_html__( 'Download', 'backwpup' ) . '</a> | '; } else { $r .= self::generate_download_link( $download_url ) . ' | '; } } if ( current_user_can( 'backwpup_logs' ) && BackWPup_Option::get( $item, 'logfile' ) ) { $logfile = basename( (string) BackWPup_Option::get( $item, 'logfile' ) ); if ( is_object( $this->job_object ) && (int) $this->job_object->job['jobid'] === (int) $item ) { $logfile = basename( (string) $this->job_object->logfile ); } $log_name = str_replace( [ '.html', '.gz' ], '', basename( $logfile ) ); $r .= '<a class="thickbox" href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&log=' . $log_name . '&_ajax_nonce=' . wp_create_nonce( 'view-log_' . $log_name ) . '&TB_iframe=true&width=640&height=440" title="' . esc_attr( $logfile ) . '">' . esc_html__( 'Log', 'backwpup' ) . '</a>'; } $r .= '</span>'; return $r; } /** * Generates download link from url. * * @param string $download_url Download url. * @return string */ private static function generate_download_link( $download_url ) { $params = []; parse_str( wp_parse_url( $download_url, PHP_URL_QUERY ), $params ); $file = $params['file']; $local_file = untrailingslashit( BackWPup::get_plugin_data( 'TEMP' ) ) . '/' . basename( $params['local_file'] ?? $file ); $jobid = $params['jobid']; $destination = strtoupper( str_replace( 'download', '', $params['action'] ) ); // Construct the link. return sprintf( '<a href="#TB_inline?height=300&width=630&inlineId=tb_download_file" class="backup-download-link thickbox js-backwpup-download-backup" id="backup-download-link" data-jobid="%1$s" data-destination="%2$s" data-file="%3$s" data-local-file="%4$s" data-nonce="%5$s" data-url="%6$s">%7$s</a>', intval( $jobid ), esc_attr( $destination ), esc_attr( $file ), esc_attr( $local_file ), wp_create_nonce( 'backwpup_action_nonce' ), wp_nonce_url( $download_url, 'backwpup_action_nonce' ), __( 'Download', 'backwpup' ) ); } /** * Load listing page. * * @return void */ public static function load() { // Create table. self::$listtable = new self(); if ( empty( self::$listtable->current_action() ) ) { self::ensure_list_nonce(); } switch ( self::$listtable->current_action() ) { case 'delete': // Delete job. if ( ! current_user_can( 'backwpup_jobs_edit' ) ) { break; } $jobs = filter_input( INPUT_GET, 'jobs', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); if ( ! empty( $jobs ) ) { check_admin_referer( 'bulk-jobs' ); foreach ( array_map( 'absint', $jobs ) as $jobid ) { wp_clear_scheduled_hook( 'backwpup_cron', [ 'arg' => (int) $jobid ] ); BackWPup_Option::delete_job( $jobid ); } } break; case 'copy': // Copy job. if ( ! current_user_can( 'backwpup_jobs_edit' ) ) { break; } $old_job_id = absint( filter_input( INPUT_GET, 'jobid', FILTER_SANITIZE_NUMBER_INT ) ); if ( $old_job_id < 1 ) { break; } check_admin_referer( 'copy-job_' . $old_job_id ); // Create new. $newjobid = BackWPup_Option::get_job_ids(); sort( $newjobid ); $newjobid = end( $newjobid ) + 1; $old_options = BackWPup_Option::get_job( $old_job_id ); foreach ( $old_options as $key => $option ) { if ( 'jobid' === $key ) { $option = $newjobid; } if ( 'name' === $key ) { $option = __( 'Copy of', 'backwpup' ) . ' ' . $option; } if ( 'activetype' === $key ) { $option = ''; } if ( 'archivename' === $key ) { $option = str_replace( $old_job_id, $newjobid, (string) $option ); } if ( 'logfile' === $key || 'lastbackupdownloadurl' === $key || 'lastruntime' === $key || 'lastrun' === $key ) { continue; } BackWPup_Option::update( $newjobid, $key, $option ); } break; case 'runnow': $jobid = absint( filter_input( INPUT_GET, 'jobid', FILTER_SANITIZE_NUMBER_INT ) ); if ( $jobid ) { if ( ! current_user_can( 'backwpup_jobs_start' ) ) { wp_die( esc_html__( 'Sorry, you don\'t have permissions to do that.', 'backwpup' ) ); } check_admin_referer( 'backwpup_job_run-runnowlink' ); // Check temp folder. $temp_folder_message = BackWPup_File::check_folder( BackWPup::get_plugin_data( 'TEMP' ), true ); BackWPup_Admin::message( $temp_folder_message, true ); // Check log folder. $log_folder = get_site_option( 'backwpup_cfg_logfolder' ); $log_folder = BackWPup_File::get_absolute_path( $log_folder ); $log_folder_message = BackWPup_File::check_folder( $log_folder ); BackWPup_Admin::message( $log_folder_message, true ); // Check backup destinations. $job_types = BackWPup::get_job_types(); $job_conf_types = BackWPup_Option::get( $jobid, 'type' ); $creates_file = false; foreach ( $job_types as $id => $job_type_class ) { if ( in_array( $id, $job_conf_types, true ) && $job_type_class->creates_file() ) { $creates_file = true; break; } } if ( $creates_file ) { $job_conf_dests = BackWPup_Option::get( $jobid, 'destinations' ); $destinations = 0; foreach ( BackWPup::get_registered_destinations() as $id => $dest ) { if ( ! in_array( $id, $job_conf_dests, true ) || empty( $dest['class'] ) ) { continue; } /* @var BackWPup_Destinations $dest_class */ $dest_class = BackWPup::get_destination( $id ); $job_settings = BackWPup_Option::get_job( $jobid ); if ( ! $dest_class->can_run( $job_settings, false ) ) { BackWPup_Admin::message( sprintf( /* translators: 1: job name, 2: destination name. */ __( 'The job "%1$s" destination "%2$s" is not configured properly', 'backwpup' ), esc_attr( BackWPup_Option::get( $jobid, 'name' ) ), $id ), true ); } ++$destinations; } if ( $destinations < 1 ) { BackWPup_Admin::message( sprintf( /* translators: %s: job name. */ __( 'The job "%s" needs properly configured destinations to run!', 'backwpup' ), esc_attr( BackWPup_Option::get( $jobid, 'name' ) ) ), true ); } } // Only start job if messages empty. $log_messages = BackWPup_Admin::get_messages(); if ( empty( $log_messages ) ) { $old_log_file = BackWPup_Option::get( $jobid, 'logfile' ); BackWPup_Job::get_jobrun_url( 'runnow', $jobid ); usleep( 250000 ); // Wait a quarter second. $new_log_file = BackWPup_Option::get( $jobid, 'logfile', null, false ); // Sleep as long as job not started. $i = 0; while ( $old_log_file === $new_log_file ) { usleep( 250000 ); // Wait a quarter second for next try. $new_log_file = BackWPup_Option::get( $jobid, 'logfile', null, false ); // Wait maximal 10 sec. if ( $i >= 40 ) { BackWPup_Admin::message( sprintf( /* translators: 1: Job name, 2: Information URL */ __( 'Job "%1$s" has started, but not responded for 10 seconds. Please check <a href="%2$s">information</a>.', 'backwpup' ), esc_attr( BackWPup_Option::get( $jobid, 'name' ) ), network_admin_url( 'admin.php' ) . '?page=backwpupsettings#backwpup-tab-information' ), true ); break 2; } ++$i; } BackWPup_Admin::message( sprintf( /* translators: %s: Job name */ __( 'Job "%s" started.', 'backwpup' ), esc_attr( BackWPup_Option::get( $jobid, 'name' ) ) ) ); } } break; case 'abort': // Abort job. if ( ! current_user_can( 'backwpup_jobs_start' ) ) { break; } check_admin_referer( 'abort-job' ); if ( ! file_exists( BackWPup::get_plugin_data( 'running_file' ) ) ) { break; } // Abort. BackWPup_Job::user_abort(); BackWPup_Admin::message( __( 'Job will be terminated.', 'backwpup' ) ); break; default: do_action( 'backwpup_page_jobs_load', self::$listtable->current_action() ); break; } self::$listtable->prepare_items(); } /** * Print admin styles * * @return void */ public static function admin_print_styles() { ?> <style type="text/css" media="screen"> .column-last, .column-next, .column-type, .column-dest { width: 15%; } #TB_ajaxContent { background-color: black; color: #c0c0c0; } #showworking { white-space:nowrap; display: block; width: 100%; font-family:monospace; font-size:12px; line-height:15px; } #runningjob { padding:10px; position:relative; margin: 15px 0 25px 0; padding-bottom:25px; } h2#runnigtitle { margin-bottom: 15px; padding: 0; } #warningsid, #errorid { margin-right: 10px; } .infobuttons { position: absolute; right: 10px; bottom: 0; } .progressbar { margin-top: 20px; height: auto; background: #f6f6f6 url('<?php echo esc_url( BackWPup::get_plugin_data( 'URL' ) ); ?>/assets/images/progressbarhg.jpg'); } #lastmsg, #onstep, #lasterrormsg { text-align: center; margin-bottom: 20px; } #backwpup-page #lastmsg, #backwpup-page #onstep, #backwpup-page #lasterrormsg { font-family: "Open Sans", sans-serif; } .bwpu-progress { background-color: #1d94cf; color: #fff; padding: 5px 0; text-align: center; } #progresssteps { background-color: #007fb6; } .row-actions .lastlog { display: none; } @media screen and (max-width: 782px) { .column-type, .column-dest { display: none; } .row-actions .lastlog { display: inline-block; } .last-action-links { display: none; } } </style> <?php } /** * Print admin scripts. * * @return void */ public static function admin_print_scripts() { wp_enqueue_script( 'backwpupgeneral' ); $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; $plugin_url = BackWPup::get_plugin_data( 'url' ); $plugin_dir = BackWPup::get_plugin_data( 'plugindir' ); $plugin_scripts_url = "{$plugin_url}/assets/js"; $plugin_scripts_dir = "{$plugin_dir}/assets/js"; $shared_scripts_path = "{$plugin_url}/vendor/inpsyde/backwpup-shared/resources/js"; $shared_scripts_dir = "{$plugin_dir}/vendor/inpsyde/backwpup-shared/resources/js"; wp_register_script( 'backwpup_functions', "{$shared_scripts_path}/functions{$suffix}.js", [ 'underscore', 'jquery' ], BackWPup::get_plugin_data( 'Version' ), true ); wp_register_script( 'backwpup_states', "{$shared_scripts_path}/states{$suffix}.js", [ 'backwpup_functions', ], BackWPup::get_plugin_data( 'Version' ), true ); $dependencies = [ 'jquery', 'underscore', 'backwpupgeneral', 'backwpup_functions', 'backwpup_states', ]; if ( \BackWPup::is_pro() ) { $dependencies[] = 'decrypter'; } wp_enqueue_script( 'backwpup-backup-downloader', "{$plugin_scripts_url}/backup-downloader{$suffix}.js", $dependencies, BackWPup::get_plugin_data( 'Version' ), true ); if ( \BackWPup::is_pro() ) { self::admin_print_pro_scripts( $suffix, $plugin_url, $plugin_dir ); } } /** * Print admin pro scripts. * * @param string $suffix Script suffix. * @param string $plugin_url Plugin url. * @param string $plugin_dir Plugin Directory. * * @return void */ private static function admin_print_pro_scripts( $suffix, $plugin_url, $plugin_dir ) { $restore_scripts_path = "{$plugin_url}/vendor/inpsyde/backwpup-restore-shared/resources/js"; $restore_scripts_dir = "{$plugin_dir}/vendor/inpsyde/backwpup-restore-shared/resources/js"; wp_register_script( 'decrypter', "{$restore_scripts_path}/decrypter{$suffix}.js", [ 'underscore', 'jquery', 'backwpup_states', 'backwpup_functions', ], BackWPup::get_plugin_data( 'Version' ), true ); } /** * Admin page assigned to admin menu item. * * @return void */ public static function page() { echo '<div class="wrap" id="backwpup-page">'; // translators: %s: plugin name. echo '<h1>' . esc_html( sprintf( __( '%s › Legacy Jobs', 'backwpup' ), BackWPup::get_plugin_data( 'name' ) ) ) . '</h1>'; BackWPup_Admin::display_messages(); $job_object = BackWPup_Job::get_working_data(); if ( current_user_can( 'backwpup_jobs_start' ) && is_object( $job_object ) ) { // Read existing logfile. $filesystem = backwpup_wpfilesystem(); $logfiledata = $filesystem->get_contents( $job_object->logfile ); preg_match( '/<body[^>]*>/si', $logfiledata, $match ); if ( ! empty( $match[0] ) ) { $startpos = strpos( $logfiledata, $match[0] ) + strlen( $match[0] ); } else { $startpos = 0; } $endpos = stripos( $logfiledata, '</body>' ); if ( empty( $endpos ) ) { $endpos = strlen( $logfiledata ); } $length = strlen( $logfiledata ) - ( strlen( $logfiledata ) - $endpos ) - $startpos; ?> <div id="runningjob"> <div id="runniginfos"> <?php // translators: %s: job name. ?> <h2 id="runningtitle"><?php esc_html( sprintf( __( 'Job currently running: %s', 'backwpup' ), $job_object->job['name'] ) ); ?></h2> <span id="warningsid"><?php esc_html_e( 'Warnings:', 'backwpup' ); ?> <span id="warnings"><?php echo absint( $job_object->warnings ); ?></span></span> <span id="errorid"><?php esc_html_e( 'Errors:', 'backwpup' ); ?> <span id="errors"><?php echo absint( $job_object->errors ); ?></span></span> <div class="infobuttons"><a href="#TB_inline?height=440&width=630&inlineId=tb-showworking" id="showworkingbutton" class="thickbox button button-primary button-primary-bwp" title="<?php esc_attr_e( 'Log of running job', 'backwpup' ); ?>"><?php esc_html_e( 'Display working log', 'backwpup' ); ?></a> <a href="<?php echo esc_url( wp_nonce_url( network_admin_url( 'admin.php' ) . '?page=backwpupjobs&action=abort', 'abort-job' ) ); ?>" id="abortbutton" class="backwpup-fancybox button button-bwp"><?php esc_html_e( 'Abort', 'backwpup' ); ?></a> <a href="#" id="showworkingclose" title="<?php esc_attr_e( 'Close working screen', 'backwpup' ); ?>" class="button button-bwp" style="display:none" ><?php esc_html_e( 'Close', 'backwpup' ); ?></a></div> </div> <input type="hidden" name="logpos" id="logpos" value="<?php echo esc_attr( strlen( $logfiledata ) ); ?>"> <div id="lasterrormsg"></div> <div class="progressbar"><div id="progressstep" class="bwpu-progress" style="width:<?php echo esc_attr( (int) $job_object->step_percent ); ?>%;"><?php echo esc_html( $job_object->step_percent ); ?>%</div></div> <div id="onstep"><?php echo esc_html( $job_object->steps_data[ $job_object->step_working ]['NAME'] ); ?></div> <div class="progressbar"><div id="progresssteps" class="bwpu-progress" style="width:<?php echo esc_attr( (int) $job_object->substep_percent ); ?>%;"><?php echo esc_html( $job_object->substep_percent ); ?>%</div></div> <div id="lastmsg"><?php echo esc_html( $job_object->lastmsg ); ?></div> <div id="tb-showworking" style="display:none;"> <div id="showworking"><?php echo wp_kses_post( self::render_log_content( substr( $logfiledata, $startpos, $length ) ) ); ?></div> </div> </div> <?php } // Display jobs table. ?> <form id="posts-filter" action="" method="get"> <input type="hidden" name="page" value="backwpupjobs" /> <?php wp_nonce_field( self::LIST_NONCE_ACTION, '_wpnonce', false, false ); ?> <?php wp_nonce_field( 'backwpup_ajax_nonce', 'backwpupajaxnonce', false ); self::$listtable->display(); ?> <div id="ajax-response"></div> </form> </div> <div id="tb_download_file" style="display: none;"> <div id="tb_container"> <p id="download-file-waiting"> <?php esc_html_e( 'Please wait …', 'backwpup' ); ?> </p> <p id="download-file-success" style="display: none;"> <?php esc_html_e( 'Your download has been generated. It should begin downloading momentarily.', 'backwpup' ); ?> </p> <div class="progressbar" style="display: none;"> <div id="progresssteps" class="bwpu-progress" style="width:0%;">0%</div> </div> <?php if ( \BackWPup::is_pro() ) { $view = new ViewLoader(); $view->decrypt_key_input(); } ?> </div> </div> <?php if ( ! empty( $job_object->logfile ) ) { ?> <script type="text/javascript"> //<![CDATA[. jQuery(document).ready(function ($) { backwpup_show_working = function () { var save_log_pos = 0; $.ajax({ type: 'GET', url: ajaxurl, cache: false, data:{ action: 'backwpup_working', logpos: $('#logpos').val(), logfile: '<?php echo esc_js( basename( (string) $job_object->logfile ) ); ?>', _ajax_nonce: '<?php echo esc_js( wp_create_nonce( 'backwpupworking_ajax_nonce' ) ); ?>' }, dataType: 'json', success:function (rundata) { if ( rundata == 0 ) { $("#abortbutton").remove(); $("#backwpup-adminbar-running").remove(); $(".job-run").hide(); $("#message").hide(); $(".job-normal").show(); $('#showworkingclose').show(); } if (0 < rundata.log_pos) { $('#logpos').val(rundata.log_pos); } if ('' != rundata.log_text) { $('#showworking').append(rundata.log_text); $('#TB_ajaxContent').scrollTop(rundata.log_pos * 15); } if (0 < rundata.error_count) { $('#errors').replaceWith('<span id="errors">' + rundata.error_count + '</span>'); } if (0 < rundata.warning_count) { $('#warnings').replaceWith('<span id="warnings">' + rundata.warning_count + '</span>'); } if (0 < rundata.step_percent) { $('#progressstep').replaceWith('<div id="progressstep" class="bwpu-progress">' + rundata.step_percent + '%</div>'); $('#progressstep').css('width', parseFloat(rundata.step_percent) + '%'); } if (0 < rundata.sub_step_percent) { $('#progresssteps').replaceWith('<div id="progresssteps" class="bwpu-progress">' + rundata.sub_step_percent + '%</div>'); $('#progresssteps').css('width', parseFloat(rundata.sub_step_percent) + '%'); } if (0 < rundata.running_time) { $('#runtime').replaceWith('<span id="runtime">' + rundata.running_time + '</span>'); } if ( '' != rundata.onstep ) { $('#onstep').replaceWith('<div id="onstep">' + rundata.on_step + '</div>'); } if ( '' != rundata.last_msg ) { $('#lastmsg').replaceWith('<div id="lastmsg">' + rundata.last_msg + '</div>'); } if ( '' != rundata.last_error_msg ) { $('#lasterrormsg').replaceWith('<div id="lasterrormsg">' + rundata.last_error_msg + '</div>'); } if ( rundata.job_done == 1 ) { $("#abortbutton").remove(); $("#backwpup-adminbar-running").remove(); $(".job-run").hide(); $("#message").hide(); $(".job-normal").show(); $('#showworkingclose').show(); } else { if ( rundata.restart_url !== '' ) { backwpup_trigger_cron( rundata.restart_url ); } setTimeout('backwpup_show_working()', 750); } }, error:function( ) { setTimeout('backwpup_show_working()', 750); } }); }; backwpup_trigger_cron = function ( cron_url ) { $.ajax({ type: 'POST', url: cron_url, dataType: 'text', cache: false, processData: false, timeout: 1 }); }; backwpup_show_working(); $('#showworkingclose').on('click', function() { $("#runningjob").hide( 'slow' ); return false; }); }); //]]>. </script> <?php } } /** * Function to generate json data. * * @throws Exception To check capability and nonce verification. */ public static function ajax_working() { $allowed_caps = [ 'backwpup_jobs', 'backwpup_jobs_start', 'backwpup_backups', 'manage_options', // admins fallback. ]; // Check if the user has at least one of the listed capabilities. $can_access = array_reduce( $allowed_caps, fn( $carry, $cap ) => $carry || current_user_can( $cap ), false ); if ( ! $can_access ) { http_response_code( 403 ); echo wp_json_encode( [ 'success' => false, 'data' => [ 'message' => __( 'You do not have sufficient permissions to access this function.', 'backwpup' ), 'job_done' => 1, ], ] ); throw new Exception( 'ajax_exit' ); } // Nonce verification. if ( ! check_ajax_referer( 'backwpupworking_ajax_nonce', '_ajax_nonce', false ) ) { http_response_code( 401 ); echo wp_json_encode( [ 'success' => false, 'data' => [ 'message' => __( 'Security check failed. Please refresh the page and try again.', 'backwpup' ), 'job_done' => 1, ], ] ); throw new Exception( 'ajax_exit' ); } $log_folder = get_site_option( 'backwpup_cfg_logfolder' ); $log_folder = BackWPup_File::get_absolute_path( $log_folder ); $job_object = BackWPup_Job::get_working_data(); $logfile = basename( (string) $job_object->logfile ); try { $logfile_param = filter_input( INPUT_GET, 'logfile', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); $logfile_param = $logfile_param ? sanitize_text_field( $logfile_param ) : $logfile; $logfile = self::get_logfile_path( $log_folder, $logfile_param ); } catch ( \InvalidArgumentException $e ) { // Logfile either not passed or is invalid. echo 'error'; exit( 0 ); } $logpos = absint( filter_input( INPUT_GET, 'logpos', FILTER_SANITIZE_NUMBER_INT ) ); $restart_url = ''; // Check if logfile renamed. if ( file_exists( $logfile . '.gz' ) ) { $logfile .= '.gz'; } if ( ! is_readable( $logfile ) ) { exit( '0' ); } $job_object = BackWPup_Job::get_working_data(); $done = 0; if ( is_object( $job_object ) ) { $warnings = $job_object->warnings; $errors = $job_object->errors; $step_percent = $job_object->step_percent; $substep_percent = $job_object->substep_percent; $runtime = current_time( 'timestamp' ) - $job_object->start_time; // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested $onstep = $job_object->steps_data[ $job_object->step_working ]['NAME']; $lastmsg = $job_object->lastmsg; $lasterrormsg = $job_object->lasterrormsg; $step_done = count( $job_object->steps_done ); $step_todo = count( $job_object->steps_todo ); $substeps_todo = $job_object->substeps_todo; $substeps_done = $job_object->substeps_done; } else { $logheader = BackWPup_Job::read_logheader( $logfile ); $warnings = $logheader['warnings']; $runtime = $logheader['runtime']; $errors = $logheader['errors']; $step_percent = 100; $substep_percent = 100; $step_done = 100; $step_todo = 100; $substeps_todo = 100; $substeps_done = 100; $onstep = esc_html__( 'Job completed', 'backwpup' ); if ( $errors > 0 ) { // Translators: %s is duration in seconds. $lastmsg = '<div class="bwu-message-error"><p>' . esc_html__( 'ERROR:', 'backwpup' ) . ' ' . sprintf( esc_html__( 'Job has ended with errors in %s seconds. You must resolve the errors for correct execution.', 'backwpup' ), $logheader['runtime'] ) . '</p></div>'; } elseif ( $warnings > 0 ) { // Translators: %s is duration in seconds. $lastmsg = '<div class="backwpup-message backwpup-warning"><p>' . esc_html__( 'WARNING:', 'backwpup' ) . ' ' . sprintf( esc_html__( 'backup created with warnings in %s seconds. Please resolve them for correct execution.', 'backwpup' ), $logheader['runtime'] ) . '</p></div>'; } else { // Translators: %s is duration in seconds. $lastmsg = sprintf( esc_html__( 'Backup created in %s seconds.', 'backwpup' ), $logheader['runtime'] ); } $lasterrormsg = ''; $done = 1; } $filesystem = backwpup_wpfilesystem(); if ( '.gz' === substr( $logfile, -3 ) ) { $logfiledata = $filesystem->get_contents( 'compress.zlib://' . $logfile ); } else { $logfiledata = $filesystem->get_contents( $logfile ); } if ( $logpos > 0 ) { $logfiledata = substr( $logfiledata, $logpos ); } preg_match( '/<body[^>]*>/si', $logfiledata, $match ); if ( ! empty( $match[0] ) ) { $startpos = strpos( $logfiledata, $match[0] ) + strlen( $match[0] ); } else { $startpos = 0; } $endpos = stripos( $logfiledata, '</body>' ); if ( false === $endpos ) { $endpos = strlen( $logfiledata ); } $length = strlen( $logfiledata ) - ( strlen( $logfiledata ) - $endpos ) - $startpos; // Check if restart must done on ALTERNATE_WP_CRON. if ( is_object( $job_object ) && defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { $restart = BackWPup_Job::get_jobrun_url( 'restartalt' ); if ( 0 === $job_object->pid && '' === $job_object->uniqid ) { $restart_url = $restart['url']; } $last_update = microtime( true ) - $job_object->timestamp_last_update; if ( empty( $job_object->pid ) && $last_update > 10 ) { $restart_url = $restart['url']; } } $data_ro_return = [ 'log_pos' => strlen( $logfiledata ) + $logpos, 'log_text' => self::render_log_content( substr( $logfiledata, $startpos, $length ) ), 'warning_count' => $warnings, 'error_count' => $errors, 'running_time' => $runtime, 'step_percent' => $step_percent, 'on_step' => $onstep, 'last_msg' => $lastmsg, 'last_error_msg' => $lasterrormsg, 'sub_step_percent' => $substep_percent, 'restart_url' => $restart_url, 'job_done' => $done, 'step_done' => $step_done, 'step_todo' => $step_todo, 'substeps_todo' => $substeps_todo, 'substeps_done' => $substeps_done, 'job_id' => $job_object->job['jobid'], ]; wp_send_json( $data_ro_return ); } /** * Render log HTML through the shared log renderer when available. * * @param string $content Raw HTML log file fragment. * * @return string */ private static function render_log_content( string $content ): string { $container = wpm_apply_filters_typed( '?object', 'backwpup_container', null ); if ( is_object( $container ) && method_exists( $container, 'has' ) && $container->has( 'log_facade' ) ) { $log_facade = $container->get( 'log_facade' ); if ( is_object( $log_facade ) && method_exists( $log_facade, 'render_html' ) ) { return $log_facade->render_html( $content ); } } $log_facade = new \WPMedia\BackWPup\Log\LogFacade(); return $log_facade->render_html( $content ); } /** * Get log file path. * * @param string $folder Folder Path. * @param string|null $filename Filename. * @return string * * @throws \InvalidArgumentException When empty filename. */ private static function get_logfile_path( string $folder, ?string $filename ): string { if ( ! $filename ) { throw new \InvalidArgumentException( 'Log file cannot be null.' ); } $filename = basename( trim( $filename ) ); if ( preg_match( '/^[a-zA-Z0-9_-]+\.[a-zA-Z0-9]{1,5}$/', $filename ) === 0 || strpos( $filename, 'backwpup_log_' ) === false ) { throw new \InvalidArgumentException( 'Invalidly formatted log filename passed.' ); } return $folder . $filename; } /** * Render extra controls in the table navigation area (above or below the table). * * @param string $which The location of the extra table nav markup: 'top' or 'bottom'. */ protected function extra_tablenav( $which ) { if ( 'top' !== $which ) { // Add the filter only at the top of the table. return; } // Get the current "status" filter from the GET request. $current_status_filter = ''; $nonce = $this->get_list_nonce(); if ( $nonce && wp_verify_nonce( $nonce, self::LIST_NONCE_ACTION ) ) { $current_status_filter = filter_input( INPUT_GET, 'status', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); $current_status_filter = $current_status_filter ? sanitize_text_field( $current_status_filter ) : ''; } ?> <div class="alignleft actions"> <label for="filter-by-status" class="screen-reader-text"> <?php esc_html_e( 'Filter by Status', 'backwpup' ); ?> </label> <select name="status" id="filter-by-status" onchange="this.form.submit();"> <option value=""><?php esc_html_e( 'All Statuses', 'backwpup' ); ?></option> <option value="disabled" <?php selected( $current_status_filter, 'disabled' ); ?>> <?php esc_html_e( 'Disabled', 'backwpup' ); ?> </option> </select> <noscript> <button type="submit" class="button"><?php esc_html_e( 'Filter', 'backwpup' ); ?></button> </noscript> </div> <?php } /** * Ensure the list view has a valid nonce in the URL. * * @return void */ private static function ensure_list_nonce() { $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); if ( null === $nonce && isset( $_GET['_wpnonce'] ) ) { $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ); } else { $nonce = $nonce ? sanitize_text_field( $nonce ) : ''; } if ( $nonce && wp_verify_nonce( $nonce, self::LIST_NONCE_ACTION ) ) { return; } $base_url = is_network_admin() ? network_admin_url( 'admin.php?page=backwpupjobs' ) : admin_url( 'admin.php?page=backwpupjobs' ); $current_url = add_query_arg( $_GET, $base_url ); $current_url = remove_query_arg( [ '_wpnonce', '_wp_http_referer' ], $current_url ); $current_url = add_query_arg( '_wpnonce', wp_create_nonce( self::LIST_NONCE_ACTION ), $current_url ); wp_safe_redirect( $current_url ); exit; } /** * Check if the list nonce is valid. * * @return bool */ private function get_list_nonce() { $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); if ( null === $nonce && isset( $_GET['_wpnonce'] ) ) { $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ); } else { $nonce = $nonce ? sanitize_text_field( $nonce ) : ''; } if ( ! $nonce || ! wp_verify_nonce( $nonce, self::LIST_NONCE_ACTION ) ) { return ''; } return (string) $nonce; } }
[-] class-system-tests-runner.php
[edit]
[-] class-jobtype-dbdump.php
[edit]
[-] class-destination-rsc.php
[edit]
[-] class-encryption.php
[edit]
[-] class-destination-downloader-factory.php
[edit]
[-] class-destination-downloader-interface.php
[edit]
[-] class-destination-ftp-type-ftp.php
[edit]
[-] class-path-fixer.php
[edit]
[-] class-message-box.php
[edit]
[-] class-destination-dropbox-api.php
[edit]
[-] class-option.php
[edit]
[-] class-destination-dropbox-api-request-exception.php
[edit]
[-] class-page-about.php
[edit]
[-] class-migrate.php
[edit]
[-] class-system-requirements.php
[edit]
[-] class-adminbar.php
[edit]
[-] class-msazure-destination-configuration.php
[edit]
[-] class-job.php
[edit]
[-] class-destination-ftp-type-exception.php
[edit]
[-] class-destination-sugarsync-api.php
[edit]
[-] class-download-file-interface.php
[edit]
[-] class-encryption-fallback.php
[edit]
[-] BackWPup.php
[edit]
[-] class-page-backwpup.php
[edit]
[-] class-destination-downloader-data.php
[edit]
[-] class-mysqldump-exception.php
[edit]
[-] class-s3-destination.php
[edit]
[-] class-destination-ftp.php
[edit]
[-] class-cron.php
[edit]
[+]
Notice
[-] class-destination-downloader.php
[edit]
[-] class-destinations.php
[edit]
[-] class-destination-ftp-downloader.php
[edit]
[-] class-destination-dropbox-downloader.php
[edit]
[-] class-download-handler.php
[edit]
[-] class-destination-dropbox.php
[edit]
[-] class-system-tests.php
[edit]
[-] class-destination-folder-downloader.php
[edit]
[-] class-destination-ftp-type.php
[edit]
[-] class-thirdparties.php
[edit]
[-] class-jobtype-wpplugin.php
[edit]
[-] class-directory.php
[edit]
[-] class-recursive-directory.php
[edit]
[-] class-destination-msazure-downloader.php
[edit]
[-] class-destination-connect-interface.php
[edit]
[-] class-install.php
[edit]
[-] class-admin.php
[edit]
[-] class-jobtype-file.php
[edit]
[-] functions.php
[edit]
[+]
Utils
[+]
ThirdParty
[-] class-destination-s3-downloader.php
[edit]
[-] class-destination-rsc-downloader.php
[edit]
[-] class-destination-sugarsync-downloader.php
[edit]
[-] class-destination-email.php
[edit]
[+]
..
[-] class-mysqldump.php
[edit]
[-] class-page-firstbackup.php
[edit]
[-] class-jobtype-wpexp.php
[edit]
[-] class-jobtype-dbcheck.php
[edit]
[-] class-file.php
[edit]
[-] class-sanitize-path.php
[edit]
[+]
Settings
[-] class-destination-s3.php
[edit]
[-] class-page-logs.php
[edit]
[-] class-factory-exception.php
[edit]
[-] class-page-restore.php
[edit]
[+]
dependencies
[-] class-create-archive-exception.php
[edit]
[-] class-page-editjob.php
[edit]
[-] class-page-backups.php
[edit]
[-] class-destination-dropbox-api-exception.php
[edit]
[-] class-create-archive.php
[edit]
[-] class-encryption-openssl.php
[edit]
[-] class-destination-onedrive-config-trait.php
[edit]
[-] class-destination-download-exception.php
[edit]
[-] class-download-file.php
[edit]
[-] class-page-settings.php
[edit]
[-] class-destination-msazure.php
[edit]
[-] class-page-onboarding.php
[edit]
[-] class-destination-folder.php
[edit]
[-] class-jobtypes.php
[edit]
[-] class-destination-connect-exception.php
[edit]
[-] class-destination-sugarsync.php
[edit]
[-] class-page-jobs.php
[edit]
[-] class-destination-sugarsync-api-exception.php
[edit]
[-] class-encryption-mcrypt.php
[edit]