Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
posthelic
/
wp-content
/
plugins
/
wponlinebackup
/
include
:
disk.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /* WPOnlineBackup_Disk - Performs the disk operations required to write the backup Also allows spanning accross multiple files in timeout situations and generates patch files if necessary */ class WPOnlineBackup_Disk { /*private*/ var $WPOnlineBackup; /*private*/ var $status; /*private*/ var $rotate_id; /*private*/ var $prefix; /*private*/ var $name; /*private*/ var $file; /*private*/ var $offset; /*private*/ var $size; /*private*/ var $p_file; /*private*/ var $p_offset; /*private*/ var $p_size; /*private*/ var $p_index; /*private*/ var $rotation; /*private*/ var $patches; /*private*/ var $header = false; /*private*/ var $rc_header; /*private*/ var $r_files; /*private*/ var $rp_files; /*private*/ var $rc_file; /*private*/ var $rc_offset; /*public*/ function WPOnlineBackup_Disk( & $WPOnlineBackup, $rotate_id = 0 ) { $this->WPOnlineBackup = & $WPOnlineBackup; $this->rotate_id = $rotate_id; $this->r_files = $this->rp_files = array(); } /*public*/ function Get_Header() { if ( $this->header === false ) $this->header = <<<HEADER <?php /*Rejection header*/ __halt_compiler(); } HEADER; return $this->header; } /*public*/ function Save() { // Ensure all data is flushed if ( $this->file !== false ) fflush( $this->file ); if ( $this->p_file !== false ) fflush( $this->p_file ); if ( $this->rc_file !== false ) fflush( $this->rc_file ); $state = array( 'status' => $this->status, 'header' => $this->header, // In case we change during update 'rc_header' => $this->rc_header, 'has_header' => $this->has_header, 'rotate_id' => $this->rotate_id, 'prefix' => $this->prefix, 'name' => $this->name, 'offset' => $this->offset, 'size' => $this->size, 'd_offset' => $this->d_offset, 'rotation' => $this->rotation, 'p_offset' => $this->p_offset, 'p_size' => $this->p_size, 'p_index' => $this->p_index, 'p_rindex' => $this->p_rindex, 'patches' => $this->patches, ); if ( $this->status == 2 ) { $state['rc_offset'] = $this->rc_offset; } return $state; } /*public*/ function Load( $state, $rotation = false ) { // ASSERTION - Status is null and we are initialised $this->status = $state['status']; $this->header = $state['header']; $this->rc_header = $state['rc_header']; $this->has_header = $state['has_header']; $this->rotate_id = $state['rotate_id']; if ( $rotation === false ) $rotate = false; else $rotate = $rotation != $this->rotate_id ? true : false; $this->prefix = $state['prefix']; $this->name = $state['name']; $this->offset = $state['offset']; $this->size = $state['size']; $this->d_offset = $state['d_offset']; $this->p_file = false; $this->p_offset = $state['p_offset']; $this->p_size = $state['p_size']; $this->p_index = $state['p_index']; $this->p_rindex = $state['p_rindex']; $this->rotation = $state['rotation']; $this->patches = $state['patches']; if ( $this->status == 0 && $rotate ) { // Rotate the files $this->rotation[$this->rotate_id] = array( 'rotate_id' => $this->rotate_id, 'offset' => $this->offset, 'size' => $this->size, 'has_header' => $this->has_header, ); $this->offset += $this->size; $this->size = 0; $this->patches[$this->rotate_id] = array( 'rotate_id' => $this->rotate_id, 'offset' => $this->p_offset, 'size' => $this->p_size, ); $this->p_offset += $this->p_size; $this->p_size = 0; // Fill in any gaps, to ensure we delete all files in cleanup $i = $this->rotate_id + 1; while ( $i < $rotation ) { $this->rotation[$i] = array( 'rotate_id' => $i, 'offset' => 0, 'size' => 0, ); $this->patches[$i] = array( 'rotate_id' => $i, 'offset' => 0, 'size' => 0, ); $i++; } // Set the new rotation value $this->rotate_id = $rotation; // All rotations have rejection header $this->has_header = true; // Attempt to cleanup rotated files $this->CleanUp_Rotated(); } if ( $this->status == 0 ) { if ( $this->rotate_id ) $state['name'] .= '.' . $this->rotate_id; // Reopen the file if ( ( $this->file = @fopen( $this->prefix . '/' . $state['name'] . '.php', $rotate ? 'w+b' : 'r+b' ) ) === false ) return OBFW_Exception(); // Attempt to truncate the file to the correct size @ftruncate( $this->file, ( $this->has_header ? strlen( $this->header ) : 0 ) + $this->size ); if ( $rotate || $this->size == 0 ) { if ( !$rotate && @fseek( $this->file, 0, SEEK_SET ) != 0 ) { @fclose( $this->file ); return OBFW_Exception(); } // Write the Rejection header if we want one if ( $this->has_header && true !== ( $ret = $this->Write_Rejection_Header( $this->file ) ) ) { @fclose( $this->file ); return $ret; } } else { // Seek to where we left off if ( @fseek( $this->file, ( $this->has_header ? strlen( $this->header ) : 0 ) + $this->size, SEEK_SET ) != 0 ) { @fclose( $this->file ); return OBFW_Exception(); } } $this->rc_file = false; } else if ( $this->status == 2 ) { $this->rc_offset = $state['rc_offset']; // Open a file to reconstruct into if ( ( $this->rc_file = @fopen( $this->prefix . '/' . $state['name'] . '.rc.php', 'r+b' ) ) === false ) return OBFW_Exception(); // Attempt to truncate the file to the correct size @ftruncate( $this->rc_file, ( $this->rc_header ? strlen( $this->header ) : 0 ) + $this->rc_offset ); if ( $this->rc_offset == 0 ) { // Seek to where we left off if ( @fseek( $this->rc_file, 0, SEEK_SET ) != 0 ) { @fclose( $this->rc_file ); return OBFW_Exception(); } // Write the Rejection header if we want one in the rc file if ( $this->rc_header && true !== ( $ret = $this->Write_Rejection_Header( $this->rc_file ) ) ) { @fclose( $this->rc_file ); return $ret; } } else { // Seek to where we left off if ( @fseek( $this->rc_file, ( $this->rc_header ? strlen( $this->header ) : 0 ) + $this->rc_offset, SEEK_SET ) != 0 ) { @fclose( $this->rc_file ); return OBFW_Exception(); } } $this->d_offset = $this->rc_offset; $this->file = false; } else { $this->file = false; $this->rc_file = false; } // Clean up deleted data if need be $this->Delete(); return true; } /*public*/ function Initialise( $prefix ) { $this->prefix = $prefix; } /*public*/ function Open( $name, $rjct_header = true ) { // ASSERTION - Status is null and we are initialised $this->status = 0; // Set the rejection header $this->Get_Header(); // Modify the name to include a random seed so it is hidden from the world $this->name = $name = $name . '.' . $this->WPOnlineBackup->Random_Seed( $name, 'disk' ); if ( $this->rotate_id ) $name .= '.' . $this->rotate_id; // Create the file with PHP extension so you cannot download it if ( ( $this->file = @fopen( $this->prefix . '/' . $name . '.php', 'w+b' ) ) === false ) return OBFW_Exception(); $this->rc_header = $rjct_header; $this->has_header = $rjct_header; // Write the Rejection header if we want one on the initial file if ( $this->has_header && true !== ( $ret = $this->Write_Rejection_Header( $this->file ) ) ) { @fclose( $this->file ); return $ret; } $this->offset = 0; $this->size = 0; $this->d_offset = 0; $this->p_file = false; $this->p_offset = 0; $this->p_size = 0; $this->p_index = array(); $this->p_rindex = array(); $this->rotation = array(); $this->patches = array(); $this->rc_file = false; return true; } /*public*/ function Get_File_Path() { $name = $this->name; if ( $this->rotate_id ) $name .= '.' . $this->rotate_id; return $this->prefix . '/' . $name . '.php'; } /*private*/ function CleanUp_Handles() { foreach ( $this->r_files as $id => $file ) @fclose( $this->r_files[$id] ); foreach ( $this->rp_files as $id => $file ) @fclose( $this->rp_files[$id] ); if ( $this->p_file !== false ) @fclose( $this->p_file ); if ( $this->file !== false ) @fclose( $this->file ); } /*public*/ function Close() { $this->CleanUp_Handles(); $this->p_file = false; $this->file = false; $this->status = 1; return true; } /*public*/ function CleanUp( $wipe = true ) { if ( $wipe ) $this->Delete( true ); $this->CleanUp_Handles(); if ( $this->rc_file !== false ) { @fclose( $this->rc_file ); if ( $wipe ) @unlink( $this->prefix . '/' . $this->name . '.rc.php' ); } } /*private*/ function Partial_Read( $read, $length, $type, $id ) { $e = OBFW_Exception(); $name = $this->name; switch ( $type ) { case 'patch': $name .= '.patch'; default: if ( $id ) $name .= '.' . $id; break; } if ( $e ) $e = 'PHP last error: ' . $e; else $e = 'PHP has no record of an error.'; return 'Attempt to read from file ' . $this->prefix . '/' . $name . '.php only partially succeeded. Unexpected end of file. Only ' . $read . ' of ' . $length . ' bytes were read. ' . $e; } /*private*/ function Partial_Write( $method, $written, $length, $type = '' ) { $e = OBFW_Exception(); $name = $this->name; switch ( $type ) { case 'patch': $name .= '.patch'; default: if ( $this->rotate_id ) $name .= '.' . $this->rotate_id; break; case 'rc': $name .= '.rc'; break; } if ( $e ) $e = 'PHP last error: ' . $e; else $e = 'PHP has no record of an error.'; return 'Attempt to ' . $method . ' to file ' . $this->prefix . '/' . $name . '.php only partially succeeded. Only ' . $written . ' of ' . $length . ' bytes were written. (' . $this->size . ' bytes already written.) ' . $e; } /*private*/ function _Try_Write( $file, $data, $length, $partial, $partial_type = '' ) { // It seems when you fwrite lots of times it sometimes begins to write less than what you requested // Maybe the write buffer is not quite full, but has room for some bytes, and so PHP adds to it and then returns how many fit? // Then when the buffer is actually full, it waits so it never returns 0 unless something is wrong... Maybe one needs to check the source. // Just loop until we failed, wrote nothing, or finish // Interestingly we ARE seeing instances of 0 getting returned // One cause we have confirmed is the file reached 2GB and PHP is 32-bit with the bodged large file support disabled // However, we still see it even with arbitrary bytes getting written - so that is why we retry with a pause // Another interesting case we are seeing is sometimes the file can reach a certain size and fwrite just crashes the script without reason // This has a completely unknown cause $todo_length = $length; $tries = 5; while ( true ) { if ( ( $written = @fwrite( $file, $data, $todo_length ) ) === false ) return OBFW_Exception(); // If we wrote nothing, fail if ( $written == 0 ) { if ( --$tries <= 0 ) return $this->Partial_Write( $partial, $length - $todo_length, $length, $partial_type ); // Rest a second sleep(1); // Try again continue; } $todo_length -= $written; if ( $todo_length == 0 ) break; // Trim off what we wrote $data = substr( $data, $written ); } return true; } /*public*/ function Write( $data, $length = null ) { // ASSERTION - Status is 0 $rlen = strlen( $data ); if ( is_null( $length ) ) $length = $rlen; else if ( $rlen < $length ) return 'Attempt to write file ' . $this->prefix . '/' . $name . '.php failed due to insufficient data. Only ' . $rlen . ' of ' . $length . ' bytes were available.'; // Nothing to write? if ( $length == 0 ) return true; if ( true !== ( $ret = $this->_Try_Write( $this->file, $data, $length, 'write' ) ) ) return $ret; $this->size += $length; return true; } /*public*/ function Pos() { // Return current position - used for incremental index file. return $this->offset + $this->size; } /*public*/ function Rewrite( $offset, $data, $length = null ) { // ASSERTION - Status is 0 // ASSERTION - Rewrite always rewrites EXISTING data, and never writes past the current end of the file $rlen = strlen( $data ); if ( is_null( $length ) ) $length = $rlen; else if ( $rlen < $length ) return 'Attempt to write file ' . $this->prefix . '/' . $name . '.php failed due to insufficient data. Only ' . $rlen . ' of ' . $length . ' bytes were available.'; if ( $offset >= $this->offset ) { // Rewriting in the active file if ( @fseek( $this->file, ( $this->has_header ? strlen( $this->header ) : 0 ) + ( $offset - $this->offset ), SEEK_SET ) != 0 ) return OBFW_Exception(); if ( true !== ( $ret = $this->_Try_Write( $this->file, $data, $length, 'rewrite' ) ) ) return $ret; if ( @fseek( $this->file, ( $this->has_header ? strlen( $this->header ) : 0 ) + $this->size, SEEK_SET ) != 0 ) return OBFW_Exception(); } else { // Store in patch files only data that is rewritten in rotated files $this_length = min( $this->offset - $offset, $length ); // Open the patches file if needed if ( $this->p_file === false ) { if ( $this->p_size == 0 ) { if ( ( $this->p_file = @fopen( $this->prefix . '/' . $this->name . '.patch.' . $this->rotate_id . '.php', 'w+b' ) ) === false ) return OBFW_Exception(); if ( ( $ret = $this->Write_Rejection_Header( $this->p_file, 'patch' ) ) !== true ) return $ret; } else { if ( ( $this->p_file = @fopen( $this->prefix . '/' . $this->name . '.patch.' . $this->rotate_id . '.php', 'r+b' ) ) === false ) return OBFW_Exception(); // Seek to where we left off if ( @fseek( $this->p_file, strlen( $this->header ) + $this->p_size, SEEK_SET ) != 0 ) return OBFW_Exception(); } } // Write the patch if ( true !== ( $ret = $this->_Try_Write( $this->p_file, $data, $this_length, 'rewrite', 'patch' ) ) ) return $ret; // Index the patch so we can find it when we need it if ( !array_key_exists( $offset, $this->p_index ) ) { $this->p_index[$offset] = array(); ksort( $this->p_index ); } $this->p_index[$offset][$this_length] = array( $this->rotate_id, $this->p_size ); ksort( $this->p_index[$offset] ); if ( !array_key_exists( $this->rotate_id, $this->p_rindex ) ) $this->p_rindex[$this->rotate_id] = 1; else $this->p_rindex[$this->rotate_id]++; $this->p_size += $this_length; // Modify length and offset and recurse if we still have to rewrite some more in the active file $length -= $this_length; if ( $length == 0 ) return true; $offset += $this_length; return $this->Rewrite( $offset, substr( $data, $this_length ), $length ); } return true; } /*public*/ function Flush( & $buffer, $length ) { // ASSERTION - Status is 1 (closed) or 2 (reconstructing) $buffer = ''; $flushed = 0; foreach ( $this->rotation as $id => $rotate ) { if ( $rotate['size'] == 0 ) continue; // Find the file that contains this part of the data if ( $rotate['offset'] + $rotate['size'] > $this->d_offset + $flushed ) { if ( !array_key_exists( $id, $this->r_files ) ) { $name = $this->name; if ( $id ) $name .= '.' . $id; if ( ( $this->r_files[$id] = @fopen( $this->prefix . '/' . $name . '.php', 'rb' ) ) === false ) { $ret = OBFW_Exception(); unset( $this->r_files[$id] ); return $ret; } } $available = $rotate['offset'] + $rotate['size'] - $this->d_offset - $flushed; // Get the data if ( ( $to_flush = min( $length - $flushed, $available ) ) != 0 ) { if ( @fseek( $this->r_files[$id], ( $rotate['has_header'] ? strlen( $this->header ) : 0 ) + $this->d_offset + $flushed - $rotate['offset'], SEEK_SET ) != 0 ) return OBFW_Exception(); if ( ( $extract = @fread( $this->r_files[$id], $to_flush ) ) === false ) return OBFW_Exception(); if ( ( $len = strlen( $extract ) ) != $to_flush ) return $this->Partial_Read( $len, $to_flush, '', $id ); $buffer .= $extract; $flushed += $to_flush; } // If anymore to retrieve from different rotation files, keep looping if ( $flushed < $length ) { @fclose( $this->r_files[$id] ); unset( $this->r_files[$id] ); continue; } else if ( $to_flush == $available ) { // Also close (closing is optimized for continuous flushes) @fclose( $this->r_files[$id] ); unset( $this->r_files[$id] ); } // More data $ret = $this->Patch( $this->d_offset, $length, $buffer, true ); $this->d_offset += $flushed; return $ret; } } // Check the current file if ( $this->offset + $this->size > $this->d_offset + $flushed ) { // Check the file is available (won't be if first call) if ( $this->file === false ) { $name = $this->name; if ( $this->rotate_id ) $name .= '.' . $this->rotate_id; if ( ( $this->file = @fopen( $this->prefix . '/' . $name . '.php', 'rb' ) ) === false ) return OBFW_Exception(); } $available = $this->offset + $this->size - $this->d_offset - $flushed; if ( ( $to_flush = min( $length - $flushed, $available ) ) != 0 ) { // Get the data if ( @fseek( $this->file, ( $this->has_header ? strlen( $this->header ) : 0 ) + $this->d_offset + $flushed - $this->offset, SEEK_SET ) != 0 ) return OBFW_Exception(); if ( ( $extract = @fread( $this->file, $to_flush ) ) === false ) return OBFW_Exception(); if ( ( $len = strlen( $extract ) ) != $to_flush ) return $this->Partial_Read( $len, $to_flush, '', $this->rotate_id ); $buffer .= $extract; $flushed += $to_flush; } // Anymore data? $ret = $to_flush < $available ? true : false; if ( $ret === false ) { // Also close if there is no more data @fclose( $this->file ); $this->file = false; } $ret = $this->Patch( $this->d_offset + $flushed, $to_flush, $buffer, $ret ); $this->d_offset += $flushed; return $ret; } // No more data return false; } /*private*/ function Patch( $offset, $length, & $buffer, $ret ) { // Don't be concerned about loading p_file and not setting it's offset to the end (meaning Rewrite() will overwrite data) // Rewrite() should never be called after Flush() (which calls Patch()) is called so it would be a bug if so. Flush() requires the file is closed for changes // Find applicable patches foreach ( $this->p_index as $p_offset => $index ) { foreach ( $index as $p_length => $patch ) { // If patch already applied, skip if ( $p_offset + $p_length <= $offset ) continue; // If patch doesn't apply yet, return as no more apply (patches are in order) if ( $p_offset >= $offset + $length ) return $ret; // Patch applies, calculate what needs patching if ( $p_offset < $offset ) { $p_start = $offset - $p_offset; $to_copy = min( $p_length - $p_start, $length ); $to = 0; } else { $p_start = 0; $to_copy = min( $offset + $length - $p_offset, $p_length ); $to = $p_offset - $offset; } if ( $to_copy == 0 ) continue; if ( $this->rotate_id == $patch[0] ) { if ( $this->p_file === false ) { if ( ( $this->p_file = @fopen( $this->prefix . '/' . $this->name . '.patch.' . $this->rotate_id . '.php', 'rb' ) ) === false ) return OBFW_Exception(); } $file = $this->p_file; } else { if ( !array_key_exists( $patch[0], $this->rp_files ) ) { $name = $this->name . '.patch'; if ( $patch[0] ) $name .= '.' . $patch[0]; if ( ( $this->rp_files[ $patch[0] ] = @fopen( $this->prefix . '/' . $name . '.php', 'rb' ) ) === false ) { $ret = OBFW_Exception(); unset( $this->rp_files[ $patch[0] ] ); return $ret; } } $file = $this->rp_files[ $patch[0] ]; } // Get the data if ( @fseek( $file, strlen( $this->header ) + $patch[1] + $p_start, SEEK_SET ) != 0 ) return OBFW_Exception(); if ( ( $extract = @fread( $file, $to_copy ) ) === false ) return OBFW_Exception(); if ( ( $len = strlen( $extract ) ) != $to_copy ) return $this->Partial_Read( $len, $to_copy, 'patch', $patch[0] ); $buffer = substr_replace( $buffer, $extract, $to, $len ); } } return $ret; } /*public*/ function Delete( $all = false ) { // First, remove patches we no longer need foreach ( $this->p_index as $p_offset => $index ) { foreach ( $index as $p_length => $patch ) { // If patch still required, keep and leave (patches are kept in order) if ( !$all && $p_offset + $p_length > $this->d_offset ) break 2; // Remove patch, and patch file if neccessary unset( $this->p_index[$p_offset][$p_length] ); $this->p_rindex[ $patch[0] ]--; if ( $this->p_rindex[ $patch[0] ] == 0 ) { // Ensure we don't have this file open if ( array_key_exists( $patch[0], $this->rp_files ) ) { @fclose( $this->rp_files[ $patch[0] ] ); unset( $this->rp_files[ $patch[0] ] ); } $name = $this->name . '.patch'; if ( $patch[0] ) $name .= '.' . $patch[0]; @unlink( $this->prefix . '/' . $name . '.php' ); unset( $this->p_rindex[ $patch[0] ] ); } } } // Find actual files that can be deleted foreach ( $this->rotation as $id => $rotate ) { // If file is past the deletion offset, we need it and all ones after it if ( !$all && $rotate['offset'] + $rotate['size'] > $this->d_offset ) break; // Ensure we don't have this file open if ( array_key_exists( $id, $this->r_files ) ) { @fclose( $this->r_files[ $id ] ); unset( $this->r_files[ $id ] ); } $name = $this->name; if ( $id ) $name .= '.' . $id; @unlink( $this->prefix . '/' . $name . '.php' ); unset( $this->rotation[ $id ] ); } // Delete completely and close if specified to do so if ( $all ) { // Ensure we don't have it open if ( $this->file !== false ) { @fclose( $this->file ); $this->file = false; } $name = $this->name; if ( $this->rotate_id ) $name .= '.' . $this->rotate_id; @unlink( $this->prefix . '/' . $name . '.php' ); } return true; } /*public*/ function Start_Reconstruct() { // ASSERTION - Haven't already started flushing - we can only Flush OR Reconstruct // No reconstruction neccessary, just return true and return the result in Do_Reconstruct() if ( count( $this->rotation ) == 0 ) { $this->status = 3; return true; } // Open a file to reconstruct into if ( ( $this->rc_file = @fopen( $this->prefix . '/' . $this->name . '.rc.php', 'w+b' ) ) === false ) return OBFW_Exception(); $this->status = 2; $this->rc_offset = 0; // Only write rejection header if we want one on the rc file if ( $this->rc_header && true !== ( $ret = $this->Write_Rejection_Header( $this->rc_file ) ) ) { @fclose( $this->rc_file ); return $ret; } return true; } /*public*/ function Do_Reconstruct() { if ( $this->status == 3 ) { $name = $this->name; if ( $this->rotate_id ) $name .= '.' . $this->rotate_id; return array( 'file' => $this->prefix . '/' . $name . '.php', 'offset' => $this->rc_header ? strlen( $this->header ) : 0, 'size' => $this->offset + $this->size, ); } // Grab a block of data $length = $this->WPOnlineBackup->Get_Setting( 'max_block_size' ); if ( !is_bool( $ret = $this->Flush( $data, $length ) ) ) { @fclose( $this->rc_file ); return $ret; } $length = strlen( $data ); // Flush into the reconstruction file if ( true !== ( $ret = $this->_Try_Write( $this->rc_file, $data, $length, 'write', 'rc' ) ) ) { @fclose( $this->rc_file ); return $ret; } $this->rc_offset += $length; if ( $ret === false ) { // No more data $this->status = 3; return array( 'file' => $this->prefix . '/' . $this->name . '.rc.php', 'offset' => $this->rc_header ? strlen( $this->header ) : 0, 'size' => $this->offset + $this->size, ); } return true; } /*public*/ function End_Reconstruct() { if ( $this->rc_file !== false ) { $this->Delete( true ); @fclose( $this->rc_file ); $this->rc_file = false; } return true; } /*public*/ function Branch( & $branch ) { // Create a new disk with the same destination folder and rotation ID and return it $branch = new WPOnlineBackup_Disk( $this->WPOnlineBackup, $this->rotate_id ); $branch->Initialise( $this->prefix ); return true; } /*private*/ function Write_Rejection_Header( $file, $type = '' ) { // This simply turns the entire file into a PHP script // If anyone tries to access it through HTTP, on 99.99% of WordPress servers PHP is PHP... // it will parse the file as PHP instead of streaming it to the user // PHP 5 - __halt_compiler() cleanly aborts the compiler in the first line of the file // Users accessing the file see a blank page and no data // PHP 4 - We get a little dirty and force a Syntax Error to prevent PHP scanning the entire file // Users accessing the file see a Syntax Error or a blank page and no data // If a server returns the actual code instead of parsing it as PHP - this would already be considered a security issue $data = $this->header; $length = strlen( $data ); if ( true !== ( $ret = $this->_Try_Write( $file, $data, $length, 'write header', $type ) ) ) return $ret; return true; } /*private*/ function CleanUp_Rotated() { // Loop through rotated files foreach ( $this->rotation as $id => $rotate ) { $name = $this->name; if ( $id ) $name .= '.' . $id; // If size is 0, just delete the file if ( $rotate['size'] == 0 ) { @unlink( $this->prefix . '/' . $name . '.php' ); } else { // Open the file - ignore error we can get access violations and all kinds of crap if it timed out if ( ( $file = @fopen( $this->prefix . '/' . $name . '.php', 'r+b' ) ) === false ) continue; // Attempt to truncate the file to the correct size @ftruncate( $file, ( $rotate['has_header'] ? strlen( $this->header ) : 0 ) + $rotate['size'] ); // And close @fclose($file); } } } } ?>