MD 5 cheksum файлов

Статус
В этой теме нельзя размещать новые ответы.

Tycoon

Постоялец
Регистрация
20 Апр 2006
Сообщения
77
Реакции
36
написал скрипт который отслеживает изменения в заданных файлах, которые находятся в md5_log/file.list


список файлов :
T:/home/server/www/spy2.php
T:/home/server/www/spy.php
T:/home/server/www/fs.php
T:/home/server/www/scan_dir.php
T:/home/server/www/chekmd5.php
T:/home/server/www/md5.php



PHP:
////////////////////////////////// 
$arr = file("md5_log/file.list"); // чита в массив список файлов 
foreach ($arr as $value) 
{ 

   echo "File $value  <br>";  // обпрабатываю их в цикле, хочу получить все значения 


///////////////////////////////////// 
$files = $value; // записываю все значения в новую перменную 
/********************** сравниваю           *******************************/ 
    $file_md5 = "md5_log/md5.hash"; // 
$md5_new_file = trim(@md5_file($files)); 
$md5_old_file = trim(file_get_contents($file_md5)); 

if ($md5_new_file <> $md5_old_file) 
{ 
    echo "Файл был изменен"; 
    rename($file_md5, $file_md5 . ".bak"); 
    $fp = fopen($file_md5, 'w'); 
    fwrite($fp, $md5_new_file); 
    fclose($fp); 
    ///////////////// crontab 

    $message = "В последний раз файл <br>" . $files . " был изменен: " . date("d-Y-H:i:s.", 
        @filemtime($files)) . " MD5 файла: " . @md5_file($files) . " Размер файла: " . @ 
        filesize($files) . " байт"; 

    echo ("<br>Информация об измененных файлах отправлена на емайл: <br> " . $files . 
        "<br>"); 
    @mail('noreply@bk.ru', 
        'Сообщение об изменение МД5 суммы файлов на сервере : http://' . $_SERVER['SERVER_NAME'] . 
        $value, $message); 

    //////////////////////////////////////////////////////////////// 
    unlink($file_md5 . ".bak"); 
} 

// 
else 
{ 
    echo "Ничего не изменилось"; 
} 
}

проблема в том что когда делаю
print "<pre>" ;
print_r($arr);


распечатывается:

Array
(
[0] => T:/home/server/www/spy2.php

[1] => T:/home/server/www/spy.php

[2] => T:/home/server/www/fs.php

[3] => T:/home/server/www/scan_dir.php

[4] => T:/home/server/www/chekmd5.php

[5] => T:/home/server/www/md5.php
)
Файл был изменен
Информация об измененных файлах отправлена на емайл:
T:/home/server/www/spy2.php

Array
(
[0] => T:/home/server/www/spy2.php

[1] => T:/home/server/www/spy.php

[2] => T:/home/server/www/fs.php

[3] => T:/home/server/www/scan_dir.php

[4] => T:/home/server/www/chekmd5.php

[5] => T:/home/server/www/md5.php
)
Ничего не изменилось

Array
(
[0] => T:/home/server/www/spy2.php

[1] => T:/home/server/www/spy.php

[2] => T:/home/server/www/fs.php

[3] => T:/home/server/www/scan_dir.php

[4] => T:/home/server/www/chekmd5.php

[5] => T:/home/server/www/md5.php
)
Ничего не изменилось

Array
(
[0] => T:/home/server/www/spy2.php

[1] => T:/home/server/www/spy.php

[2] => T:/home/server/www/fs.php

[3] => T:/home/server/www/scan_dir.php

[4] => T:/home/server/www/chekmd5.php

[5] => T:/home/server/www/md5.php
)
Ничего не изменилось

Array
(
[0] => T:/home/server/www/spy2.php

[1] => T:/home/server/www/spy.php

[2] => T:/home/server/www/fs.php

[3] => T:/home/server/www/scan_dir.php

[4] => T:/home/server/www/chekmd5.php

[5] => T:/home/server/www/md5.php
)
Ничего не изменилось

Array
(
[0] => T:/home/server/www/spy2.php

[1] => T:/home/server/www/spy.php

[2] => T:/home/server/www/fs.php

[3] => T:/home/server/www/scan_dir.php

[4] => T:/home/server/www/chekmd5.php

[5] => T:/home/server/www/md5.php
)
Файл был изменен
Информация об измененных файлах отправлена на емайл:
T:/home/server/www/md5.php


изменения были тока в 1 файле : T:/home/server/www/md5.php , но почему то первый файл в списке


Файл был изменен
Информация об измененных файлах отправлена на емайл:
T:/home/server/www/spy2.php


