/lib/ezc/Archive/src/utils/checksums.php

https://bitbucket.org/ericsagnes/ezpublish-multisite · PHP · 228 lines · 92 code · 26 blank · 110 comment · 15 complexity · 4798d2836083c402f291fa06bd46d226 MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcArchiveChecksums class.
  4. *
  5. * @package Archive
  6. * @version //autogentag//
  7. * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
  8. * @license http://ez.no/licenses/new_bsd New BSD License
  9. * @access private
  10. */
  11. /**
  12. * The ezcArchiveChecksums is a collection of checksum algorithms. The
  13. * total-byte-value checksum and CRC32 checksum are currently available.
  14. *
  15. * For each different checksum are two methods available:
  16. * - Calculate the checksum from a string.
  17. * - Calculate the checksum from a file.
  18. *
  19. * The latter will consume less memory since a part of the file is read in
  20. * memory at the time, and will be freed after use. The consequence might be
  21. * that the checksum from a string is a bit faster.
  22. *
  23. * @package Archive
  24. * @version //autogentag//
  25. * @access private
  26. */
  27. class ezcArchiveChecksums
  28. {
  29. /**
  30. * The CRC-32 lookup table.
  31. *
  32. * @var array(int)
  33. */
  34. private static $crc32Table = false;
  35. /**
  36. * Calculates the total-byte-value checksum from a string.
  37. *
  38. * Returns the total ASCII value from all characters in the data string.
  39. * Example 1: For example:
  40. *
  41. * <code>
  42. * $crc = ezcArchiveChecksums::getTotalByteValueFromFile( "abc" );
  43. * // $crc contains the value: 141 + 142 + 143 = 426
  44. * </code>
  45. *
  46. * @param string $data Character string.
  47. * @return int The total byte value.
  48. *
  49. * @see getTotalByteValueFromFile()
  50. */
  51. public static function getTotalByteValueFromString( $data )
  52. {
  53. $total = 0;
  54. $length = strlen( $data );
  55. for ( $i = 0; $i < $length; $i++ )
  56. {
  57. $total += ord( $data[$i] );
  58. }
  59. return $total;
  60. }
  61. /**
  62. * Calculates the total-byte-value checksum from a file.
  63. *
  64. * Returns the total ASCII value from all characters in the data string.
  65. * For example:
  66. *
  67. * <code>
  68. * $crc = ezcArchiveChecksums::getTotalByteValueFromFile( "abc" );
  69. * // $crc contains the value: 141 + 142 + 143 = 426
  70. * </code>
  71. *
  72. * @param string $fileName The file to use
  73. * @return int Value which contains the total byte value.
  74. */
  75. public static function getTotalByteValueFromFile( $fileName )
  76. {
  77. if ( ( $fp = fopen( $fileName, 'rb' ) ) === false )
  78. {
  79. return false;
  80. }
  81. // Perform the algorithm on each character in file
  82. $total = 0;
  83. while ( true )
  84. {
  85. $i = fread( $fp, 1 );
  86. if ( strlen( $i ) == 0 )
  87. {
  88. break;
  89. }
  90. $total += ord( $i );
  91. }
  92. fclose( $fp );
  93. return $total;
  94. }
  95. /**
  96. * Calculates the (official) CRC-32 polynomial from a $data string as input.
  97. *
  98. * @param string $data
  99. * @return int The calculated CRC-32.
  100. */
  101. public static function getCrc32FromString( $data )
  102. {
  103. return crc32( $data );
  104. }
  105. /**
  106. * Calculates the (official) CRC-32 polynomial from a file.
  107. *
  108. * This method is taken from the PHP user comments
  109. * (http://no.php.net/manual/en/function.crc32.php).
  110. *
  111. * @param string $fileName Absolute or relative path to the file.
  112. * @return int The calculated CRC-32.
  113. */
  114. public static function getCrc32FromFile( $fileName )
  115. {
  116. if ( self::$crc32Table === false )
  117. {
  118. self::crc32InitTable();
  119. }
  120. // Once the lookup table has been filled in by the two functions above,
  121. // this function creates all CRCs using only the lookup table.
  122. // You need unsigned variables because negative values
  123. // introduce high bits where zero bits are required.
  124. // PHP doesn't have unsigned integers:
  125. // I've solved this problem by doing a '&' after a '>>'.
  126. // Start out with all bits set high.
  127. $crc = 0xffffffff;
  128. // Added for issue #13517: Not possible to add directories to an archive on Windows
  129. if ( is_dir( $fileName ) )
  130. {
  131. return false;
  132. }
  133. if ( ( $fp = fopen( $fileName ,'rb' ) ) === false )
  134. {
  135. return false;
  136. }
  137. // Perform the algorithm on each character in file
  138. while ( true )
  139. {
  140. $i = fread( $fp, 1 );
  141. if ( strlen( $i ) == 0 )
  142. {
  143. break;
  144. }
  145. $crc = ( ( $crc >> 8 ) & 0x00ffffff ) ^ self::$crc32Table[( $crc & 0xFF ) ^ ord( $i )];
  146. }
  147. fclose( $fp );
  148. // Exclusive OR the result with the beginning value.
  149. return $crc ^ 0xffffffff;
  150. }
  151. /**
  152. * Initializes the CRC-32 table.
  153. *
  154. * Builds the lookup table array. This is the official polynomial used by
  155. * CRC-32 in PKZip, WinZip and Ethernet.
  156. *
  157. * This method is taken from the PHP user comments
  158. * (http://no.php.net/manual/en/function.crc32.php).
  159. */
  160. protected static function crc32InitTable()
  161. {
  162. // Builds lookup table array
  163. // This is the official polynomial used by
  164. // CRC-32 in PKZip, WinZip and Ethernet.
  165. $polynomial = 0x04c11db7;
  166. // 256 values representing ASCII character codes.
  167. for ( $i = 0; $i <= 0xFF; ++$i )
  168. {
  169. self::$crc32Table[$i] = ( self::crc32Reflect( $i, 8 ) << 24 );
  170. for ( $j = 0; $j < 8; ++$j )
  171. {
  172. self::$crc32Table[$i] = ( ( self::$crc32Table[$i] << 1 ) ^ ( ( self::$crc32Table[$i] & ( 1 << 31 ) ) ? $polynomial : 0 ) );
  173. }
  174. self::$crc32Table[$i] = self::crc32Reflect( self::$crc32Table[$i], 32 );
  175. }
  176. }
  177. /**
  178. * Reflects CRC bits in the lookup table
  179. *
  180. * This method is taken from the PHP user comments
  181. * (http://no.php.net/manual/en/function.crc32.php).
  182. *
  183. * @param int $ref
  184. * @param int $ch
  185. * @return int
  186. */
  187. protected static function crc32Reflect( $ref, $ch )
  188. {
  189. $value = 0;
  190. // Swap bit 0 for bit 7, bit 1 for bit 6, etc.
  191. for ( $i = 1; $i < ( $ch + 1 ); ++$i )
  192. {
  193. if ( $ref & 1 )
  194. {
  195. $value |= ( 1 << ( $ch - $i ) );
  196. }
  197. $ref = ( ( $ref >> 1 ) & 0x7fffffff );
  198. }
  199. return $value;
  200. }
  201. }
  202. ?>