Subversion Repositories cryptochat

Rev

Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. class DirectoryHashCalculator {
  4.         /*
  5.  
  6.         Directory Hash V3 by Daniel Marschall
  7.  
  8.         <directoryhash>      ::= SHA1(<directorycontext>)
  9.         <directorycontext>   ::= "" | <entry>
  10.         <entries>            ::= <entry> ["|" <entry>]
  11.                                  IMPORTANT: (MD5) SORTED ASCENDING!
  12.         <entry>              ::= <file_md5_hash> <filenames>
  13.         <filenames>          ::= "*" <relative_directory> <filename> [<filenames>]
  14.                                  IMPORTANT: (RelativeDir+Filename) SORTED ASCENDING!
  15.         <file_md5_hash>      ::= MD5(FILECONTENT(<relative_directory> <filename>))
  16.         <filename>           ::= given.
  17.                                  IMPORTANT: All directories (this automatically
  18.                                  excludes "", "." and "..") and non-existing resp.
  19.                                  non-readable files are not included.
  20.                                  addFile() will return false.
  21.         <relative_directory> ::= given.
  22.                                  Note: Usually, the directory is in relative diction.
  23.                                  IMPORTANT: "./" is always stripped from beginning!
  24.                                  IMPORTANT: "\" is made to "/"!
  25.  
  26.         Example:
  27.                 "" --> Empty directory
  28.                 <hash1>*<file1_with_hash1>*<file2_with_hash1>|<hash2>*<file1_with_hash2>
  29.        
  30.         */
  31.  
  32.         private $hashes;
  33.  
  34.         function __construct() {
  35.                 $this->clear();
  36.         }
  37.  
  38.         private static function makeFilenameConsistently(&$filename) {
  39.                 // Rule 1: Cut off "./" from beginning
  40.                 if (substr($filename, 0, 2) == './') {
  41.                         $filename = substr($filename, 2, strlen($filename)-2);
  42.                 }
  43.                
  44.                 // Rule 2: Use "/" instead of "\"
  45.                 $filename = str_replace('\\', '/', $filename);
  46.         }
  47.  
  48.         /*
  49.         @return
  50.                 MD5-Hash of the file or FALSE is calculation/adding
  51.                 was not successful.
  52.         */
  53.         public function addFile($file) {
  54.                 if (!file_exists($file)) return false;
  55.                 // if (!is_readable($file)) return false;
  56.                 // if (basename($file) == '') return false;
  57.                 // if (basename($file) == '.') return false;
  58.                 // if (basename($file) == '..') return false;
  59.                 self::makeFilenameConsistently($file);
  60.                 $file_md5 = md5_file($file);
  61.                 if ($file_md5 === false) return false; // Error...
  62.                 $this->hashes[$file_md5][] = $file;
  63.                 return $file_md5;
  64.         }
  65.  
  66.         public function clear() {
  67.                 $this->hashes = array();
  68.         }
  69.  
  70.         private function getDirectoryContext() {
  71.                 if (count($this->hashes) == 0) return '';
  72.                 $directory_context = '';
  73.                 // Sort md5 hashes ascending (so that the result is equal at every machine)
  74.                 ksort($this->hashes);
  75.                 foreach ($this->hashes as $hash => $filenames) {
  76.                         // Sort filenames ascending (so that the result is equal at every machine)
  77.                         sort($filenames);
  78.                         $directory_context .= $hash;   
  79.                         foreach ($filenames as $filename) {
  80.                                 $directory_context .= '*'.$filename;
  81.                         }
  82.                         $directory_context .= '|';
  83.                 }
  84.                 $directory_context = substr($directory_context, 0, strlen($directory_context)-1);
  85.                 return $directory_context;     
  86.         }
  87.  
  88.         public function calculateDirectoryHash() {
  89.                 $directory_context = $this->getDirectoryContext();
  90.                 return sha1($directory_context);
  91.         }
  92.        
  93.         function getVersionDescription() {
  94.                 return 'Marschall V3';
  95.         }
  96. }
  97.  
  98. ?>