сообщается что он тоже был изменен а на самом деле он не был изменен, и если я изменю други файлы из списка , сообщение и емайла нету о том что они были изменены....
 
для каждого из файлов вы рассчитываете md5, но сравниваете с одной и той же md5, взятой из файла:

PHP:
$file_md5 = "md5_log/md5.hash";

Сделайте так:

PHP:
$file_md5 = "md5_log/" . $files . ".md5.hash";
 
для каждого из файлов вы рассчитываете md5, но сравниваете с одной и той же md5, взятой из файла:

PHP:
$file_md5 = "md5_log/md5.hash";
Сделайте так:

PHP:
$file_md5 = "md5_log/" . $files . ".md5.hash";

Я теперь пробую записать МД5 всех файлов, но все равно скрипт отсылат 1 сообщение 6 раз об изменении 1 файла, а точнее менно того который я запускаю с этим кодом, вот я добавил МД5 для всех фалов но ечть ошибка я не могу паноять где именно

PHP:
 ////////////////////////////////// 
$arr = file("md5_log/file.list"); 
foreach ($arr as $files) 
{ 

echo "File $files  <br>"; 
 $fp1 = fopen("md5_log/md5.hash", 'w+');  
    foreach ($arr as $value) 
   
   { 
        $files = trim($value); 
        fwrite($fp1, md5_file($files) . "\n"); // записываю хеши  фалов из списка$arr
 
    
 }   fclose($fp1); 



$file_md5 = file("md5_log/md5.hash");  //считываю их в массив

// 
$md5_new_file = @md5_file($files); 
$md5_old_file = file_get_contents($file_md5); 

if ($md5_new_file <> $md5_old_file) 
{ 
    echo "Файл был изменен"; 
    rename($file_md5, $file_md5 . ".bak"); 
    $fp = fopen($file_md5, 'w'); 
    fwrite($fp, $md5_new_file); 
    fclose($fp); 
    ///////////////// crontab 

    $message = "В последний раз файл <br>" . $files . " был изменен: " . date("d-Y-H:i:s.", 
        @filemtime($files)) . " MD5 файла: " . @md5_file($files) . " Размер файла: " . @ 
        filesize($files) . " байт"; 

    echo ("<br>Информация об измененных файлах отправлена на емайл: <br> " . $files . 
        "<br>"); 
    @mail('noreply@bk.ru', 
        'Сообщение об изменение МД5 суммы файлов на сервере : http://' . $_SERVER['SERVER_NAME'] . 
        $value, $message); 

    //////////////////////////////////////////////////////////////// 
    unlink($file_md5 . ".bak"); 
} 

// 
else 
{ 
    echo "Ничего не изменилось"; 
} 

}
 
1) не следует использовать цикл в цикле, сбивается внутренний указатель массива:

PHP:
foreach ($arr as $files) 
{ 
...
    foreach ($arr as $value)
...

2) переменная, определенная внутри вложенного цикла,

PHP:
$files = trim($value);

используется далее вне этого цикла (содержит значение, присвоенное в последнем цикле, надо ли оно?)

Лучше переписать код заново, используя следующий алгоритм. В file.list храним полный путь к файлам, по которым контролируем контр.сумму. В md5.hash храним имена файлов и контрольные суммы через ':', например:

Код:
/usr/www/index.php:23424234dfe78ed87
/usr/www/index.html:596890834908d989f

Реализация может быть, например, такой:
PHP:
$filename_filelist = 'md5_log/file.list';
$filename_md5hash = 'md5_log/md5.hash';
$arr = file($filename_filelist); 
$arr_tmp = file($filename_md5hash);
$arr_md5 = array();
// считываем md5.hash в ассоц.массив
foreach ($arr_tmp as $fileAndmd5) { 
  $aRow = explode(':', trim($fileAndmd5));
  if (sizeof($aRow) == 2) {
    $arr_md5[trim($aRow[0])] = trim($aRow[1]); // пара Имя файла -> md5
  }
}

