Exemplo n.º 1
0
 function _Decryption_Loop()
 {
     // If legacy drop to legacy function
     if ($this->job['legacy']) {
         return $this->_Legacy_Decryption_Loop();
     }
     // Grab the real block size and adjust the configured block size to ensure it is an exact divisor
     $real_blocksize = mcrypt_enc_get_block_size($this->cipher);
     $blocksize = $this->WPOnlineBackup->Get_Setting('max_block_size');
     if (($rem = $blocksize % $real_blocksize) != 0) {
         $blocksize += $real_blocksize - $rem;
     }
     // Grab total length of data - increase it to block size and calculate the amount we'll need to trim after decryption
     $len = $this->job['header']['len'];
     if (($rem = $len % $real_blocksize) != 0) {
         $len += $trim = $real_blocksize - $rem;
     } else {
         $trim = 0;
     }
     // Take off what we've already done
     $len -= $this->job['done_bytes'];
     // Decrypt loop - if we've already done the last block break out
     while ($len - $trim > 0) {
         $block = min($blocksize, $len);
         if (($data = @fread($this->file, $block)) === false) {
             return OBFW_Exception();
         }
         if (strlen($data) != $block) {
             return 'Partially read ' . strlen($data) . ' of ' . $block . ' bytes from encrypted data file for decryption.';
         }
         // Change the IV for the next block to the encrypted data of the last block we're about to decrypt
         $this->job['current_iv'] = substr($data, $block - $real_blocksize, $real_blocksize);
         $data = mdecrypt_generic($this->cipher, $data);
         if (($len -= $block) <= 0) {
             if ($trim != 0) {
                 $data = substr($data, 0, $trim * -1);
             }
         }
         $block = strlen($data);
         if (true !== ($ret = $this->stream->Write($data))) {
             return 'Write to stream failed. ' . $ret;
         }
         if ($this->hash_ctx !== false) {
             hash_update($this->hash_ctx, $data);
             $this->job['hash_len'] += $block;
         } else {
             if ($this->job['crc'] !== false) {
                 $this->job['crc'] = WPOnlineBackup_Functions::Combine_CRC32($this->job['crc'], crc32($data), $block);
             } else {
                 $this->job['crc'] = crc32($data);
             }
         }
         $this->job['done_bytes'] += $block;
         // Update the progress
         if ($this->job['done_bytes'] >= $this->job['header']['len']) {
             $this->job['progress'] = 99;
         } else {
             $this->job['progress'] = 10 + floor($this->job['done_bytes'] * 89 / $this->job['header']['len']);
             if ($this->job['progress'] > 99) {
                 $this->job['progress'] = 99;
             }
         }
         $this->bootstrap->Tick();
     }
     if ($this->hash_ctx !== false && $this->job['hash_len'] > 0) {
         list($crc) = array_values(unpack('N', hash_final($this->hash_ctx, true)));
         if ($this->job['crc'] !== false) {
             $this->job['crc'] = WPOnlineBackup_Functions::Combine_CRC32($this->job['crc'], $crc, $this->job['hash_len']);
         } else {
             $this->job['crc'] = $crc;
         }
         $this->hash_ctx = false;
     }
     if ($this->job['crc'] != $this->job['header']['crc']) {
         return false;
     }
     $this->bootstrap->Log_Event(WPONLINEBACKUP_EVENT_INFORMATION, 'File integrity check was successful.');
     // Prevent duplicated messages
     $this->bootstrap->Tick(false, true);
     return true;
 }
Exemplo n.º 2
0
 function PBKDF2_Broken($p, $s, $c, $kl)
 {
     $hl = strlen(sha256('test')) / 2;
     $kb = ($kl + ($hl - $kl % $hl)) / $hl;
     $dk = '';
     for ($bn = 1; $bn <= $kb; $bn++) {
         $ib = $b = WPOnlineBackup_Functions::hash_hmac_sha256_Broken($s . pack('N', $bn), $p, true);
         for ($i = 1; $i < $c; $i++) {
             $ib ^= $b = WPOnlineBackup_Functions::hash_hmac_sha256_Broken($b, $p, true);
         }
         $dk .= $ib;
     }
     return substr($dk, 0, $kl);
 }
 function Last_Write()
 {
     if ($this->hash_ctx !== false) {
         hash_update($this->hash_ctx, $this->data);
         $this->hash_len += $this->data_len;
     } else {
         if ($this->crc !== false) {
             $this->crc = WPOnlineBackup_Functions::Combine_CRC32($this->crc, crc32($this->data), $this->data_len);
         } else {
             $this->crc = crc32($this->data);
         }
     }
     // Encrypt remaining buffer in place - leave the padding
     $this->data = mcrypt_generic($this->cipher, $this->data);
     $len = strlen($this->data);
     $this->encsize += $len;
     // Write it
     if (($ret = $this->disk->Write($this->data, $len)) !== true) {
         return $ret;
     }
     // Clear the buffer
     $this->data = '';
     $this->data_len = 0;
     return true;
 }
