我正在尝试在我的服务器上从PHP 5.2.x升级到5.3.2。问题是,我依赖于PHP的ezmlm_hash()的破解实现(这里列出了错误:http://bugs.php.net/bug.php?id=47969)。
我的第一个想法是用PHP自己重写破解版本的本机PHP函数(用C语言编写)并在我的代码中使用它,而不是修改PHP源代码并且必须从源代码编译PHP。 / p>
以下是代码的C版本:
PHP_FUNCTION(ezmlm_hash)
{
char *str = NULL;
unsigned int h = 5381L;
int j, str_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&str, &str_len) == FAILURE) {
return;
}
for (j = 0; j < str_len; j++) {
h = (h + (h << 5)) ^ (unsigned long) (unsigned char) tolower(str[j]);
}
h = (h % 53);
RETURN_LONG((int) h);
}
这是我用PHP编写的内容:
function ezmlm_hash_mine($email_address){
$h = 5381;
$email_length = strlen($email_address);
for($x=0;$x<$email_length;$x++){
$chr = strtolower($email_address[$x]);
$h = ($h + ($h << 5)) ^ ( ord($chr) );
}
$h = $h % 53;
return $h;
}
我正在使用64位计算机。这两个函数输出不同的结果:
$email_addresses = array(
'test@example.com',
'mike@example.com',
);
print('<PRE>');
foreach($email_addresses as $email_address){
print(ezmlm_hash($email_address).PHP_EOL);
print(ezmlm_hash_mine($email_address).PHP_EOL.PHP_EOL);
}
输出:
23
-52
15
-21
我知道我可能有一些精确或打字问题,我只是不确定如何解决它。任何帮助将不胜感激!
更新
当我在32位机器上运行代码时,它们都输出新的校正值:
12
12
45
45
我认为这与模运算符有关...有没有人知道C模运算符的PHP等价物? PHP中的%表现不同!
更新2
似乎这对于vanilla PHP是不可能的,因为它的浮点运算没有足够的精度和奇怪的。我将不得不安装BCMath或GMP。感谢大家的见解。
答案 0 :(得分:1)
计算后尝试将此EDIT截断为32位:
function ezmlm_hash_mine($email_address){
$h = gmp_init(5381);
$d = gmp_setbit(0, 64);
$d32 = gmp_setbit(0, 32);
$email_length = strlen($email_address);
$chr = strtolower($email_address);
for($x=0;$x<$email_length;$x++){
$h = gmp_mod(gmp_xor(gmp_mod(gmp_add($h, gmp_mod(gmp_mul($h, "32"), $d)), $d), ord($chr[$x])), $d32);
}
$h = gmp_mod($h, 53);
return gmp_intval($h);
}
答案 1 :(得分:0)
问题可能出在这一行 $ h =($ h +($ h&lt;&lt; 5))^(ord($ chr));
在应用xor之前的C中,单个字符被强制转换为4字节长。虽然我不确定什么类型的ord返回,但尝试在较小的表达式中打破表达式并测试它们在C和PHP中表现相同的天气
像h +(h <&lt; 5)在每个h的C和PHP中应该表现完全相同。