Приложение работает в php 5.3, но не 5.4+

Мы запускаем серверное приложение для активации нашего программного обеспечения, веб-приложение и сама база данных отлично работают в php 5.4+, но активация в программном обеспечении вызывает внутреннюю ошибку сервера, если мы используем что-либо выше, чем php 5.3 (тест с 5.4, 5.5 и 5.6) - я хотел бы установить 5.6, чтобы быть в курсе будущих событий и обновляться на сервере.

Я предполагаю, что проблема заключается в php-файле активации, может ли кто-нибудь найти здесь какой-либо код, который не будет совместим с php54+?

<?PHP

ini_set('display_errors',1);
error_reporting(E_ALL);

require 'includes/master.inc.php';

$post = trim(file_get_contents('php://input'));
//$post = base64_decode($post);
//$dict = json_decode($post);

$a = new Activation();
$a->app_id        = 373; // $dict->app_id;
$a->name          = $_REQUEST["nameOrEmail"]; //$dict->email;
$a->serial_number = $_REQUEST["activationCode"]; //$dict->serial;
$a->guid        = $_REQUEST["guid"];
$a->dt            = dater();
$a->ip            = $_REQUEST["ip_overwrite"];
if($a->ip == "")  $a->ip = $_SERVER['REMOTE_ADDR'];

if($a->serial_number == null || $a->guid == null) {
    header("HTTP/1.0 400 Activation Code or more arguments required");
    exit();
}
$a->insert();

$app = new Application($a->app_id);
if(!$app->ok()) {
    header("HTTP/1.0 412 Invalid Application");
    exit();
}
$o = new Order();
$o->select($a->serial_number, 'serial_number');
if(!$o->ok()) {
    header("HTTP/1.0 406 Invalid activation code");
    exit();
}

// Because we die before the activation is updated with the found order id,
// this has the added benefit of highlighting the activation as "fraudulent"
// in the activations list. It's not fraudulent obviously, but it does let
// us quickly see if deactivated licenses are still being used.
if($o->deactivated == 1) {
    header("HTTP/1.0 409 Activation Code is disabled.");
    exit();
}

if($o->license_name != null && $o->license_name != $a->guid)  {
    header("HTTP/1.0 410 Activation Code has been already claimed.");
    exit();
}
$a->order_id = $o->id;
$a->update();

//$o->downloadLicense();


//header("Cache-Control: public");
//header("Cache-Control: no-store, no-cache, must-revalidate");
//header("Cache-Control: post-check=0, pre-check=0", false);
//header("Pragma: no-cache");
//header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
//header("Content-Type: application/x-download"); // Stupid fix for Safari not honoring content-disposition
//header("Content-Length: " . strlen($this->order->license));
//header("Content-Disposition: attachment; filename={$this->application->license_filename}");
//header("Content-Transfer-Encoding: binary");
//echo $this->order->license;
//exit;

/**
  * hex2bin
  * Converts a hexadecimal string to binary
  * @param string Hex string
  * @return string Binary string
  */
function hex2bin($hex) {
if (strlen($hex) % 2)
    $hex = "0".$hex;
$bin = '';
for ($i = 0; $i < strlen($hex); $i += 2) { 
    $bin .= chr(hexdec(substr($hex, $i, 2))); 
}

   return $bin; 
} 

/**
  * dec2hex
  * Converts a decimal string to a hexadecimal string
  * @param string Decimal string
  * @return string Hex string
  */
function dec2hex($number)
{
$hexvalues = array('0','1','2','3','4','5','6','7',
                   '8','9','A','B','C','D','E','F');
$hexval = '';
while($number != '0')
{
    $hexval = $hexvalues[bcmod($number,'16')].$hexval;
    $number = bcdiv($number,'16',0);
}
return $hexval;
}

/**
  * hex2dec
  * Converts a hexadecimal string to decimal string
  * @param string Hex string
  * @return string Decimal string
  */
function hex2dec($number)
{
$decvalues = array('0' =>  '0', '1' =>  '1', '2' => '2',
                   '3' =>  '3', '4' =>  '4', '5' => '5',
                   '6' =>  '6', '7' =>  '7', '8' => '8',
                   '9' =>  '9', 'A' => '10', 'B' => '11',
                   'C' => '12', 'D' => '13', 'E' => '14',
                   'F' => '15', 'a' => '10', 'b' => '11',
                   'c' => '12', 'd' => '13', 'e' => '14',
                   'f' => '15');
$decval = '0';

$number = array_pop(explode("0x", $number, 2));

$number = strrev($number);
for($i = 0; $i < strlen($number); $i++)
{
        $decval = bcadd(bcmul(bcpow('16',$i,0),$decvalues[$number{$i}]), $decval);
}
return $decval;
}

/**
  * powmod
  * Raise a number to a power mod n
  * This could probably be made faster with some Montgomery trickery, but it's just fallback for now
  * @param string Decimal string to be raised
  * @param string Decimal string of the power to raise to
  * @param string Decimal string the modulus
  * @return string Decimal string
  */
function powmod($num, $pow, $mod)
{
if (function_exists('bcpowmod')) {
    // bcpowmod is only available under PHP5
    return bcpowmod($num, $pow, $mod);
}

// emulate bcpowmod
$result = '1';
do {
    if (!bccomp(bcmod($pow, '2'), '1')) {
        $result = bcmod(bcmul($result, $num), $mod);
    }
    $num = bcmod(bcpow($num, '2'), $mod);
    $pow = bcdiv($pow, '2');
} while (bccomp($pow, '0'));
return $result;
}