Exemplo n.º 4
0
 function Collect_Files($param)
 {
     global $wpdb;
     if ($this->job['progress'] == 0) {
         $wpdb->query('START TRANSACTION');
         // Initialise by grabbing the total number of items to backup, so we can track the progress
         if (is_null($row = $wpdb->get_row($this->db_force_master . 'SELECT COUNT(*) AS total ' . 'FROM `' . $this->db_prefix . 'wponlinebackup_items` ' . 'WHERE activity_id = ' . $this->bootstrap->activity_id . ' AND backup = 1 AND bin = ' . WPONLINEBACKUP_BIN_FILESYSTEM . ' AND item_id > ' . $this->job['last_id'], ARRAY_A)) && is_null($wpdb->get_col_info('name', 0))) {
             $ret = $this->bootstrap->DBError(__LINE__, __FILE__);
             $wpdb->query('COMMIT');
             return $ret;
         }
         if (!is_null($row)) {
             $this->job['total'] = $row['total'];
         }
         $this->job['progress'] = 5;
         $this->bootstrap->Tick();
     }
     if ($this->job['progress'] < 99) {
         while (true) {
             $wpdb->query('START TRANSACTION');
             // Fetch a batch of files we have marked for backup
             $result = $wpdb->get_results($this->db_force_master . 'SELECT f.item_id, f.type, f.name_bin, p.item_id AS parent_id, p.name AS parent_name, p.path AS parent_path, f.new_file_size, f.new_mod_time ' . 'FROM `' . $this->db_prefix . 'wponlinebackup_items` AS f ' . 'LEFT JOIN `' . $this->db_prefix . 'wponlinebackup_items` AS p ON (p.bin = f.bin AND p.item_id = f.parent_id) ' . 'WHERE f.activity_id = ' . $this->bootstrap->activity_id . ' AND f.backup = 1 AND f.bin = ' . WPONLINEBACKUP_BIN_FILESYSTEM . ' AND f.item_id > ' . $this->job['last_id'] . ' ' . 'ORDER BY f.item_id ASC ' . 'LIMIT 50', ARRAY_A);
             if (is_null($wpdb->get_col_info('name', 0))) {
                 $ret = $this->bootstrap->DBError(__LINE__, __FILE__);
                 $wpdb->query('COMMIT');
                 return $ret;
             }
             $wpdb->query('COMMIT');
             // If no files left, return
             if (count($result) == 0) {
                 $this->job['progress'] = 99;
                 break;
             }
             // Process file list
             foreach ($result as $item) {
                 if (is_null($item['parent_id'])) {
                     $item['parent_id'] = 0;
                     $item['parent_path'] = '';
                     $item['parent_name'] = '';
                 }
                 $item_name = $item['parent_path'] . $item['parent_name'] . '/' . $item['name_bin'];
                 $item_path = $this->job['root'] . $item_name;
                 if ($item['type'] == WPONLINEBACKUP_ITEM_FILE) {
                     // If recovery mode we have previously timed out and we are taking our time in this run
                     if ($this->WPOnlineBackup->recovery_mode) {
                         $size = $this->Prevent_Timeout_Start('fs:c', $item_path);
                     } else {
                         $size = null;
                     }
                     if (is_null($size)) {
                         // Backup the file
                         if (($ret = $this->stream->Add_File_From_Path(WPONLINEBACKUP_BIN_FILESYSTEM, WPOnlineBackup_Functions::UTF8_Validate($item_name), $item_path, $size, array('item_id' => $item['item_id'], 'parent_id' => $item['parent_id'], 'mod_time' => $item['new_mod_time'], 'backup_time' => $this->job['generation']))) !== true) {
                             // $ret false means we need to end backup - but use the $size for the reason like we would if simply skipping
                             if ($ret === false) {
                                 $this->bootstrap->Log_Event(WPONLINEBACKUP_ERROR, $size[0]);
                                 return $size[1];
                             }
                             return $this->bootstrap->FSError(__LINE__, __FILE__, '\'Filesystem' . $item_path . '\' (' . (is_array($size) ? $size['file_size'] : __('Size unknown', 'wponlinebackup')) . ')', $ret);
                         }
                     }
                     // Update the progress message and report an error if needed
                     if (is_array($size)) {
                         if ($size['file_size'] != $item['new_file_size']) {
                             if ($wpdb->query('UPDATE `' . $this->db_prefix . 'wponlinebackup_items` ' . 'SET new_file_size = ' . $size['file_size'] . ' ' . 'WHERE bin = ' . WPONLINEBACKUP_BIN_FILESYSTEM . ' AND item_id = ' . $item['item_id']) === false) {
                                 return $this->bootstrap->DBError(__LINE__, __FILE__);
                             }
                         }
                         $this->progress['message'] = sprintf($this->file_taken_msg, WPOnlineBackup_Functions::UTF8_Validate($item_name));
                         // Insert the generation
                         if ($wpdb->query('INSERT INTO `' . $this->db_prefix . 'wponlinebackup_generations` ' . '(bin, item_id, backup_time, file_size, stored_size, mod_time, commit) ' . 'VALUES (' . WPONLINEBACKUP_BIN_FILESYSTEM . ', ' . $item['item_id'] . ', ' . $this->job['generation'] . ', ' . $item['new_file_size'] . ', ' . $size['stored_size'] . ', ' . $item['new_mod_time'] . ', ' . '0' . ') ' . 'ON DUPLICATE KEY UPDATE item_id = VALUES(item_id)') === false) {
                             return $this->bootstrap->DBError(__LINE__, __FILE__);
                         }
                     } else {
                         $this->bootstrap->Log_Event(WPONLINEBACKUP_EVENT_ERROR, sprintf(__('File %s was skipped: %s', 'wponlinebackup'), WPOnlineBackup_Functions::UTF8_Validate($item_name), $size));
                         $this->progress['message'] = sprintf($this->file_failed_msg, WPOnlineBackup_Functions::UTF8_Validate($item_name), $size);
                         // To prevent duplication of the above event log, we'll have to do something special - mark the item as DON'T backup
                         // We don't want to force an update if we can help it, and we don't want to have to use Mark_Visited/Already_Visited here too
                         if ($wpdb->query('UPDATE `' . $this->db_prefix . 'wponlinebackup_items` ' . 'SET backup = 0 ' . 'WHERE bin = ' . WPONLINEBACKUP_BIN_FILESYSTEM . ' AND item_id = ' . $item['item_id']) === false) {
                             return $this->bootstrap->DBError(__LINE__, __FILE__);
                         }
                     }
                     // If recovery mode we can now clear where we are as we've just finished this entry
                     if ($this->WPOnlineBackup->recovery_mode) {
                         $this->progress['tick_progress'][0] = false;
                     }
                 } else {
                     $success = true;
                     // Backup the folder
                     if (($ret = $this->stream->Add_Folder_From_Path(WPONLINEBACKUP_BIN_FILESYSTEM, WPOnlineBackup_Functions::UTF8_Validate($item_name), $item_path, $success, array('item_id' => $item['item_id'], 'parent_id' => $item['parent_id'], 'backup_time' => $this->job['generation']))) !== true) {
                         // $ret false means we need to end backup - but use the $success for the reason like we would if simply skipping
                         if ($ret === false) {
                             $this->bootstrap->Log_Event(WPONLINEBACKUP_ERROR, $success[0]);
                             return $success[1];
                         }
                         return $this->bootstrap->FSError(__LINE__, __FILE__, '\'Filesystem' . $item_path . '/\'', $ret);
                     }
                     // Report an error
                     if ($success !== true) {
                         $this->bootstrap->Log_Event(WPONLINEBACKUP_EVENT_ERROR, sprintf(__('Status of folder %s was skipped: %s', 'wponlinebackup'), WPOnlineBackup_Functions::UTF8_Validate($item_name), $success));
                         // To prevent duplication of the above event log, we'll have to do something special - mark the item as DON'T backup
                         // We don't want to force an update if we can help it, and we don't want to have to use Mark_Visited/Already_Visited here too
                         if ($wpdb->query('UPDATE `' . $this->db_prefix . 'wponlinebackup_items` ' . 'SET backup = 0 ' . 'WHERE bin = ' . WPONLINEBACKUP_BIN_FILESYSTEM . ' AND item_id = ' . $item['item_id']) === false) {
                             return $this->bootstrap->DBError(__LINE__, __FILE__);
                         }
                     } else {
                         // Insert the generation
                         if ($wpdb->query('INSERT INTO `' . $this->db_prefix . 'wponlinebackup_generations` ' . '(bin, item_id, backup_time, commit) ' . 'VALUES (' . WPONLINEBACKUP_BIN_FILESYSTEM . ', ' . $item['item_id'] . ', ' . $this->job['generation'] . ', ' . '0' . ') ' . 'ON DUPLICATE KEY UPDATE item_id = VALUES(item_id)') === false) {
                             return $this->bootstrap->DBError(__LINE__, __FILE__);
                         }
                     }
                 }
                 ++$this->job['done'];
                 // Update the progress
                 if ($this->job['done'] >= $this->job['total']) {
                     $this->job['progress'] = 98;
                 } else {
                     $this->job['progress'] = 5 + floor($this->job['done'] * 93 / $this->job['total']);
                     if ($this->job['progress'] >= 98) {
                         $this->job['progress'] = 98;
                     }
                 }
                 $this->job['last_id'] = $item['item_id'];
                 $this->bootstrap->Tick();
             }
         }
     }
     return true;
 }
 function Commit_Stream()
 {
     // ASSERTION - We have just finalised a stream with End_Stream() and are ready to commit it
     $size = $this->rolling_size;
     // Did we never hit the large file size? If not, just store with normal deflation
     if ($size <= $this->WPOnlineBackup->Get_Setting('file_buffer_size')) {
         // Calculate CRC
         $crc = crc32($this->rolling_buffer);
         // Compress the data
         $this->rolling_buffer = gzdeflate($this->rolling_buffer);
         // Update the compressed data size
         $zlen = strlen($this->rolling_buffer);
         if (($ret = $this->writer->Write($this->rolling_buffer, $zlen)) !== true) {
             return $ret;
         }
         $this->rolling_buffer = false;
         // Already done everything neccessary, move out
         return compact('size', 'crc', 'zlen');
     }
     // Finalize crc if we used hash_init
     if ($this->rolling_hash_ctx !== false) {
         list($inc_crc) = array_values(unpack('N', hash_final($this->rolling_hash_ctx, true)));
         $this->rolling_hash_ctx = false;
         if ($this->rolling_crc !== false) {
             $this->rolling_crc = WPOnlineBackup_Functions::Combine_CRC32($this->rolling_crc, $inc_crc, $this->rolling_hash_len);
         } else {
             $this->rolling_crc = $inc_crc;
         }
     }
     $crc = $this->rolling_crc;
     // Close and delete the buffer file
     $this->rolling_tempfile->CleanUp();
     if ($this->register_temps) {
         $this->WPOnlineBackup->bootstrap->Unregister_Temp($this->rolling_tempfile->Get_File_Path());
     }
     $this->rolling_tempfile = false;
     // Get the deflate stream size
     if (($zlen = @filesize($this->rolling_gzipname)) === false) {
         return OBFW_Exception();
     }
     // Take away header and trailer
     $zlen -= 10 + 8;
     // Start to transfer the compressed data to our own file
     if (($f = @fopen($this->rolling_gzipname, 'rb')) === false) {
         return OBFW_Exception();
     }
     // Skip the header
     if (@fseek($f, 10, SEEK_SET) != 0) {
         $e = OBFW_Exception();
         @fclose($f);
         return $e;
     }
     // Start transferring
     $data = '';
     while (!@feof($f)) {
         // Always get 8 extra bytes
         if (($extract = @fread($f, $this->WPOnlineBackup->Get_Setting('max_block_size') + 8)) === false) {
             $e = OBFW_Exception();
             @fclose($f);
             return $e;
         }
         $data .= $extract;
         // Write all but the last 8 bytes
         $to_write = strlen($data) - 8;
         // Stop if we don't have anything to write
         if ($to_write == 0) {
             break;
         }
         // Write
         if (($ret = $this->writer->Write($data, $to_write)) !== true) {
             @fclose($f);
             return $ret;
         }
         // Leave the last 8 on the buffer
         $data = substr($data, -8);
     }
     // Clean up the tempfile
     @fclose($f);
     return compact('size', 'crc', 'zlen');
 }
 function Add_EOF_Entry()
 {
     // Build EOF entry
     $fields = array(array('a3', 'EOF'), array('C', 0x0));
     // Write the fields
     if (($ret = $this->indx_disk->Write(WPOnlineBackup_Functions::Pack_Fields($fields))) !== true) {
         return $ret;
     }
     return true;
 }
 function Add_CDR_EOF()
 {
     $cdr_len = $this->cdr_ofs;
     $cdr_ofs = $this->ofs;
     // Prepare comment
     $comment = 'Backup file generated by Online Backup for WordPress ' . WPONLINEBACKUP_VERSION . PHP_EOL;
     $fields = array(array('V', 0x6054b50), array('v', 0x0), array('v', 0x0), array('v', $this->file_count), array('v', $this->file_count), array('V', $cdr_len), array('V', $cdr_ofs), array('v', strlen($comment)));
     // Write the fields
     if (($ret = $this->writer->Write(WPOnlineBackup_Functions::Pack_Fields($fields) . $comment)) !== true) {
         return $ret;
     }
     return true;
 }
 function Write_Stream($data, $len = false, $no_write = false)
 {
     // ASSERTION - We are currently in the middle of a stream deflation with Start_Stream
     // Since we always write directly because we have no compression to do, if we don't want to write, return false to say we want to
     if ($no_write) {
         return false;
     }
     // If len is false, use strlen(), otherwise truncate
     if ($len === false) {
         $len = strlen($data);
     } else {
         $data = substr($data, 0, $len);
     }
     // Add to size
     $this->rolling_size += $len;
     // Update crc and zlen
     if ($this->rolling_hash_ctx !== false) {
         hash_update($this->rolling_hash_ctx, $data);
         $this->rolling_hash_len += $len;
     } else {
         if ($this->rolling_crc !== false) {
             $this->rolling_crc = WPOnlineBackup_Functions::Combine_CRC32($this->rolling_crc, crc32($data), $len);
         } else {
             $this->rolling_crc = crc32($data);
         }
     }
     // Write the data
     if (($ret = $this->writer->Write($data, $len)) !== true) {
         return $ret;
     }
     return true;
 }