//проход по именам файлов и проверка md5
$md5_changed = false;
foreach ($arr as $value) { 
  $curfile = trim($value);
  if (file_exists($curfile)) {
    $md5_org = $arr_md5[$curfile];
    if (strlen($md5_org) > 0) {
      // контр сумма для текущего файла уже подсчитана - проверим
      $md5_curfile = @md5_file($curfile); 
      if ($md5_org != $md5_curfile) {
        $message = "В последний раз файл <br>" . $curfile . " был изменен: " . date("d-Y-H:i:s.", 
        @filemtime($curfile)) . " MD5 файла: " . @md5_file($curfile) . " Размер файла: " . @filesize($curfile) . " байт"; 
    echo ("<br>Информация об измененных файлах отправлена на емайл: <br> " . $curfile . 
        "<br>"); 
    @mail('noreply@bk.ru', 
        'Сообщение об изменение МД5 суммы файлов на сервере : http://' . $_SERVER['SERVER_NAME'] . 
        $cur_file, $message); 
        // запомним новую md5
        $arr_md5[$curfile] = $md5_curfile;
        $md5_changed = true;
      }
    } else {
      // для этого файла md5 еще не рассчитывалась
      $arr_md5[$curfile] = $md5_curfile;
      $md5_changed = true;
    }
  }
}
if ($md5_changed) {
  // записываем в файл md5.hash измененный ассоц массив
  rename($filename_md5hash, $filename_md5hash . '.bak');
  $fp = fopen($filename_md5hash, 'w'); 
  foreach($arr_md5 as $curfile => $curmd5) {
    fwrite($fp, "$curfile:$curmd5\n"); 
  }
  fclose($fp); 
  unlink($filename_md5hash . '.bak');
}
 
PHP:
<?php
/**
 *Класс для проверки изменений файлов передается имя файла содержащего
 *список файлов, каждый файл на новой строке
 */
class md5_check{
    /**
     * сообщение об ошибках
     *@var string
     */
    protected $Error = '';    
    function __construct($fileMask){
      if(!file_exists($fileMask)){$this->Error="Отсутствует шаблон";}
     else{
     $arrayFiles = file($fileMask);
      foreach($arrayFiles as $file){
	  $file = trim($file);
	  $fileMD5 = $file.".md5";//здесб если md5 файлы храняться в другой папке можно дописать изменения пути
	  if(file_exists($file)){//если файл существует
	    if(!file_exists($fileMD5)){//если не существует md5 файл
		$this->Errors .= "Отсутствует файл $file.$fileMD5 \r\n";
		file_put_contents($fileMD5,md5_file($file));
	    }
	    else{
		if(file_get_contents($fileMD5) != md5_file($file))
		{
		     $this->Errors .= "Файл \"$file\" был изменен ".date("d-Y-H:i:s.",filemtime($file))."\r\n";
		     file_put_contents($fileMD5,md5_file($file));
		}
	    }
	  }
	  else{
		$this->Errors .= "Отсутствует файл $file\r\n";
	  }
      }
      if($this->Errors != ''){//если были ошибки то выполняется
	    echo $this->Errors;
      }
     }
    }
}
 
1) не следует использовать цикл в цикле, сбивается внутренний указатель массива:

PHP:
foreach ($arr as $files) 
{ 
...
    foreach ($arr as $value)
...
2) переменная, определенная внутри вложенного цикла,

PHP:
$files = trim($value);
используется далее вне этого цикла (содержит значение, присвоенное в последнем цикле, надо ли оно?)

Лучше переписать код заново, используя следующий алгоритм. В file.list храним полный путь к файлам, по которым контролируем контр.сумму. В md5.hash храним имена файлов и контрольные суммы через ':', например:

Код:
/usr/www/index.php:23424234dfe78ed87
/usr/www/index.html:596890834908d989f
Реализация может быть, например, такой:
PHP:
$filename_filelist = 'md5_log/file.list';
$filename_md5hash = 'md5_log/md5.hash';
$arr = file($filename_filelist); 
$arr_tmp = file($filename_md5hash);
$arr_md5 = array();
// считываем md5.hash в ассоц.массив
foreach ($arr_tmp as $fileAndmd5) { 
  $aRow = explode(':', trim($fileAndmd5));
  if (sizeof($aRow) == 2) {
    $arr_md5[trim($aRow[0])] = trim($aRow[1]); // пара Имя файла -> md5
  }
}

