HEX
Server: Apache/2.4.6 (CloudLinux) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16
System: Linux s1.gigspace.ru 3.10.0-962.3.2.lve1.5.77.el7.x86_64 #1 SMP Mon Dec 12 07:06:14 EST 2022 x86_64
User: samok164 (6070)
PHP: 7.2.34
Disabled: NONE
Upload Files
File: /var/www/samok164/data/www2/obryadi.ru/rzgn/r4_getHash.php
<?php

if (!defined("ENT_NOQUOTES")) {
    define("ENT_NOQUOTES", 0);
}

if (!defined("ENT_COMPAT")) {
    define("ENT_COMPAT", 2);
}

if (!defined("ENT_QUOTES")) {
    define("ENT_QUOTES", 3);
}

if (!function_exists('html_entity_decode')) {
    /**
     * Версия http://www.php.net/manual/en/function.html-entity-decode.php для PHP 4
     *
     * @return string Returns the decoded string
     */
    function html_entity_decode($string, $opt=ENT_COMPAT) {
        $trans_tbl = get_html_translation_table(HTML_ENTITIES);
        $trans_tbl = array_flip($trans_tbl);

        if ($opt & 1) { // Translating single quotes
            // Add single quote to translation table; doesn't appear to be there by default
            $trans_tbl["&apos;"] = "'";
        }

        if (!($opt & 2)) { // Not translating double quotes
            // Remove double quote from translation table
            unset($trans_tbl["&quot;"]);
        }

        return strtr($string, $trans_tbl);
    }
}

/**
 * Преобразует все HTML-сущности в соответствующие символы.
 *
 * @return string Returns the decoded string
 */
function _unescape($data) {
    return html_entity_decode($data);
}

/**
 * Разбирает URL и возвращает его компоненты (в соответствии с RFC 1808):
 * <scheme>://<netloc>/<path>;<params>?<query>#<fragment>
 *
 * @return array Массив компонентов разобранного URL
 */
function _parse_url($url) {
    $parsed_url = parse_url($url);
    $parsed_url['path'] = isset($parsed_url['path']) ? $parsed_url['path'] : '';
    $parsed_url['scheme'] = isset($parsed_url['scheme']) ? $parsed_url['scheme'] : '';
    $parsed_url['netloc'] = isset($parsed_url['host']) ? $parsed_url['host'] : '';
    $parsed_url['params'] = isset($parsed_url['params']) ? $parsed_url['params'] : '';
    $parsed_url['query'] = isset($parsed_url['query']) ? $parsed_url['query'] : '';
    $parsed_url['fragment'] = isset($parsed_url['fragment']) ? $parsed_url['fragment'] : '';

    list($parsed_url['path'], $parsed_url['params']) = array_pad(explode(';', $parsed_url['path'], 2), 2, '');

    return array($parsed_url['scheme'], $parsed_url['netloc'], $parsed_url['path'],
        $parsed_url['params'], $parsed_url['query'], $parsed_url['fragment']);
}

/**
 * This can be confusing for anyone who's used to the CGI standard, so keep it in mind.
 *
 * @return array Массив разобранного на фрагменты по '&' и ';' и '=' URL
 */
function proper_parse_str($qs) {
    $pairs = array();

    foreach (explode('&', $qs) as $s1) {
        foreach (explode(';', $s1) as $s2) {
            $pairs[] = $s2;
        }
    }

    $arr = array();

    foreach ($pairs as $pair) {
        list($name, $value) = array_pad(explode('=', $pair, 2), 2, NULL);
        $name = isset($name) ? rawurldecode($name) : $name;
        $value = isset($value) ? rawurldecode($value) : $value;

        if (isset($arr[$name])) {
            if (is_array($arr[$name])) {
                $arr[$name][] = $value;
            } else {
                $arr[$name] = array($arr[$name], $value);
            }
        }
        else {
            $arr[$name] = $value;
        }
    }

    return $arr;
}

/**
 * Разбирает строку, которая должна иметь формат запроса URL, в переменные.
 *
 * @return array Массив разобранной строки в переменные
 */
function _parse_qsl($query, $keep_blank_values=false) {
    $arr = array();
    $arr = proper_parse_str($query);

    foreach ($arr as $key => $value) {
        if ($value == '') {
            if (!$keep_blank_values) {
                unset($arr[$key]);
            }
        }
        else {
            if (is_array($value)) {
                foreach ($value as $k => $v) {
                    if ($v == '') {
                        if (!$keep_blank_values) {
                            unset($value[$k]);
                        }
                    }
                }

                if (empty($value)) {
                    unset($arr[$key]);
                }
            }
        }
    }

    return $arr;
}