Exemplo n.º 9
0
    function Print_Local_Table()
    {
        global $wpdb;
        ?>
<p style="float: left; margin: 5px"><img src="<?php 
        echo WPONLINEBACKUP_URL;
        ?>
/images/folders.png" alt=""></p>
<p><?php 
        _e('Below is a list of backup files currently stored on your server. <strong>It is highly recommended that these backups are downloaded and stored away from the server to prevent a total loss if the server fails.</strong>', 'wponlinebackup');
        ?>
</p>
<p><?php 
        echo sprintf(__('Old files are deleted automatically to keep you below %s storage space whilst still keeping a minimum of %s files (configurable in General Settings.) LOCKED files will never be deleted and will not counted towards the storage space.', 'wponlinebackup'), WPOnlineBackup_Formatting::Fix_B($this->WPOnlineBackup->Get_Setting('local_max_storage') * 1048576), $this->WPOnlineBackup->Get_Setting('local_min_gens'));
        ?>
</p>
<p><?php 
        echo sprintf(__('Encrypted files, which have a .ENC file extension, can be decrypted from this page; the result of the decryption will be stored next to the original file in this folder. You can also upload files to this folder via FTP for decryption or storage; the location is: %s.', 'wponlinebackup'), WPONLINEBACKUP_LOCALBACKUPDIR);
        ?>
</p>
<table class="widefat" style="clear: left" cellspacing="0">
<thead>
<tr>
<th scope="col" id="filename" class="manage-column column-filename" style=""><?php 
        echo __('File Name', 'wponlinebackup');
        ?>
</th>
<th scope="col" id="filesize" class="manage-column column-filesize" style=""><?php 
        echo __('File Size', 'wponlinebackup');
        ?>
</th>
<th scope="col" id="created" class="manage-column column-created" style=""><?php 
        echo __('Created', 'wponlinebackup');
        ?>
</th>
<th scope="col" id="settings" class="manage-column column-settings" style=""><?php 
        echo __('Settings', 'wponlinebackup');
        ?>
</th>
<th scope="col" id="actions" class="manage-column column-actions" style=""><?php 
        echo __('Download / Delete', 'wponlinebackup');
        ?>
</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col" class="manage-column column-filename" style=""><?php 
        echo __('File Name', 'wponlinebackup');
        ?>
</th>
<th scope="col" class="manage-column column-filesize" style=""><?php 
        echo __('File Size', 'wponlinebackup');
        ?>
</th>
<th scope="col" class="manage-column column-created" style=""><?php 
        echo __('Created', 'wponlinebackup');
        ?>
</th>
<th scope="col" class="manage-column column-settings" style=""><?php 
        echo __('Settings', 'wponlinebackup');
        ?>
</th>
<th scope="col" class="manage-column column-actions" style=""><?php 
        echo __('Download / Delete', 'wponlinebackup');
        ?>
</th>
</tr>
</tfoot>
<tbody>
<?php 
        // For UTF8_Validate
        require_once WPONLINEBACKUP_PATH . '/include/functions.php';
        // Just don't show backups we've marked for deletion
        $result = $wpdb->get_results('SELECT filename, locked, filesize, creation_date, compressed, encrypted ' . 'FROM `' . $wpdb->prefix . 'wponlinebackup_local`', ARRAY_A);
        // Create a map of filenames and index creation dates
        $filenames = array();
        $creation_dates = array();
        foreach ($result as $download) {
            $filenames[$download['filename']] =& $download;
            $creation_dates[] = $download['creation_date'];
        }
        // Browse the backups directory and populate any missing entries
        if (false !== ($d = @opendir(WPONLINEBACKUP_LOCALBACKUPDIR))) {
            while (false !== ($f = @readdir($d))) {
                // Ignore dot files - also ignore index.html
                if (substr($f, 0, 1) == '.' || $f == 'index.html') {
                    continue;
                }
                // Do we have it already?
                if (isset($filenames[$f])) {
                    continue;
                }
                // Missing entry, get some information we need
                $created = @filemtime(WPONLINEBACKUP_LOCALBACKUPDIR . '/' . $f);
                $size = @filesize(WPONLINEBACKUP_LOCALBACKUPDIR . '/' . $f);
                if ($created === false || $size === false) {
                    continue;
                }
                $encrypted = preg_match('#\\.enc$#i', substr($f, -4)) ? 1 : 0;
                $add = array('locked' => 1, 'filesize' => $size, 'creation_date' => $created, 'compressed' => 0, 'encrypted' => $encrypted);
                // If not UTF-8 valid, add it to the list but not the database since it won't be addable
                if ($f != ($futf = WPOnlineBackup_Functions::UTF8_Validate($f))) {
                    $add['filename'] = sprintf(__('%s <b>(Contains invalid characters, please rename via FTP)</b>', 'wponlinebackup'), $futf);
                } else {
                    $add['filename'] = $f;
                    // Add to database
                    $wpdb->insert($wpdb->prefix . 'wponlinebackup_local', $add, array('%d', '%d', '%d', '%d', '%d', '%s'));
                }
                // Add to results
                $result[] = $add;
                $creation_dates[] = $created;
            }
            @closedir($d);
        }
        // Sort
        array_multisort($creation_dates, SORT_DESC, $result);
        // Display the backups, or an empty message
        if (count($result) == 0) {
            ?>
<tr>
<td colspan="5" style="text-align: center; padding: 12px"><img src="<?php 
            echo WPONLINEBACKUP_URL;
            ?>
/images/information.png" style="width: 16px; height: 16px; vertical-align: middle" alt="">&nbsp;<i><?php 
            _e('No local backups exist.', 'wponlinebackup');
            ?>
</i></td>
</tr>
<?php 
        } else {
            $c = 0;
            foreach ($result as $download) {
                ?>
<tr<?php 
                if ($c++ % 2 == 0) {
                    ?>
 class="alternate"<?php 
                }
                ?>
 valign="top">
<td class="column-filename"><img src="<?php 
                echo WPONLINEBACKUP_URL;
                ?>
/images/<?php 
                if (preg_match('#\\.([A-Za-z]+)$#', $download['filename'], $matches)) {
                    $ext = $matches[1];
                } else {
                    $ext = '';
                }
                switch ($ext) {
                    case 'enc':
                        echo 'lock_small.png';
                        break;
                    case 'zip':
                    case 'gz':
                        // Legacy V1 database-only backups are GZ extension
                        echo 'compress.png';
                        break;
                    default:
                        echo 'page_white.png';
                        break;
                }
                ?>
" style="width: 16px; height: 16px; vertical-align: middle" alt="">&nbsp;<?php 
                if ($download['locked']) {
                    echo sprintf(__('%s <b>(LOCKED)</b>', 'wponlinebackup'), esc_html($download['filename']));
                } else {
                    echo esc_html($download['filename']);
                }
                ?>
</td>
<td class="column-filesize"><?php 
                echo WPOnlineBackup_Formatting::Fix_B($download['filesize']);
                ?>
</td>
<td class="column-created"><?php 
                echo date_i18n(_x('jS M Y g.i.s A', 'Local backup creation time', 'wponlinebackup'), WPOnlineBackup::Convert_Unixtime_To_Wordpress_Unixtime($download['creation_date']));
                ?>
</td>
<td class="column-settings"><?php 
                $settings = array();
                if ($download['compressed']) {
                    $settings[] = array('compress.png', __('Compressed', 'wponlinebackup'));
                }
                if ($download['encrypted']) {
                    $settings[] = array('lock_small.png', __('Encrypted', 'wponlinebackup'));
                }
                if (count($settings)) {
                    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" alt="<?php 
                        echo $icon[1];
                        ?>
" title="<?php 
                        echo $icon[1];
                        ?>
"><?php 
                        if ($key != $last) {
                            ?>
 <?php 
                        }
                    }
                }
                ?>
</td>
<td class="column-events"><a href="admin.php?page=wponlinebackup&amp;section=local&amp;download=<?php 
                echo urlencode($download['filename']);
                ?>
"><?php 
                echo __('Download', 'wponlinebackup');
                ?>
</a>
 | <a href="admin.php?page=wponlinebackup&amp;section=local&amp;delete=<?php 
                echo urlencode($download['filename']);
                ?>
"><?php 
                echo __('Delete', 'wponlinebackup');
                ?>
</a>
<?php 
                if ($download['locked']) {
                    ?>
 | <a href="admin.php?page=wponlinebackup&amp;section=local&amp;unlock=<?php 
                    echo urlencode($download['filename']);
                    ?>
"><?php 
                    echo __('Unlock', 'wponlinebackup');
                    ?>
</a>
<?php 
                } else {
                    ?>
 | <a href="admin.php?page=wponlinebackup&amp;section=local&amp;lock=<?php 
                    echo urlencode($download['filename']);
                    ?>
"><?php 
                    echo __('Lock', 'wponlinebackup');
                    ?>
</a>
<?php 
                }
                if ($download['encrypted']) {
                    ?>
 | <a href="admin.php?page=wponlinebackup&amp;section=local&amp;decrypt=<?php 
                    echo urlencode($download['filename']);
                    ?>
"><?php 
                    echo __('Decrypt', 'wponlinebackup');
                    ?>
</a>
<?php 
                }
                ?>
</td>
</tr>
<?php 
            }
        }
        ?>
</tbody>
</table>
<p style="text-align: center">
	<img src="<?php 
        echo WPONLINEBACKUP_URL;
        ?>
/images/compress.png" style="width: 16px; height: 16px; vertical-align: middle" alt="">&nbsp;<i><?php 
        echo __('Compressed', 'wponlinebackup');
        ?>
</i>
	&nbsp;
	<img src="<?php 
        echo WPONLINEBACKUP_URL;
        ?>
/images/lock_small.png" style="width: 16px; height: 16px; vertical-align: middle" alt="">&nbsp;<i><?php 
        echo __('Encrypted', 'wponlinebackup');
        ?>
</i>
</p>
<?php 
    }