/**
  * getSignature
  * Get the base64 signature of a dictionary
  * @param array Associative array (i.e. dictionary) of key-value pairs
  * @param string Hexadecimal string of public key
  * @param string Hexadecimal string the private key
  * @return string Base64 encoded signature
  */
function getSignature($dict, $key, $privKey)
{
// Sort keys alphabetically
uksort($dict, "strcasecmp");

// Concatenate all values
$total = '';
foreach ($dict as $value)
    $total .= $value;

// Get the hash
$hash = sha1(utf8_encode($total));

// OpenSSL-compatible PKCS1 Padding
// 128 bytes - 20 bytes hash - 3 bytes extra padding = 105 bytes '0xff'
$paddedHash = '0001';
for ($i = 0; $i < 105; $i++)
{
    $paddedHash .= 'ff';
}
$paddedHash .= '00'.$hash;

$decryptedSig = hex2dec($paddedHash);

// Encrypt into a signature
$sig = powmod($decryptedSig, hex2dec($privKey), hex2dec($key));
$sig = base64_encode(hex2bin(dec2hex($sig)));
return $sig;
}

$activationResponse =  getSignature(array("activationCode"=>$a->serial_number, "guid"=>$a-     >guid), "BE6749000DA18D2D21F1D09455DB1E6C354E0B",    "7EEF860009165E1E164517CBDDF6D66A6F5D176C03883EC3E7BB643D84B0E17A41E68A57AE09670A943042F50AE9E41633E  E64A88639DA4691C3A11778839AAEB");
echo $activationResponse;

 $o->license_name = $a->guid;
 $o->license = $activationResponse;
$o->update();

exit();

Вот шестнадцатеричная ошибка из журнала

2014/12/02 13:05:22 [error] 22848#0: *280 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Cannot redeclare hex2bin() in /var/www/html/aurora/aurora-inapp.php on line 85" while reading response header from upstream, client: 141.101.00.22, server: test.com, request: "POST /aurora/aurora-inapp.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "test.com"

person realdannys    schedule 02.12.2014    source источник
comment
error_log содержание ...?   -  person Aleksei Matiushkin    schedule 02.12.2014
comment
Мне кажется, вы пытаетесь использовать функцию, устаревшую в PHP 5.4, которая доступна в версии 5.3. Пожалуйста, предоставьте соответствующие записи из вашего error_log.   -  person AStopher    schedule 02.12.2014
comment
Это могло быть вызвано содержимым includes/master.inc.php, но мы не знаем. Кроме того, я не доверяю операторам if() без фигурных скобок. Пожалуйста, используйте фигурные скобки, и котята будут избавлены.   -  person MonkeyZeus    schedule 02.12.2014
comment
Я получил ошибку Fatal error</b>: Cannot redeclare hex2bin() in <b>[...][...]</b> on line <b>83</b><br при тестировании кода на совместимость в песочнице PHP, возможно, это так. Если нет, то указанный вами код не работает, предоставьте полный код.   -  person AStopher    schedule 02.12.2014
comment
Вам действительно нужно проверить журналы ошибок Apache и журналы ошибок PHP.   -  person MonkeyZeus    schedule 02.12.2014
comment
Добавлен код ошибки, так как @cybermonkey обнаружил, что это hex2bin, который, кажется, больше не работает - хотя я не уверен, как обновить его до 5.4+ совместимого кода.   -  person realdannys    schedule 02.12.2014


Ответы (1)


Ваш код дает сбой, так как с PHP 5.4 в PHP появилась собственная функция hex2bin. Чтобы решить эту проблему, вам нужно удалить используемую функцию hex2bin.

Возможно, вы захотите выполнить простую проверку версии в операторе if перед объявлением функции с помощью phpversion() :

if (!function_exists('hex2bin')) 
{
    function hex2bin($hex) {
    if (strlen($hex) % 2)
        $hex = "0".$hex;
    $bin = '';
    for ($i = 0; $i < strlen($hex); $i += 2) { 
        $bin .= chr(hexdec(substr($hex, $i, 2))); 
    }

       return $bin; 
    } 
}

Из Github:

Начиная с PHP 5.4 PHP предоставляет собственную функцию hex2bin, которая приводит к сбою объявления hex2bin в ykksm-util.php, что приводит к следующей ошибке:

Неустранимая ошибка PHP: невозможно повторно объявить hex2bin()

Приветствую Райана П. за полезный комментарий:

Этот код не сработает - он вызывает phpinfo() с недопустимым аргументом, а вызов phpversion("tidy") вернет версию аккуратного расширения (2.0). Лучше просто проверить существование функции, т.е. if (!function_exists('hex2bin')) {

person AStopher    schedule 02.12.2014
comment
Спасибо @cybermonkey, мне удалось выяснить, и я просто переименовал его, поэтому вместо него используется функция aug_hex2bin($hex) - person realdannys; 02.12.2014
comment
@realdannys Нет проблем, я рад помочь. Ведь именно для этого мы здесь :-). - person AStopher; 02.12.2014
comment
Этот код не будет работать — он вызывает phpinfo() с недопустимым аргументом, а вызов phpversion("tidy") вернет версию аккуратного расширения (2.0). Лучший способ - просто проверить существование функции, т.е. if (!function_exists('hex2bin')) { - person kitti; 24.05.2016
comment
@RyanP Отредактировано и приписано. - person AStopher; 24.05.2016