/**
 * Оставляет только параметры, указанные в $attributes (r4_knownparams.list).
 * Удаляет параметры из заданного списка и $exclude_attributes (по точному совпадению).
 *
 * @return array
 */
function _delete_trash_keyvals($keyvals, $attributes=array(), $exclude_attributes=array(), $allow_value_list=true) {
    $r4_exclude_attributes = array('r5showhash', 'r5techinfo');
    $exclude_attributes = array_merge($r4_exclude_attributes, $exclude_attributes);

    foreach (array_keys($keyvals) as $key) {
        if (!empty($attributes) && !in_array($key, $attributes)) {
            unset($keyvals[$key]);
            continue;
        }

        foreach ($exclude_attributes as $exclude_attribute) {
            $matches = array();

            if (preg_match('/{{(.*)}}/', $exclude_attribute, $matches)) {
                if (preg_match("/{$matches[1]}/", $key)) {
                    unset($keyvals[$key]);
                    break;
                }
            }
            else {
                if ($key === $exclude_attribute) {
                    unset($keyvals[$key]);
                    break;
                }
            }
        }

        if (!$allow_value_list && is_array($keyvals[$key])) {
            $keyvals[$key] = end($keyvals[$key]);
        }
    }

    return $keyvals;
}

if (!function_exists('http_build_query')) {
    /**
     * Версия http://www.php.net/manual/ru/function.http-build-query.php для PHP 4
     *
     * @return string Возвращает URL-кодированную строку
     */
    function http_build_query($params, $prefix='', $remove_final_amp=TRUE, $remove_null_value=TRUE) {
        $query_string = '';

        if (is_array($params)) {
            foreach ($params as $key => $value) {
                $correct_key = $prefix;

                if ($prefix === '') {
                    $correct_key .= $key;
                }
                else {
                    $correct_key .= "[" . $key . "]";
                }

                if (!$remove_null_value || isset($value)) {
                    if (!is_array($value)) {
                        $query_string .= urlencode($correct_key) . "=" . urlencode($value) . "&";
                    }
                    else {
                        $query_string .= http_build_query($value, $correct_key, FALSE, $remove_null_value);
                    }
                }
            }
        }

        if ($remove_final_amp === true) {
            return substr($query_string, 0, strlen($query_string) - 1);
        }
        else {
            return $query_string;
        }
    }
}

/**
 * Генерирует URL-кодированную строку запроса.
 *
 * @return string Возвращает URL-кодированную строку
 */
function _urlencode($query) {
    foreach ($query as $k => $v){
        if (!isset($v) && $k != '') {
            $query[$k] = '';
        }
    }

    $query = preg_replace('#%5B\d+%5D#i', '', http_build_query($query));
    $query = str_replace('+', '%20', $query);

    return $query;
}

/**
 * Резервирует заданный набор encode-последовательностей.
 *
 * @return string Возвращает декодированный URL в виде строки
 */
function _unquotepath($path) {
    foreach (array('2f', '2F', '3f', '3F') as $reserved) {
        $path = str_replace('%'.$reserved, '%25'.strtoupper($reserved), $path);
    }
    return rawurldecode($path);
}

/**
 * Преобразует адрес в корректный URL.
 * Unsafe-символы (см. http://www.asciitable.com/) преобразуются в соответствии с RFC-3986.
 *
 * @return string Корректный URL
 */
function _safe_url_string($url) {
    if (!function_exists('_safe_url_string_callback')) {
        function _safe_url_string_callback($matches) {
            return "%".strtoupper(bin2hex($matches[1]));
        }
    }

    return preg_replace_callback('#([\x00-\x20\x22\x3C\x3E\x5B-\x5E\x60\x7B\x7D\x7F\x80-\xFF])#i', '_safe_url_string_callback', $url);
}

/**
 * Возвращает составленный URL.
 *
 * @return string Составленный из фрагментов URL
 */
