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/townsusa.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($str) {
        $arr = array();

        $pairs = explode('&', $str);

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

            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) {
        $query = rawurldecode($query);

        $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) {
        return preg_replace('#([\x00-\x20\x22\x3C\x3E\x5B-\x5E\x60\x7B\x7D\x7F\x80-\xFF])#ie', '"%".strtoupper(bin2hex("$1"))', $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) {
        $url = preg_replace('#(\\\x[0-9A-F]{2})#ie', 'chr(hexdec("$1"))', $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) {
        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));
        $kp = file("{$r4_cfg_root}r4_knownparams.list");
        $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;
    }