//проход по именам файлов и проверка md5
$md5_changed = false;
foreach ($arr as $value) { 
  $curfile = trim($value);
  if (file_exists($curfile)) {
    $md5_org = $arr_md5[$curfile];
    if (strlen($md5_org) > 0) {
      // контр сумма для текущего файла уже подсчитана - проверим
      $md5_curfile = @md5_file($curfile); 
      if ($md5_org != $md5_curfile) {
        $message = "В последний раз файл <br>" . $curfile . " был изменен: " . date("d-Y-H:i:s.", 
        @filemtime($curfile)) . " MD5 файла: " . @md5_file($curfile) . " Размер файла: " . @filesize($curfile) . " байт"; 
    echo ("<br>Информация об измененных файлах отправлена на емайл: <br> " . $curfile . 
        "<br>"); 
    @mail('noreply@bk.ru', 
        'Сообщение об изменение МД5 суммы файлов на сервере : http://' . $_SERVER['SERVER_NAME'] . 
        $cur_file, $message); 
        // запомним новую md5
        $arr_md5[$curfile] = $md5_curfile;
        $md5_changed = true;
      }
    } else {
      // для этого файла md5 еще не рассчитывалась
      $arr_md5[$curfile] = $md5_curfile;
      $md5_changed = true;
    }
  }
}
if ($md5_changed) {
  // записываем в файл md5.hash измененный ассоц массив
  rename($filename_md5hash, $filename_md5hash . '.bak');
  $fp = fopen($filename_md5hash, 'w'); 
  foreach($arr_md5 as $curfile => $curmd5) {
    fwrite($fp, "$curfile:$curmd5\n"); 
  }
  fclose($fp); 
  unlink($filename_md5hash . '.bak');
}

Почемуто в файл хешей записывается в таком виде
HTML:
T:/home/v-nedv/www/robert.php:
T:/home/v-nedv/www/md5.php:
а Мд5 не записывается

я сделал так:

PHP:
 <?php

$filename_filelist = 'md5_log/file.list';

$arr = file($filename_filelist); 
print "<pre>";
print_r($arr);
 

 $fp1 = fopen("md5_log/md5.hash", 'w'); // записываю в хеш файл файл:МД5
    foreach ($arr as $value)
    {
        $files = trim($value);
        fwrite($fp1, $files . ":" . md5_file($files) . "\n");

    }
    fclose($fp1);
    
$filename_md5hash  = file ('md5_log/md5.hash');    


    
/////////////////////////////////
$arr_tmp = $filename_md5hash ;

print "<pre>"; // тут получаю 
Array
(
    [0] => T:/home/v-nedv/www/robert.php:d6949cefad9162333a218d09a552b084

    [1] => T:/home/v-nedv/www/md.php:1605df3d7439cd267eb6a74e1ea66f40

)
print_r($arr_tmp);

//$arr_tmp = file($filename_md5hash);
$arr_md5 = array();


// считываем md5.hash в ассоц.массив
foreach ($arr_tmp as $fileAndmd5) { 
  $aRow = explode(':', trim($fileAndmd5));
  
  if (sizeof($aRow) == 2) {
    $arr_md5[trim($aRow[0])] = trim($aRow[1]); // пара Имя файла -> md5
  }
    
}



//проход по именам файлов и проверка md5
$md5_changed = false;
foreach ($arr as $value) { 
  $curfile = trim($value);
  if (file_exists($curfile)) {
    $md5_org = $arr_md5[$curfile];
    if (strlen($md5_org) > 0) {
      // контр сумма для текущего файла уже подсчитана - проверим
      $md5_curfile = @md5_file($curfile); 
      if ($md5_org != $md5_curfile) {
        $message = "В последний раз файл <br>" . $curfile . " был изменен: " . date("d-Y-H:i:s.", 
        @filemtime($curfile)) . " MD5 файла: " . @md5_file($curfile) . " Размер файла: " . @filesize($curfile) . " байт"; 
    echo ("<br>Информация об измененных файлах отправлена на емайл: <br> " . $curfile . 
        "<br>"); 
    @mail('noreply@bk.ru', 
        'Сообщение об изменение МД5 суммы файлов на сервере : http://' . $_SERVER['SERVER_NAME'] . 
        $cur_file, $message); 
        // запомним новую md5
        $arr_md5[$curfile] = $md5_curfile;
        $md5_changed = true;
      }
    } else {
      // для этого файла md5 еще не рассчитывалась
      $arr_md5[$curfile] = $md5_curfile;
      $md5_changed = true;
    }
  }
}
if ($md5_changed) {
  // записываем в файл md5.hash измененный ассоц массив
  rename($filename_md5hash, $filename_md5hash . '.bak');
  $fp = fopen($filename_md5hash, 'w'); 
  foreach($arr_md5 as $curfile => $curmd5) {
    fwrite($fp, "$curfile:$curmd5\n"); 
  }
  fclose($fp); 
  unlink($filename_md5hash . '.bak');
}  

?>

скрипт выдает
HTML:
Warning:  rename() expects parameter 1 to be string, array given in T:\home\site\www\md.php on line 80



Warning:  fopen() expects parameter 1 to be string, array given in T:\home\site
\www\md.php on line 81



Warning:  fwrite(): supplied argument is not a valid stream resource in T:\home\site
\www\md.php on line 83



Warning:  fwrite(): supplied argument is not a valid stream resource in T:\home\site
\www\md.php on line 83