function _urlunparse($data) {
    $scheme = isset($data['scheme']) && $data['scheme'] != '' ? $data['scheme'].'://' : '';
    $netloc = isset($data['netloc']) && $data['netloc'] != '' ? $data['netloc'] : '';
    $path = isset($data['path']) && $data['path'] != '' ? $data['path'] : '';
    $params = isset($data['params']) && $data['params'] != '' ? ';'.$data['params'] : '';
    $query = isset($data['query']) && $data['query'] != '' ? '?'.$data['query'] : '';
    $fragment = isset($data['fragment']) && $data['fragment'] != '' ? '#'.$data['fragment'] : '';

    return $scheme.$netloc.$path.$params.$query.$fragment;
}

/**
 * Приводит урл к каноническому виду применяя следующие процедуры:
 *
 * - unescape символов в урле
 * - сортирует get-параметры запроса, только по ключу
 * - процентное кодирование путий и аргументов запроса, non-ASCII символы процентно кодуруются с помощью UTF-8 (RFC-3986)
 * - все пробелы превращаются в '%20' (по документации так правильно делать для всех урлов, кроме урлов из форм)
 * - приводит процентное кодирование к единому регистру (%2f -> %2F)
 * - сохранять get-параметры с пустым значением (до тех пор пока keep_blank_values не будет выставлен в false)
 * - удаляет фрагменты (якори) (до тех пор пока keep_fragments не будет выставлен в true)
 * - добавляет слэш в конце путей
 *
 * @param string $url Искомый URL
 * @param bool $keep_blank_values Сохранить пустые параметры
 * @param bool $keep_fragments Сохранить фрагменты (якоря)
 * @param array $attributes Список параметров которые должны остаться в урле
 * @param array $exclude_attributes Список параметров которые нужно убрать из урла
 * @param bool $allow_value_list Оставить дублирующиеся GET-параметры в урле
 *
 * @return string URL в каноническом виде
 */
function _canonicalize_url($url, $keep_blank_values=true, $keep_fragments=false,
        $encoding='UTF-8', $attributes=array(), $exclude_attributes=array(), $allow_value_list=true) {
    if (!function_exists('_canonicalize_url_callback')) {
        function _canonicalize_url_callback($matches) {
            return chr(hexdec($matches[1]));
        }
    }

    $url = preg_replace_callback('#(\\\x[0-9A-F]{2})#i', '_canonicalize_url_callback', $url);

    if (function_exists('mb_check_encoding')) {
        if (!mb_check_encoding($url, $encoding)) {
            $url = mb_convert_encoding($url, $encoding);
        }
    }
    elseif (function_exists('mb_detect_encoding')) {
        if (mb_detect_encoding($url) != $encoding) {
            $url = mb_convert_encoding($url, $encoding);
        }
    }

    $url = _unescape(trim($url));

    list($scheme, $netloc, $path, $params, $query, $fragment) = _parse_url($url);

    $keyvals = _parse_qsl($query, $keep_blank_values);
    $keyvals = _delete_trash_keyvals($keyvals, $attributes, $exclude_attributes, $allow_value_list);
    ksort($keyvals);

    $query = _urlencode($keyvals);

    $path = _safe_url_string(_unquotepath($path)) | '/';
    $path = preg_replace('#/+#', '/', $path);

    $fragment = $keep_fragments ? $fragment : '';

    $data = array(
        'scheme' => strtolower($scheme),
        'netloc' => strtolower($netloc),
        'path' => $path,
        'params' => $params,
        'query' => $query,
        'fragment' => $fragment
    );

    return _urlunparse($data);
}

/**
 * Возвращает относительный путь URL.
 *
 * @return string Относительный путь
 */
function _get_relative_url($url) {
    $url = preg_replace('#https?://.*?(?:/|$)#i', '/', $url, 1);
    $url = ltrim($url, '/');

    return '/'.$url;
}

/**
 * Custom hexdec function for greater numbers using BC Math.
 *
 * @link http://www.php.net/manual/en/book.bc.php BCMath Arbitrary Precision Mathematics
 *
 * @return string
 */
function bchexdec($hex) {
    $dec = 0;
    $len = strlen($hex);

    for ($i = 1; $i <= $len; $i++) {
        $dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
    }

    return $dec;
}

/**
 * Custom hexdec function for greater numbers using GMP.
 *
 * @link http://www.php.net/manual/en/book.gmp.php GNU Multiple Precision
 *
 * @return string
 */
function gmp_hexdec($hex) {
    $gmp = gmp_init(0);
    $mult = gmp_init(1);

    for ($i = strlen($hex) - 1; $i >= 0; $i--, $mult = gmp_mul($mult, 16)) {
        $gmp = gmp_add($gmp, gmp_mul($mult, hexdec($hex[$i])));
    }

    return gmp_strval($gmp);
}


