PHP File Synchronisation

File Synchronisation

<?php
error_reporting(63);
/***************************************
** Title........: File Synchronisation
** Filename.....: file.synchronisation.php
** Author.......: Richard Heyes
** Version......: 1.0
** Notes........:
** Last changed.: 21/4/2000
** Last change..:
***************************************/

/***************************************
** Source and destination directories.
***************************************/
        $src_dir = 'dira/';
        $dest_dir = 'dirb/';

/***************************************
** Directory deletion method.
**
** 1 - Uses php rmdir() function. Since
**     this cannot delete non-empty
**     directories, the script uses
**     recursive function calling to enter
**     the directory and delete the contents.
** 2 - Uses operating systems directory
**     delete method. ie. On win32 this
**     would be deltree /Y whilst on unix
**     this could be rm -Rfd. Using this
**     method will make the logfile inaccurate
**     as the script cannot track what is
**     in the directory before it is deleted.
**     Also, directory deleteion will not be
**     confirmed.
**
** Obviously the command you choose to use
** needs to be set in $del_cmd if using
** dir_del mode 2.
***************************************/
        $dir_del = 1;
        $dir_cmd = 'deltree /Y';

/***************************************
** Logfile mode:
**
** 0 - No log is created.
** 1 - Create new log every time, (deletes
**     previous log).
** 2 - Append to same log every time.
** 3 - Create new log every day,
**     multiple runs on the same day
**     are appended to the same log.
**     Lognames MUST contain the following
**     expressions which will be expanded
**     out:
**     DD - Day
**     MM - Month
**     YY - Year (short) OR:
**     YYYY - Year (long)
** 4 - Append to same log until logfile
**     reaches a certain size defined by
**     $logsize (kilobytes). Capital X's
**     are used in the logfile name and are
**     replaced by an incrementing number.
**
***************************************/
        $logmode = 2;
        $logsize = 0;
        $logfile_path = '';
        $logfile = 'logfile.log';

/***************************************
** Set up the initial entries to go thru.
** And zero the totals.
***************************************/
        $directories = array();
        $directories[] = array('src' => $src_dir,
                               'dest' => $dest_dir);

        (int)$directories_del = 0;
        (int)$directories_made = 0;
        (int)$files_del = 0;
        (int)$files_copied = 0;
        (int)$data_size = 0;

        $log_date = array();
        $log_type = array();
        $log_file = array();
        $log_actions = array();

/***************************************
** Padding function to make all the logfile
** entries the same length. Nice.
***************************************/
        function padding(&$array, $character, $length = 0){
                if(count($array) == 0) return;
                $longest = 0;
                for($i=0; $i<count($array); $i++){
                        if(strlen($array[$i]) > strlen($array[$longest])) $longest = $i;
                }

                if($length == 0) $length = strlen($array[$longest]);

                for($i=0; $i<count($array); $i++){
                        $padding = $length - strlen($array[$i]);
                        for($j=0; $j<$padding; $j++){
                                $array[$i] .= $character;
                        }
                }
        }

/***************************************
** Check if files exist in dest directory,
** also check if the files in the source
** need copying due to being more recent.
***************************************/
        function forward($src_dir, $dest_dir, &$directories){

                global $directories_made, $files_copied;
                global $log_date, $log_type, $log_file, $log_actions;
                global $data_size;

                $dh = opendir($src_dir);
                while($file = readdir($dh)){
                        if($file == '.' OR $file == '..') continue;
                        if(is_dir($src_dir.$file) == TRUE){
                                if(!file_exists($dest_dir.$file)){
                                        if(mkdir($dest_dir.$file, 0777) == TRUE){;
                                                $directories_made++;
                                                $log_date[] = date('H:i d/m/Y', time());
                                                $log_type[] = 'Directory';
                                                $log_file[] = $dest_dir.$file;
                                                $log_actions[] = 'Created';
                                        }
                                }
                                $directories[] = array('src' => $src_dir.$file.'/',
                                                       'dest' => $dest_dir.$file.'/');
                                continue;
                        }
                        if(!file_exists($dest_dir.$file) OR filemtime($src_dir.$file) > filemtime($dest_dir.$file)){
                                if(copy($src_dir.$file, $dest_dir.$file) == TRUE){
                                        $files_copied++;
                                        $log_date[] = date('H:i d/m/Y', time());
                                        $log_type[] = 'File';
                                        $log_file[] = $src_dir.$file;
                                        $log_actions[] = 'Copied to: '.$dest_dir.$file;
                                        $data_size += filesize($src_dir.$file);
                                }else{
                                        $files_copied++;
                                        $log_date[] = date('H:i d/m/Y', time());
                                        $log_type[] = 'File';
                                        $log_file[] = $src_dir.$file;
                                        $log_actions[] = 'Copy failed.';
                                }
                        }
                }
                closedir($dh);
        }

