Я пытаюсь обновить с PHP 5.2.x до 5.3.2 на моем сервере. Проблема в том, что я полагаюсь на , нарушенную реализацию PHP ezmlm_hash() (здесь указывается ошибка: http://bugs.php.net/bug.php?id=47969).преобразование функции хэширования C в PHP: ezmlm_hash
Моя первая мысль заключалась в том, чтобы переписать сломанную версию собственной PHP-функции (которая написана на C) сама в PHP и использовать ее в моем коде вместо изменения исходного кода PHP и необходимости компилировать PHP из исходного кода.
Вот версия 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(
'[email protected]',
'[email protected]',
);
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
Я знаю, что, вероятно, есть некоторые точности или набрав вопросы, я просто не знаю, как это исправить. Любая помощь будет принята с благодарностью!
UPDATE
Когда я бегу Thes код на 32-битных машин, они оба выводят новые исправленные значения:
12
12
45
45
Я думаю, что это что-то делать с оператором по модулю .. Кто-нибудь знает PHP-эквивалент оператора C по модулю? % в PHP ведет себя по-другому!
UPDATE 2
Похоже, если это не представляется возможным с ванильным PHP, как это арифметику с плавающей точкой не имеет достаточной точности, и странность в. Мне нужно будет установить либо BCMath, либо GMP. Спасибо за понимание каждого.
, поведение которых вы были полагаться на? Если это 64-битный, вы не получите этого из кода php, который вы указали, даже игнорируя возможные проблемы с подписанным/unsigned – Spudd86
. Это определенно для меня 64-битная проблема. Запуск этого кода дает одинаковые результаты по моя 32-битная машина. – tplaner
Предполагается, что ezmlm_hash использует 'unsigned int h = 5381;' вместо 'unsigned int h = 5381L;'. Это было исправлено в более поздних версиях PHP. то есть64-битная версия вела себя плохо ... исправление заключалось в том, чтобы всегда делать 32-битные вычисления! Так что теперь я должен подражать неправильной 64-битной версии ... –