/**
 * Custom hexdec function for greater numbers.
 *
 * @return string
 */
function hex2dec($s) {
    if (!function_exists('number')) {
        function number($param) {
            return intval($param);
        }
    }

    if (!function_exists('add')) {
        function add($x, $y) {
            $c = 0;
            $r = array();
            $x = array_map('number', str_split($x));
            $y = array_map('number', str_split($y));

            while (count($x) || count($y)) {
                $s = (array_pop($x)) + (array_pop($y)) + $c;
                array_unshift($r, $s < 10 ? $s : $s - 10);
                $c = $s < 10 ? 0 : 1;
            }

            if ($c) {
                array_unshift($r, $c);
            }

            return implode('', $r);
        }
    }

    $dec = '0';
    $s = str_split($s);

    foreach($s as $chr) {
        $n = intval($chr, 16);

        for ($t = 8; $t; $t >>= 1) {
            $dec = (string)add($dec, $dec);

            if ($n & $t) {
                $dec = (string)add($dec, '1');
            }
        }
    }

    return $dec;
}

/**
 * Хэширует строку и усекает до 20 символов
 *
 * @return string Усеченная хешированная строка
 */
function _hash_string($string) {
    $string = str_replace('&amp;', '&', str_replace('&amp;', '&', $string));  // Если используется php_value arg_separator "&amp;"

    if (function_exists('bcadd')) {
        $string_hash = bchexdec(md5($string));
    }
    elseif (function_exists('gmp_add')) {
        $string_hash = gmp_hexdec(md5($string));
    }
    else {
        $string_hash = hex2dec(md5($string));
    }

    return substr($string_hash, 0, 18);
}

/**
 * Возвращает хеш относительного URL.
 * Новая функция, созданная для получения идентичных данных с python из КИТ.
 *
 * @return string Хеш относительного URL
 */
function _relative_url_hash($url, $r4_cfg_root='', $exclude_attributes=array()) {
    $attributes = array();

    $r4_knownparams = "{$r4_cfg_root}r4_knownparams.list";

    if (file_exists($r4_knownparams)) {
        $attributes = file($r4_knownparams);

        if (is_array($attributes)) {
            foreach ($attributes as $key => $attribute) {
                $attributes[$key] = trim($attribute);
            }
        }
    }

    if (empty($exclude_attributes)) {
        $r4_badparams = "{$r4_cfg_root}r4_badparams.list";

        if (file_exists($r4_badparams)) {
            $exclude_attributes = file($r4_badparams);

            if (is_array($exclude_attributes)) {
                foreach ($exclude_attributes as $key => $exclude_attribute) {
                    $exclude_attributes[$key] = trim($exclude_attribute);
                }
            }
        }
    }

    $canonical_url = _canonicalize_url($url, true, false, 'UTF-8', $attributes, $exclude_attributes);
    $relative_canonical_url = _get_relative_url($canonical_url);

    return _hash_string($relative_canonical_url);
}

/**
 * Старая функция
 *
 * @return string Хеш md5 от $url и его параметров
 */
function getHash($url, $r4_cfg_root) {
    $u = parse_url(str_replace('&amp;', '&', $url));

    $r4_knownparams = "{$r4_cfg_root}r4_knownparams.list";

    if (file_exists($r4_knownparams)) {
        $kp = file($r4_knownparams);
    }
    else {
        $kp = array();
    }

    $known_params = array();

    foreach ($kp as $K) {
        $known_params[] = trim($K);
    }

    if (empty($u['path'])) {
        $u['path'] = '/';
    }

    $hash = array();
    $hash['=p'] = $u['path'];

    if (!empty($u['query'])) {
        $as = explode('&', $u['query']);

        foreach ($as as $attr) {
            $pair = explode('=', $attr);

            if (!empty($pair)) {
                $v = '';
                $k = '';

                if (!empty($pair[1])) {
                    if (preg_match('/[0-9a-fA-F]{32}/', $pair[1])) {
                        continue;
                    }

                    $v = $pair[1];
                }

                if (!empty($pair[0])) {
                    if (!in_array($pair[0], $known_params)) {
                        continue;
                    }

                    $k = $pair[0];
                }

                if (!isset($hash[$k])) {
                    $hash[$k] = array();
                }

                $hash[$k][] = $v;
            }
        }
    }

    ksort($hash);
    $hash = md5(serialize($hash));

    return $hash;
}