/***************************************
** Reverse file existence checking.
***************************************/
        function reverse($src_dir, $dest_dir){
                global $directories_del, $files_del;
                global $log_date, $log_type, $log_file, $log_actions;
                global $dir_del, $dir_cmd;

                $dh = opendir($dest_dir);
                while($file = readdir($dh)){
                        if($file == '.' OR $file == '..') continue;
                        if(file_exists($src_dir.$file) == FALSE){
                                if(is_dir($dest_dir.$file) == TRUE){
                                        if($dir_del == 2){
                                                exec($dir_cmd.' '.$dest_dir.$file);
                                                $directories_del++;
                                                $log_date[] = date('H:i d/m/Y', time());
                                                $log_type[] = 'Directory';
                                                $log_file[] = $dest_dir.$file;
                                                $log_actions[] = 'Deleted';
                                        }elseif($dir_del == 1){
                                                reverse($src_dir.$file.'/', $dest_dir.$file.'/');
                                                if(rmdir($dest_dir.$file) != 0){
                                                        $directories_del++;
                                                        $log_date[] = date('H:i d/m/Y', time());
                                                        $log_type[] = 'Directory';
                                                        $log_file[] = $dest_dir.$file;
                                                        $log_actions[] = 'Deleted';
                                                }else{
                                                        $directories_del++;
                                                        $log_date[] = date('H:i d/m/Y', time());
                                                        $log_type[] = 'Directory';
                                                        $log_file[] = $dest_dir.$file;
                                                        $log_actions[] = 'Failed to delete';
                                                }
                                        }else{
                                                die('Invalid directory deletion mode.');
                                        }
                                }else{
                                        if(unlink($dest_dir.$file) != FALSE){
                                                $files_del++;
                                                $log_date[] = date('H:i d/m/Y', time());
                                                $log_type[] = 'File';
                                                $log_file[] = $dest_dir.$file;
                                                $log_actions[] = 'Deleted';
                                        }else{
                                                $files_del++;
                                                $log_date[] = date('H:i d/m/Y', time());
                                                $log_type[] = 'File';
                                                $log_file[] = $dest_dir.$file;
                                                $log_actions[] = 'Failed to delete';
                                        }
                                }
                        }
                }
                closedir($dh);
        }

/***************************************
** Loop through each entry in $directories.
** Directories may be added to $directories
** during the forward() function, therefore
** causing it to recurse through subdirectories.
***************************************/
        for($i=0; $i<count($directories); $i++){
                forward($directories[$i]['src'], $directories[$i]['dest'], $directories);
                reverse($directories[$i]['src'], $directories[$i]['dest']);
        }

/***************************************
** Create the logfile.
***************************************/
        switch($logmode){
                case 0:
                        exit;
                case 1:
                        @unlink($logfile_path.$logfile);
                        break;
                case 2:
                        break;
                case 3:
                        $logfile = ereg_replace('DD', date('d',time()), $logfile);
                        $logfile = ereg_replace('MM', date('m', time()), $logfile);
                        if(ereg('YYYY',$logfile) == TRUE) $logfile = ereg_replace('YYYY', date('Y', time()), $logfile);
                        elseif(ereg('YY',$logfile) == TRUE) $logfile = ereg_replace('YY', date('y', time()), $logfile);
                        break;
                case 4:
                        if(ereg('(X+)', $logfile, $matches)){
                                $i = 1;
                                while(file_exists($logfile_path.ereg_replace('(X){'.strlen($matches[1]).'}', sprintf('%0'.strlen($matches[1]).'d', $i), $logfile))){
                                        if(filesize($logfile_path.ereg_replace('(X){'.strlen($matches[1]).'}', sprintf('%0'.strlen($matches[1]).'d', $i), $logfile)) < ($logsize * 1024)){
                                                break;
                                        }
                                        $i++;
                                }
                                $logfile = ereg_replace('(X){'.strlen($matches[1]).'}', sprintf('%0'.strlen($matches[1]).'d', $i), $logfile);
                        }else{
                                die('Invalid logfile name: '.$logfile);
                        }
                        break;
                default:
                        die('Invalid logmode');
                        break;
        }

        $data_size = ($data_size > 1048576) ? sprintf('%01.2d',(($data_size/1024)/1024)).'Mb' : sprintf('%1.2d',($data_size/1024)).'Kb';

        error_log('File synchronisation logfile for: '.date('l jS F Y (H:i)', time())."\r\n\r\n",3,$logfile_path.$logfile);
        error_log('Directories created..: '.$directories_made."\r\n",3,$logfile_path.$logfile);
        error_log('Files copied.........: '.$files_copied."\r\n",3,$logfile_path.$logfile);
        error_log('Directories deleted..: '.$directories_del."\r\n",3,$logfile_path.$logfile);
        error_log('Files deleted........: '.$files_del."\r\n",3,$logfile_path.$logfile);
        error_log('Total data copied....: '.$data_size."\r\n\r\n",3,$logfile_path.$logfile);


        padding($log_type, ' ');
        padding($log_file, ' ');

        for($i=0; $i<count($log_date); $i++){
                error_log($log_date[$i].'  '.$log_type[$i].' '.$log_file[$i].' '.$log_actions[$i]."\r\n",3,$logfile_path.$logfile);
        }

        error_log("\r\n\r\n",3,$logfile_path.$logfile);

?>