Files
SIGE-WEB-snapshot/wp-content/plugins/all-in-one-wp-migration/lib/vendor/servmask/checksum/class-ai1wm-crc.php

203 lines
6.3 KiB
PHP

<?php
/**
* Copyright (C) 2014-2025 ServMask Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Attribution: This code is part of the All-in-One WP Migration plugin, developed by
*
* ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗
* ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝
* ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝
* ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗
* ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗
* ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
*/
if ( ! defined( 'ABSPATH' ) ) {
die( 'Kangaroos cannot jump here' );
}
class Ai1wm_Crc {
/**
* Calculate CRC32 checksum for a file
*
* @param string $file_path Path to the file
* @return string|null CRC32 checksum as hexadecimal string or null on error
*/
public static function calculate_file_crc32( $file_path ) {
if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
return null;
}
// Use hash_file for CRC32b (CRC32 with reversed bit order, more standard)
$crc = hash_file( 'crc32b', $file_path );
return $crc;
}
/**
* Verify file CRC32 checksum
*
* @param string $file_path Path to the file
* @param string $expected_crc Expected CRC32 checksum
* @return bool True if CRC matches, false otherwise
*/
public static function verify_file_crc32( $file_path, $expected_crc ) {
$calculated_crc = self::calculate_file_crc32( $file_path );
if ( $calculated_crc === null ) {
return false;
}
return strcasecmp( $calculated_crc, $expected_crc ) === 0;
}
/**
* Initialize CRC32 hash context for incremental calculation
*
* @return resource|\HashContext Hash context
*/
public static function init_crc32() {
return hash_init( 'crc32b' );
}
/**
* Update CRC32 hash with a data chunk
*
* @param resource|\HashContext $context Hash context
* @param string $data Data chunk to add
* @return void
*/
public static function update_crc32( $context, $data ) {
hash_update( $context, $data );
}
/**
* Finalize CRC32 calculation and return result
*
* @param resource|\HashContext $context Hash context
* @return string CRC32 checksum as hexadecimal string
*/
public static function finalize_crc32( $context ) {
return hash_final( $context );
}
/**
* Combine two CRC32 checksums
*
* This method mathematically combines two CRC32 values, allowing resumable
* CRC calculation across multiple processing cycles (e.g., handling timeouts).
*
* Based on zlib's crc32_combine algorithm using GF(2) polynomial arithmetic.
*
* @param string $crc1_hex CRC32 of first data block (hex string)
* @param string $crc2_hex CRC32 of second data block (hex string)
* @param int $len2 Length of second data block in bytes
* @return string Combined CRC32 checksum as hexadecimal string
*/
public static function combine_crc32( $crc1_hex, $crc2_hex, $len2 ) {
// CRC32 polynomial (reversed)
$poly = 0xEDB88320;
// Convert hex strings to integers
$crc1 = hexdec( $crc1_hex );
$crc2 = hexdec( $crc2_hex );
// If second block is empty, return first CRC unchanged
if ( $len2 === 0 ) {
return sprintf( '%08x', $crc1 );
}
// Build operator matrix for x^n where n = len2 * 8
// This represents multiplication by x^(8*len2) mod poly
$even = array_fill( 0, 32, 0 );
$even[0] = $poly;
$row = 1;
for ( $n = 1; $n < 32; $n++ ) {
$even[ $n ] = $row;
$row = $row << 1;
}
// Square to get x^2, x^4, x^8, etc.
$odd = array_fill( 0, 32, 0 );
self::gf2_matrix_square( $odd, $even );
self::gf2_matrix_square( $even, $odd );
// Apply len2 zeros to crc1 by repeatedly squaring and applying
do {
// Apply zeros operator for this bit of len2
self::gf2_matrix_square( $odd, $even );
if ( $len2 & 1 ) {
$crc1 = self::gf2_matrix_times( $odd, $crc1 );
}
$len2 >>= 1;
// If no more bits, we're done
if ( $len2 === 0 ) {
break;
}
// Square again for next bit
self::gf2_matrix_square( $even, $odd );
if ( $len2 & 1 ) {
$crc1 = self::gf2_matrix_times( $even, $crc1 );
}
$len2 >>= 1;
} while ( $len2 !== 0 );
// Combine the two CRCs
$crc1 ^= $crc2;
return sprintf( '%08x', $crc1 );
}
/**
* Matrix multiplication in GF(2)
*
* @param array $mat Matrix
* @param int $vec Vector
* @return int Result
*/
private static function gf2_matrix_times( $mat, $vec ) {
$sum = 0;
$mat_index = 0;
while ( $vec ) {
if ( $vec & 1 ) {
$sum ^= $mat[ $mat_index ];
}
$vec = ( $vec >> 1 ) & 0x7FFFFFFF;
$mat_index++;
}
return $sum;
}
/**
* Square a matrix in GF(2)
*
* @param array $square Result matrix (passed by reference)
* @param array $mat Input matrix
* @return void
*/
private static function gf2_matrix_square( &$square, $mat ) {
for ( $n = 0; $n < 32; $n++ ) {
$square[ $n ] = self::gf2_matrix_times( $mat, $mat[ $n ] );
}
}
}