function DBError($file, $line, $friendly = false) { $this->Log_Event(WPONLINEBACKUP_EVENT_ERROR, __('A database operation failed.', 'wponlinebackup') . PHP_EOL . __('Please try reinstalling the plugin - in most cases this will repair the database.', 'wponlinebackup') . PHP_EOL . __('Please contact support if the issue persists, providing the complete event log for the activity. Diagnostic information follows:', 'wponlinebackup') . PHP_EOL . PHP_EOL . 'Failed at: ' . $file . '(' . $line . ')' . PHP_EOL . WPOnlineBackup::Get_WPDB_Last_Error()); if ($friendly === false) { $friendly = __('A database operation failed.', 'wponlinebackup'); } return $friendly; }
function Get_Temp() { return realpath(WPOnlineBackup::Get_Temp_Raw()); }
function Backup_Table() { global $wpdb; // We backup each table and jump back to bootstrap after each table for a forced update // We may improve this to work same as files in future and loop forever in here and decide on our own forced updates while ($this->job['progress'] != 100) { $where = array(); if (count($this->job['primary'])) { // We have a primary or unique key, add an order by clause $extra = ' ORDER BY ' . WPOnlineBackup_Backup_Tables::Implode_Backquote(' ASC, ', $this->job['primary']) . ' ASC'; // Calculate the where clause based on the key if we already have the table information // If we don't have the table information yet, we don't give a WHERE so we can get the first set of rows if (!is_null($this->job['total'])) { $previous = array(); // We search for records with ID higher than the last id. // For multi-column, we check for where the first ID is higher, or the first ID is the same and the second ID is higher, and so on foreach ($this->job['primary'] as $index => $column) { $value = $this->job['last_id'][$index]; // Calls _real_escape if it exists - escape() seems to call _weak_escape() instead $wpdb->escape_by_ref($value); if (count($previous)) { $where[] = '(' . implode(' AND ', $previous) . ' AND `' . $column . '` > \'' . $value . '\')'; } else { $where[] = '`' . $column . '` > \'' . $value . '\''; } $previous[] = '`' . $column . '` = \'' . $value . '\''; } if (count($where) > 1) { $where = array('(' . implode(' OR ', $where) . ')'); } } // When using a key, we don't need a start offset, as we calculate it based on IDs $start = ''; } else { $extra = ''; // No primary or unique key available, so we failback to setting a start offset if (!is_null($this->job['total'])) { $start = $this->job['done'] . ', '; } else { $start = ''; } } if ($is_comments = preg_match($this->multisite_prefix_regex . 'comments$#', $this->job['table'])) { if ($this->WPOnlineBackup->Get_Setting('ignore_spam_comments')) { $where[] = '`comment_approved` <> \'spam\''; } if ($this->WPOnlineBackup->Get_Setting('ignore_trash_comments')) { $where[] = '`comment_approved` <> \'trash\''; } } else { if ($this->job['table'] == $this->db_prefix . 'options') { // Remove this option - it will trigger our tables to be created on restore $where[] = '`option_name` <> \'wponlinebackup_check_tables\''; } } $where = implode(' AND ', $where); if ($where) { $where = ' WHERE ' . $where; } if (is_null($this->job['total'])) { $this->progress['message'] = sprintf(__('Backing up %s...', 'wponlinebackup'), $this->job['table']); $drop = 'DROP TABLE IF EXISTS `' . $this->job['table'] . '`;' . WPONLINEBACKUP_EOL . WPONLINEBACKUP_EOL; // Table information doesn't exist, so let's gather it, first by getting the CREATE TABLE dump $wpdb->query('SET sql_quote_show_create = 1'); $create = $wpdb->get_var('SHOW CREATE TABLE `' . $this->job['table'] . '`', 1); // SHOW CREATE TABLE should always return a row, so 0 rows (null) or error (null) both are considered an error if (is_null($create)) { // Failed to gather table information - report, and skip the table $this->bootstrap->Log_Event(WPONLINEBACKUP_EVENT_ERROR, sprintf(__('Failed to retrieve information for table \'%s\': %s. The table will be skipped.', 'wponlinebackup'), $this->job['table'], WPOnlineBackup::Get_WPDB_Last_Error())); $this->job['progress'] = 100; // Breaking will throw us all the way out back into bootstrap for a forced update that will prevent the event log duplicating break; } // Normalise line-endings $create = preg_replace('/\\r\\n?|\\n/', WPONLINEBACKUP_EOL, $create); $create .= ';' . WPONLINEBACKUP_EOL . WPONLINEBACKUP_EOL; $this->progress['rsize'] += strlen($create); if (($ret = $this->stream->Write_Stream($drop . $create)) !== true) { return $ret; } // Get the total number of rows in the table, so we can provide progress information if required $this->job['total'] = $wpdb->get_var('SELECT COUNT(*) FROM `' . $this->job['table'] . '`' . $where); // SELECT COUNT(*) should always return a row, so 0 rows (null) or error (null) both are considered an error if (is_null($this->job['total'])) { // Failed to gather row count - report, and skip the table $this->bootstrap->Log_Event(WPONLINEBACKUP_EVENT_ERROR, sprintf(__('Failed to retrieve row count for table \'%s\': %s. The table will be skipped.', 'wponlinebackup'), $this->job['table'], WPOnlineBackup::Get_WPDB_Last_Error())); $this->job['progress'] = 100; // Breaking will throw us all the way out back into bootstrap for a forced update that will prevent the event log duplicating break; } $this->bootstrap->Tick(); } $fields = WPOnlineBackup_Backup_Tables::Implode_Backquote(',', $this->job['fields']); // Begin retrieving data if (($result = $this->Query($fields, $this->job['table'], $where, $extra, $start)) === false) { // Failure is logged inside Query() $this->job['progress'] = 100; // Breaking here throws back to bootstrap for a forced update - this will prevent duplicating the event log entries Query() wrote break; } $this->bootstrap->Tick(); // Create a fully escaped insert statement $insert = ''; $row_count = 0; $insert_size = 0; while (false !== ($next_row = $this->Fetch_Row($result))) { $row = $next_row; $values = array(); $row_count++; foreach ($row as $index => $value) { $insert_size += strlen($value); // If we're not the first row and our insert has got too big, write the insert and start another // This prevents our insert getting rediculously big if ($row_count > 1 && $insert_size > $this->max_block_size) { $row_count--; break 2; } if (is_null($value)) { $value = 'NULL'; } else { if (!$this->Requires_Quotes($value)) { } else { // escape_by_ref uses _real_escape - preferred. escape() appears to only use _weak_escape() $wpdb->escape_by_ref($value); $value = '\'' . $value . '\''; } } $values[] = $value; } $insert .= ($row_count == 1 ? 'INSERT INTO `' . $this->job['table'] . '` (' . $fields . ') VALUES' . WPONLINEBACKUP_EOL : ',' . WPONLINEBACKUP_EOL) . '(' . implode(',', $values) . ')'; } unset($values); unset($value); $this->Free_Result($result); // If 0 rows were returned, we reached the end of the dataset // We couldn't use num_rows or anything as we may be an unbuffered query result if ($row_count == 0) { $this->job['progress'] = 100; break; } // Finish the statement $insert .= ';' . WPONLINEBACKUP_EOL . WPONLINEBACKUP_EOL; $this->job['done'] += $row_count; if ($this->job['done'] >= $this->job['total']) { $this->job['progress'] = 99; } else { $this->job['progress'] = floor($this->job['done'] * 99 / $this->job['total']); if ($this->job['progress'] >= 100) { $this->job['progress'] = 99; } } $this->progress['message'] = sprintf(__('Backing up %s; %d of %d rows...', 'wponlinebackup'), $this->job['table'], $this->job['done'], $this->job['total']); // If we are tracking using a key, update the last_id fields if (count($this->job['primary'])) { foreach ($this->job['primary'] as $index => $column) { $this->job['last_id'][$index] = $row[array_search($column, $this->job['fields'])]; } } // Add to the dump $this->progress['rsize'] += strlen($insert); if (($ret = $this->stream->Write_Stream($insert)) !== true) { return $ret; } $this->bootstrap->Tick(); } return true; }
function Print_Events_Table() { global $wpdb; $activity_id = array_key_exists('activity', $_GET) ? strval($_GET['activity']) : 0; $wpdb->escape_by_ref($activity_id); $activity = $wpdb->get_row('SELECT activity_id, start, end, type, media, comp, errors, warnings, compressed, encrypted, ' . 'bsize, bcount, rsize, rcount ' . 'FROM `' . $wpdb->prefix . 'wponlinebackup_activity_log` ' . 'WHERE activity_id = \'' . $activity_id . '\'', ARRAY_A); if (is_null($activity)) { ?> <p style="text-align: center; padding: 12px"><img src="<?php echo WPONLINEBACKUP_URL; ?> /images/error.png" style="width: 16px; height: 16px; vertical-align: middle" alt=""> <i><?php _e('The specified activity no longer exists. There are no events to show.', 'wponlinebackup'); ?> </i></p> <?php return; } ?> <p> <b>Activity ID:</b> <?php echo $activity['activity_id']; if ($activity['type'] == WPONLINEBACKUP_ACTIVITY_BACKUP) { $icon = array('user.png', __('Manual Backup', 'wponlinebackup')); } else { if ($activity['type'] == WPONLINEBACKUP_ACTIVITY_AUTO_BACKUP) { $icon = array('date.png', __('Scheduled Backup', 'wponlinebackup')); } else { if ($activity['type'] == WPONLINEBACKUP_ACTIVITY_DECRYPT) { $icon = array('key.png', __('Decrypt', 'wponlinebackup')); } else { $icon = array('help.png', __('Unknown', 'wponlinebackup')); } } } if (!is_null($icon)) { ?> <br> <b>Activity Type:</b> <img src="<?php echo WPONLINEBACKUP_URL; ?> /images/<?php echo $icon[0]; ?> " style="width: 16px; height: 16px; vertical-align: middle"> <?php echo $icon[1]; } $settings = array(); switch ($activity['media']) { case WPONLINEBACKUP_MEDIA_DOWNLOAD: $settings[] = array('cd.png', __('Local', 'wponlinebackup')); break; case WPONLINEBACKUP_MEDIA_EMAIL: $settings[] = array('email.png', __('Emailed', 'wponlinebackup')); break; case WPONLINEBACKUP_MEDIA_ONLINE: $settings[] = array('transmit.png', __('Sent to Online Vault', 'wponlinebackup')); break; } if ($activity['compressed']) { $settings[] = array('compress.png', __('Compressed', 'wponlinebackup')); } if ($activity['encrypted']) { $settings[] = array('lock_small.png', __('Encrypted', 'wponlinebackup')); } if (count($settings)) { ?> <br> <b>Settings:</b> <?php end($settings); $last = key($settings); foreach ($settings as $key => $icon) { ?> <img src="<?php echo WPONLINEBACKUP_URL; ?> /images/<?php echo $icon[0]; ?> " style="width: 16px; height: 16px; vertical-align: middle"> <?php echo $icon[1]; if ($key != $last) { ?> , <?php } } } ?> </p> <p> <b>Completion:</b> <?php switch ($activity['comp']) { // case WPONLINEBACKUP_COMP_UNEXPECTED: default: $message = array('exclamation.png', 'A00', __('Unexpected stop', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_RUNNING: $message = array('ajax-loader.gif', '000', __('Running...', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_SUCCESSFUL: $message = array('accept.png', '0A0', $activity['warnings'] ? sprintf(_n('Successful (%d warning)', 'Successful (%d warnings)', $activity['warnings'], 'wponlinebackup'), $activity['warnings']) : __('Successful', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_PARTIAL: $message = array('error.png', 'A80', $activity['errors'] ? sprintf(_n('Partial (%d error)', 'Partial (%d errors)', $activity['errors'], 'wponlinebackup'), $activity['errors']) : __('Partial', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_STOPPED: $message = array('exclamation.png', 'A00', __('Stopped', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_FAILED: case WPONLINEBACKUP_COMP_TIMEOUT: case WPONLINEBACKUP_COMP_SLOWTIMEOUT: $message = array('exclamation.png', 'A00', __('Failed', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_MEMORY: case WPONLINEBACKUP_COMP_SLOWMEMORY: $message = array('exclamation.png', 'A00', __('Low Memory', 'wponlinebackup')); break; case WPONLINEBACKUP_COMP_MAINTENANCE: $message = array('exclamation.png', 'A00', __('Maintenance', 'wponlinebackup')); break; } ?> <img src="<?php echo WPONLINEBACKUP_URL; ?> /images/<?php echo $message[0]; ?> " style="width: 16px; height: 16px; vertical-align: middle" alt=""> <b style="color: #<?php echo $message[1]; ?> "><?php echo $message[2]; ?> </b> </p> <p> <b>Backup Size:</b> <?php printf(_n('%s (%d file)', '%s (%d files)', $activity['bcount'], 'wponlinebackup'), WPOnlineBackup_Formatting::Fix_B($activity['bsize']), $activity['bcount']); ?> <br> <b>Total Size:</b> <?php printf(_n('%s (%d file)', '%s (%d files)', $activity['rcount'], 'wponlinebackup'), WPOnlineBackup_Formatting::Fix_B($activity['rsize']), $activity['rcount']); ?> </p> <p> <b>Start Time:</b> <?php echo htmlentities(date_i18n(_x('jS M Y g.i.s A', 'Event log activity start time', 'wponlinebackup'), WPOnlineBackup::Convert_Unixtime_To_Wordpress_Unixtime($activity['start'])), ENT_QUOTES, 'UTF-8'); ?> <br> <b>End Time:</b> <?php if (is_null($activity['end'])) { ?> <i><?php echo __('N/A', 'wponlinebackup'); ?> </i><?php } else { echo htmlentities(date_i18n(_x('jS M Y g.i.s A', 'Event log activity end time', 'wponlinebackup'), WPOnlineBackup::Convert_Unixtime_To_Wordpress_Unixtime($activity['end'])), ENT_QUOTES, 'UTF-8'); } ?> </p> <table class="widefat" cellspacing="0"> <thead> <tr> <th width="15%" scope="col" id="time" class="manage-column column-time" style=""><?php echo __('Time', 'wponlinebackup'); ?> </th> <th width="12%" scope="col" id="type" class="manage-column column-type" style=""><?php echo __('Type', 'wponlinebackup'); ?> </th> <th scope="col" id="event" class="manage-column column-event" style=""><?php echo __('Event', 'wponlinebackup'); ?> </th> </tr> </thead> <tfoot> <tr> <th width="15%" scope="col" class="manage-column column-time" style=""><?php echo __('Time', 'wponlinebackup'); ?> </th> <th width="12%" scope="col" class="manage-column column-type" style=""><?php echo __('Type', 'wponlinebackup'); ?> </th> <th scope="col" class="manage-column column-event" style=""><?php echo __('Event', 'wponlinebackup'); ?> </th> </tr> </tfoot> <tbody> <?php $result = $wpdb->get_results('SELECT time, type, event ' . 'FROM `' . $wpdb->prefix . 'wponlinebackup_event_log` ' . 'WHERE activity_id = \'' . $activity_id . '\' ' . 'ORDER BY time DESC, event_id DESC', ARRAY_A); // Display the event logs, or an empty message if (count($result) == 0) { ?> <tr> <td colspan="8" style="text-align: center; padding: 12px"><img src="<?php echo WPONLINEBACKUP_URL; ?> /images/information.png" style="width: 16px; height: 16px; vertical-align: middle" alt=""> <i><?php _e('The Event Log for this activity is currently empty.', 'wponlinebackup'); ?> </i></td> </tr> <?php } else { $c = 0; foreach ($result as $event) { ?> <tr<?php if ($c++ % 2 == 0) { ?> class="alternate"<?php } ?> valign="top"> <td class="column-time"><?php echo htmlentities(date_i18n(_x('jS M Y g.i.s A', 'Event log entry time', 'wponlinebackup'), WPOnlineBackup::Convert_Unixtime_To_Wordpress_Unixtime($event['time'])), ENT_QUOTES, 'UTF-8'); ?> </td> <td class="column-type"><?php switch ($event['type']) { // case WPONLINEBACKUP_EVENT_INFORMATION: default: $type = array('information.png', __('Information', 'wponlinebackup')); break; case WPONLINEBACKUP_EVENT_WARNING: $type = array('error.png', __('Warning', 'wponlinebackup')); break; case WPONLINEBACKUP_EVENT_ERROR: $type = array('exclamation.png', __('Error', 'wponlinebackup')); break; } ?> <img src="<?php echo WPONLINEBACKUP_URL; ?> /images/<?php echo $type[0]; ?> " style="width: 16px; height: 16px; vertical-align: middle" alt=""> <?php echo htmlentities($type[1], ENT_QUOTES); ?> </td> <td class="column-event"><?php echo preg_replace('/(?:\\n|\\r\\n?)/', '<br>' . PHP_EOL, htmlentities($event['event'], ENT_QUOTES)); ?> </td> </tr> <?php } } ?> </tbody> </table> <?php }