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 Initialise_Backup(&$bootstrap, &$progress, &$next_step)
 {
     global $wpdb;
     // First of all, clean up everything from last backup
     if ($progress['initialise'] < ++$next_step) {
         $this->CleanUp();
         $progress['initialise'] = $next_step;
         $bootstrap->Tick();
     }
     // First of all, clear back activity logs
     if ($progress['initialise'] < ++$next_step) {
         do {
             if (($ret = $wpdb->query('DELETE a, e FROM `' . $this->db_prefix . 'wponlinebackup_activity_log` a ' . 'LEFT JOIN `' . $this->db_prefix . 'wponlinebackup_event_log` e ON (e.activity_id = a.activity_id) ' . 'WHERE a.start < ' . strtotime('-' . $this->WPOnlineBackup->Get_Setting('max_log_age') . ' months', $progress['start_time']))) === false) {
                 return $bootstrap->DBError(__LINE__, __FILE__);
             }
             // Before the Tick so we skip completely if we're done
             if (!$ret) {
                 $progress['initialise'] = $next_step;
             }
             $bootstrap->Tick();
         } while ($ret);
     }
     if ($progress['initialise'] < ++$next_step) {
         // If online, add a synchronisation job
         if ($progress['config']['target'] == 'online') {
             $progress['jobs'][] = array('processor' => 'transmission', 'progress' => 0, 'progresslen' => 5, 'retries' => 0, 'action' => 'synchronise', 'total_items' => 0, 'total_generations' => 0, 'done_items' => 0, 'done_generations' => 0);
         }
         $progress['initialise'] = $next_step;
         $bootstrap->Tick();
     }
     if ($progress['initialise'] < ++$next_step) {
         // Are we backing up the database?
         if ($progress['config']['backup_database']) {
             require_once WPONLINEBACKUP_PATH . '/include/tables.php';
             $tables = new WPOnlineBackup_Backup_Tables($this->WPOnlineBackup, $this->db_force_master);
             // Initialise - pass ourself so we can log events, and also pass the progress and its tracker
             if (true !== ($ret = $tables->Initialise($this, $progress))) {
                 return $ret;
             }
         }
         $progress['initialise'] = $next_step;
         $bootstrap->Tick();
     }
     if ($progress['initialise'] < ++$next_step) {
         // Are we backing up the filesystem?
         if ($progress['config']['backup_filesystem']) {
             require_once WPONLINEBACKUP_PATH . '/include/files.php';
             $files = new WPOnlineBackup_Backup_Files($this->WPOnlineBackup, $this->db_force_master);
             // Initialise - pass ourselves so we can log events, and also pass the progress and its tracker
             if (true !== ($ret = $files->Initialise($this, $progress))) {
                 return $ret;
             }
         }
         $progress['initialise'] = $next_step;
         $bootstrap->Tick();
     }
     if ($progress['initialise'] < ++$next_step) {
         // Reconstruct the data files
         $progress['jobs'][] = array('processor' => 'reconstruct', 'progress' => 0, 'progresslen' => 5);
         if ($progress['config']['target'] == 'online') {
             // Online needs to transmit
             $progress['jobs'][] = array('processor' => 'transmission', 'progress' => 0, 'progresslen' => 10, 'retries' => 0, 'action' => 'transmit', 'total' => 0, 'done' => 0, 'done_retention' => 0, 'retention_size' => 0, 'new_bsn' => 0, 'wait' => false);
         } else {
             if ($progress['config']['target'] == 'email') {
                 // Email needs to email
                 $progress['jobs'][] = array('processor' => 'email', 'progress' => 0, 'progresslen' => 10, 'retries' => 0);
             }
         }
         // Add the cleanups to the end of the job list so they happen only after the main backup jobs have finished
         $progress['jobs'] = array_merge($progress['jobs'], $progress['cleanups']);
         $progress['cleanups'] = array();
         // Add on the file cleanup - this places local backups in their correct place and deletes files for online backup etc.
         $progress['jobs'][] = array('processor' => 'cleanupfiles', 'progress' => 0, 'progresslen' => 5);
         // Retention for local backups should be done AFTER cleanupfiles, since cleanupfiles adds to the database the current backup and retention should take that into account
         if ($progress['config']['target'] == 'download') {
             // Local needs retention
             $progress['jobs'][] = array('processor' => 'localretention', 'progress' => 0, 'progresslen' => 5, 'deleted_gens' => 0, 'deleted_storage' => 0, 'delete_error' => 0);
         }
         // Total up the jobcount as total of all progresslens - makes calculating progress % easier
         foreach ($progress['jobs'] as $job) {
             $progress['jobcount'] += $job['progresslen'];
         }
         $progress['initialise'] = $next_step;
         $bootstrap->Tick();
     }
     if ($progress['initialise'] < ++$next_step) {
         if ($progress['config']['target'] == 'download') {
             // Create the local backup directory
             if (true !== ($ret = $bootstrap->Create_Dir_Local_Backup())) {
                 return $ret;
             }
         }
         // Try to create the temporary backup directory
         if (true !== ($ret = $bootstrap->Create_Dir_Temporary())) {
             return $ret;
         }
         $progress['initialise'] = $next_step;
         // Force a save here since we did some file operation checks and it'll save us doing it again
         $bootstrap->Tick(false, true);
     }
     // Prepare the stream configuration
     // - the streams use this configuration instead of the central configuration so we can use different settings in different streams
     $config = array('designated_path' => $progress['cache']['local_tmp_dir'], 'compression' => $this->WPOnlineBackup->Get_Env('deflate_available') ? 'DEFLATE' : 'store', 'encryption' => $progress['cache']['enc_type'], 'encryption_key' => $progress['cache']['enc_key']);
     // Set up the required stream
     if ($progress['config']['target'] == 'online') {
         $stream_type = 'Stream_Delta';
     } else {
         $stream_type = 'Stream_Full';
     }
     require_once WPONLINEBACKUP_PATH . '/include/' . strtolower($stream_type) . '.php';
     $name = 'WPOnlineBackup_' . $stream_type;
     $stream = new $name($this->WPOnlineBackup);
     // Open the file - suppress errors in html_entity_decode as PHP4 will flood out warnings about multibyte characters
     if (($ret = $stream->Open($config, @html_entity_decode(get_bloginfo('name'), ENT_QUOTES, get_bloginfo('charset')), @html_entity_decode(get_bloginfo('description'), ENT_QUOTES, get_bloginfo('charset')))) !== true) {
         return $bootstrap->Create_Failure();
     }
     if ($progress['config']['target'] == 'email') {
         // Check we aren't too big to process. Add 50% to the filesize to allow for MIME encoding and headers etc, and take 5MB from Memory_Limit for processing
         $max = floor((($memory_limit = $this->WPOnlineBackup->Memory_Limit()) - 5 * 1024 * 1024) / 2.5);
     }
     // Store the steam - we cannot store it in this->stream until it is Opened because we call CleanUp in On_Shutdown if an error occurs and CleanUp can not be called until after Open or Load
     $bootstrap->Set_Stream($stream_type, $stream);
     return true;
 }
    function Print_Settings_Backup()
    {
        // Include the tables backup processor
        require_once WPONLINEBACKUP_PATH . '/include/tables.php';
        require_once WPONLINEBACKUP_PATH . '/include/files.php';
        // Create an instance of tables and files
        $tables = new WPOnlineBackup_Backup_Tables($this->WPOnlineBackup);
        $files = new WPOnlineBackup_Backup_Files($this->WPOnlineBackup);
        // Grab the available table list
        list($core, $custom) = $tables->Fetch_Available();
        // Convert to HTMLEntities
        foreach ($core as $entry => $display) {
            $core[$entry] = htmlentities($display, ENT_QUOTES);
        }
        foreach ($custom as $entry => $display) {
            $custom[$entry] = htmlentities($display, ENT_QUOTES);
        }
        // Find the last custom item so we know when to stop placing line breaks
        end($custom);
        $last = key($custom);
        // Get the uploads directory information
        $uploads = wp_upload_dir();
        // Resolve the parent folder path so we can display it
        list($root, $parent_root, $wordpress_root) = $files->Get_Roots();
        // Regex to strip root from a path
        $strip_root = '#^' . preg_quote($root, '#') . '/#';
        ?>
<p style="float: left; margin: 5px"><img src="<?php 
        echo WPONLINEBACKUP_URL;
        ?>
/images/settings.png" alt=""></p>
<p><?php 
        _e('These settings affect the behaviour of the backups. If you have custom/plugin database tables you can choose whether to back them up or not, or only choose to backup certain ones. You can also exclude comments and trash.', 'wponlinebackup');
        ?>
</p>
<p><?php 
        _e('For filesystem backups you can also specify whether to include themes and plugins or not.', 'wponlinebackup');
        ?>
</p>
<table class="form-table" style="clear: left; border-top: 1px solid #DFDFDF">
<tr valign="top">
<th scope="row" style="text-align: right; padding: 15px"><label style="font-weight: bold"><?php 
        _e('Database backup behaviour:', 'wponlinebackup');
        ?>
</label></th>
<td><?php 
        // If we have detected core tables, display them so we know they are going to be backed up
        if (count($core)) {
            ?>
<p><?php 
            _e('Core WordPress tables will always be backed up when the database is included.', 'wponlinebackup');
            ?>
</p>
<?php 
        }
        ?>
<p><input type="radio" name="selection_method" id="selection_method_include" value="include"<?php 
        // Mark as checked if we selected this option
        if ($this->WPOnlineBackup->Get_Setting('selection_method') == 'include') {
            ?>
 checked="checked"<?php 
        }
        ?>
>&nbsp;<label for="selection_method_include"><?php 
        _e('ONLY backup the custom/plugin tables selected below (new tables will not be backed up until explicitly selected.)', 'wponlinebackup');
        ?>
</label><br>
<input type="radio" name="selection_method" id="selection_method_exclude" value="exclude"<?php 
        // Mark as checked if we selected this option
        if ($this->WPOnlineBackup->Get_Setting('selection_method') != 'include') {
            ?>
 checked="checked"<?php 
        }
        ?>
>&nbsp;<label for="selection_method_exclude"><?php 
        _e('Backup all custom/plugin tables EXCEPT those selected below (new tables will automatically be backed up until explicitly selected.) [Recommended]', 'wponlinebackup');
        ?>
</label></p>
<p><?php 
        // If we have custom tables, list them here, or display a message saying none found
        if (count($custom)) {
            foreach ($custom as $entry => $display) {
                ?>
<input type="checkbox" name="selection_list[]" id="selection_list_<?php 
                echo $display;
                ?>
" value="<?php 
                echo $display;
                ?>
"<?php 
                // Check the box if we have this table selected
                if (in_array($entry, $this->WPOnlineBackup->Get_Setting('selection_list'))) {
                    ?>
 checked="checked"<?php 
                }
                ?>
>&nbsp;<label for="selection_list_<?php 
                echo $display;
                ?>
"><?php 
                echo $display;
                ?>
</label><?php 
                // If not the last, add a new line
                if ($entry != $last) {
                    ?>
<br>
<?php 
                }
            }
        } else {
            ?>
<i><?php 
            _e('No non-default tables currently exist.', 'wponlinebackup');
            ?>
</i><?php 
        }
        ?>
</p></td>
</tr>
<tr valign="top">
<th scope="row" style="text-align: right; padding: 15px"><label style="font-weight: bold"><?php 
        _e('Database excludes:', 'wponlinebackup');
        ?>
</label></th>
<td><p><input name="ignore_trash_comments" type="checkbox" id="ignore_trash_comments"<?php 
        // Is this enabled?
        if ($this->WPOnlineBackup->Get_Setting('ignore_trash_comments')) {
            ?>
 checked="checked"<?php 
        }
        ?>
 value="1">&nbsp;<label for="ignore_trash_comments"><?php 
        _e('Exclude comments in the trash.', 'wponlinebackup');
        ?>
</label><br>
<input name="ignore_spam_comments" type="checkbox" id="ignore_spam_comments"<?php 
        // Is this enabled?
        if ($this->WPOnlineBackup->Get_Setting('ignore_spam_comments')) {
            ?>
 checked="checked"<?php 
        }
        ?>
 value="1">&nbsp;<label for="ignore_spam_comments"><?php 
        _e('Exclude comments that are marked as spam.', 'wponlinebackup');
        ?>
</label></p></td>
</tr>
<tr valign="top">
<th scope="row" style="text-align: right; padding: 15px"><label style="font-weight: bold"><?php 
        _e('Filesystem excludes:', 'wponlinebackup');
        ?>
</label></th>
<td><p><?php 
        _e('Files that are part of the default WordPress installation will always be backed up when the filesystem is included.', 'wponlinebackup');
        ?>
</p>
<p><input name="filesystem_plugins" type="checkbox" id="filesystem_plugins"<?php 
        // Is this enabled?
        if (!$this->WPOnlineBackup->Get_Setting('filesystem_plugins')) {
            ?>
 checked="checked"<?php 
        }
        ?>
 value="1">&nbsp;<label for="filesystem_plugins"><?php 
        printf(__('Exclude plugins (%s)', 'wponlinebackup'), implode('; ', array(preg_replace($strip_root, '', $files->Normalise_Path(WP_PLUGIN_DIR)), preg_replace($strip_root, '', $files->Normalise_Path(WPMU_PLUGIN_DIR)))));
        ?>
</label><br>
<input name="filesystem_themes" type="checkbox" id="filesystem_themes"<?php 
        // Is this enabled?
        if (!$this->WPOnlineBackup->Get_Setting('filesystem_themes')) {
            ?>
 checked="checked"<?php 
        }
        ?>
 value="1">&nbsp;<label for="filesystem_themes"><?php 
        printf(__('Exclude themes (%s)', 'wponlinebackup'), preg_replace($strip_root, '', $files->Normalise_Path(get_theme_root())));
        ?>
</label><br>
<input name="filesystem_uploads" type="checkbox" id="filesystem_uploads"<?php 
        // Is this enabled?
        if (!$this->WPOnlineBackup->Get_Setting('filesystem_uploads')) {
            ?>
 checked="checked"<?php 
        }
        ?>
 value="1">&nbsp;<label for="filesystem_uploads"><?php 
        printf(__('Exclude uploads (%s)', 'wponlinebackup'), preg_replace($strip_root, '', $files->Normalise_Path($uploads['basedir'])));
        ?>
</label></p>
<p><?php 
        printf(__('Custom filesystem excludes can be specified here, one per line, relative to the following folder: %s', 'wponlinebackup'), $root);
        ?>
<br>
<?php 
        printf(__('For example, to exclude %s, enter %s into the box below on its own line. Always use forward slashes even if your server runs Windows.'), $root . '/folder/cache', 'folder/cache');
        ?>
<br>
<textarea rows="10" cols="60" name="filesystem_excludes" id="filesystem_excludes"><?php 
        echo esc_html($this->WPOnlineBackup->Get_Setting('filesystem_excludes'));
        ?>
</textarea></p></td>
</tr>
<tr valign="top">
<th scope="row" style="text-align: right; padding: 15px"><label style="font-weight: bold"><?php 
        _e('WordPress in a subdirectory:', 'wponlinebackup');
        ?>
</label></th>
<td><p><?php 
        _e('By default, only the WordPress folder is backed up. However, if your WordPress folder is installed as a subdirectory within a larger website, and you wish to backup that website also, this option will allow you to do just that.', 'wponlinebackup');
        ?>
<br>
<b><?php 
        _e('If you are not sure or have not installed WordPress as a subdirectory, you should leave this option disabled as you may end up backing up significantly more than expected.', 'wponlinebackup');
        ?>
</b><br>
<?php 
        _e('You can exclude items from this level by prefixing the filesystem exclude entry with &quot;../&quot; (dot dot forward-slash) like this: ../exclude/from/parent');
        ?>
</p>
<?php 
        if (false === ($d = @opendir($parent_root))) {
            // Couldn't resolve, let the user know this option will not work, but don't hide the option so it can be disabled if it was enabled
            ?>
<p><span style="padding: 4px; display: inline-block; text-align: left; border: 1px dashed #000; background: #E9E9E9">
<img src="<?php 
            echo WPONLINEBACKUP_URL;
            ?>
/images/information.png" style="width: 16px; height: 16px; vertical-align: middle" alt="">&nbsp;<b><?php 
            _e('WordPress looks like it is NOT installed as a subdirectory so this option SHOULD be ignored. If you believe this to be wrong, you can enable the option anyway and any problems will be reported in the event log during backup.', 'wponlinebackup');
            ?>
</b>
</span></p>
<?php 
            $upone_parent = false;
        } else {
            $upone_parent = true;
            @closedir($d);
        }
        ?>
<p><input name="filesystem_upone" type="checkbox" id="filesystem_upone"<?php 
        // Is this enabled?
        if ($this->WPOnlineBackup->Get_Setting('filesystem_upone')) {
            ?>
 checked="checked"<?php 
        }
        ?>
 value="1">&nbsp;<label for="filesystem_upone"><?php 
        if ($upone_parent) {
            printf(__('Backup the parent directory as well as the WordPress directory: %s', 'wponlinebackup'), $parent_root);
        } else {
            _e('Backup the parent directory as well as the WordPress directory.', 'wponlinebackup');
        }
        ?>
</label></p></td>
</tr>
<tr valign="top">
<th scope="row" style="text-align: right; padding: 18px"><label for="local_min_gens" style="font-weight: bold"><?php 
        _e('Minimum Local Backups:', 'wponlinebackup');
        ?>
</label></th>
<td><p><?php 
        _e('The minimum number of Local Backups that should be kept, regardless of their size. We recommend 2 so you always have at least the last 2 backups available.', 'wponlinebackup');
        ?>
</p>
<p><input id="local_min_gens" name="local_min_gens" type="text" pattern="\d*" value="<?php 
        echo esc_attr($this->WPOnlineBackup->Get_Setting('local_min_gens'));
        ?>
" /></p></td>
</tr>
<tr valign="top">
<th scope="row" style="text-align: right; padding: 18px"><label for="local_max_storage" style="font-weight: bold"><?php 
        _e('Maximum Local Backups Storage:', 'wponlinebackup');
        ?>
</label></th>
<td><p><?php 
        _e('The maximum storage space Local Backups should utilise in MiB. Older Local Backups will automatically be deleted when storage exceeds this. This settings is ignored if you have less backups available than the Minimum Local Backups.', 'wponlinebackup');
        ?>
</p>
<p><input id="local_max_storage" name="local_max_storage" type="text" pattern="\d*" value="<?php 
        echo esc_attr($this->WPOnlineBackup->Get_Setting('local_max_storage'));
        ?>
" /></p></td>
</tr>
<tr valign="top">
<th scope="row" style="text-align: right; padding: 18px"><label for="max_log_age" style="font-weight: bold"><?php 
        _e('Activity and event logs:', 'wponlinebackup');
        ?>
</label></th>
<td><p><?php 
        _e('This is for how long activity and event logs should be kept. We recommend 6 months.', 'wponlinebackup');
        ?>
</p>
<p><select id="max_log_age" name="max_log_age">
<?php 
        for ($i = 1; $i <= 12; $i++) {
            ?>
	<option value="<?php 
            echo $i;
            ?>
"<?php 
            if ($this->WPOnlineBackup->Get_Setting('max_log_age') == $i) {
                ?>
 selected="selected"<?php 
            }
            ?>
><?php 
            if ($i == 6) {
                printf(__('%d months [Recommended]', 'wponlinebackup'), $i);
            } else {
                printf(_n('%d month', '%d months', $i, 'wponlinebackup'), $i);
            }
            ?>
</option>
<?php 
        }
        ?>
</select></p></td>
</tr>
</table>
<?php 
    }