Warning:  fclose(): supplied argument is not a valid stream resource in T:\home\site
\www\md.php on line 85



Warning:  unlink(Array.bak) [function.unlink]: No such file or directory in T:\home\site
\www\md.php on line 86
 
нашел ошибку:
PHP:
    $md5_curfile = @md5_file($curfile);
надо вынести из if вверх

С учетом исправления код выглядит так:
PHP:
$filename_filelist = 'md5_log/file.list';
$filename_md5hash = 'md5_log/md5.hash';
$arr = file($filename_filelist); 
$arr_tmp = file($filename_md5hash);
$arr_md5 = array();
// считываем md5.hash в ассоц.массив
foreach ($arr_tmp as $fileAndmd5) { 
  $aRow = explode(':', trim($fileAndmd5));
  if (sizeof($aRow) == 2) {
    $arr_md5[trim($aRow[0])] = trim($aRow[1]); // пара Имя файла -> md5
  }
}

//проход по именам файлов и проверка md5
$md5_changed = false;
foreach ($arr as $value) { 
  $curfile = trim($value);
  if (file_exists($curfile)) {
    $md5_org = $arr_md5[$curfile];
    $md5_curfile = @md5_file($curfile); 
    if (strlen($md5_org) > 0) {
      // контр сумма для текущего файла уже подсчитана - проверим
      if ($md5_org != $md5_curfile) {
        $message = "В последний раз файл <br>" . $curfile . " был изменен: " . date("d-Y-H:i:s.", 
        @filemtime($curfile)) . " MD5 файла: " . @md5_file($curfile) . " Размер файла: " . @filesize($curfile) . " байт"; 
    echo ("<br>Информация об измененных файлах отправлена на емайл: <br> " . $curfile . 
        "<br>"); 
    @mail('noreply@bk.ru', 
        'Сообщение об изменение МД5 суммы файлов на сервере : http://' . $_SERVER['SERVER_NAME'] . 
        $cur_file, $message); 
        // запомним новую md5
        $arr_md5[$curfile] = $md5_curfile;
        $md5_changed = true;
      }
    } else {
      // для этого файла md5 еще не рассчитывалась
      $arr_md5[$curfile] = $md5_curfile;
      $md5_changed = true;
    }
  }
}
if ($md5_changed) {
  // записываем в файл md5.hash измененный ассоц массив
  rename($filename_md5hash, $filename_md5hash . '.bak');
  $fp = fopen($filename_md5hash, 'w'); 
  foreach($arr_md5 as $curfile => $curmd5) {
    fwrite($fp, "$curfile:$curmd5\n"); 
  }
  fclose($fp); 
  unlink($filename_md5hash . '.bak');
}
 
спасибо, но сейчас если файл был изменен, мне кажется что условие // контр сумма для текущего файла уже подсчитана - проверим
if ($md5_org != $md5_curfile) не срабатывает, т.е никаких сообщений не приходити не выводится, не мог бы подсказать в чем дело?
 
вот это место:

PHP:
$filename_md5hash  = file ('md5_log/md5.hash');    
/////////////////////////////////
$arr_tmp = $filename_md5hash ;
надо заменить на:

PHP:
$filename_md5hash  = 'md5_log/md5.hash';
/////////////////////////////////
$arr_tmp = file($filename_md5hash);

Добавлено через 5 минут
спасибо, но сейчас если файл был изменен, мне кажется что условие // контр сумма для текущего файла уже подсчитана - проверим
if ($md5_org != $md5_curfile) не срабатывает, т.е никаких сообщений не приходити не выводится, не мог бы подсказать в чем дело?

а если добавить вывод перед проверкой?:
PHP:
echo "curfile=$curfile md5_org=$md5_org md5_curfile=$md5_curfile<br>";
 
вот это место:

PHP:
$filename_md5hash  = file ('md5_log/md5.hash');    
/////////////////////////////////
$arr_tmp = $filename_md5hash ;
надо заменить на:

PHP:
$filename_md5hash  = 'md5_log/md5.hash';
/////////////////////////////////
$arr_tmp = file($filename_md5hash);
Добавлено через 5 минут


а если добавить вывод перед проверкой?:
PHP:
echo "curfile=$curfile md5_org=$md5_org md5_curfile=$md5_curfile<br>";

белый экран выводится, ничего не выводит, насчет замены не очень понял т.к. ты же сам писал $filename_filelist = 'md5_log/file.list';
$filename_md5hash = 'md5_log/md5.hash';
$arr = file($filename_filelist);
$arr_tmp = file($filename_md5hash);
$arr_md5 = array();
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху