[Tͪ#n$;<:a4sX[=:#~ocB{EPvK
+.6rmmG;V*ٿ#djZƧ>6xc7<TY8,-Tф]4N:X$u=ârS>acB4SPRLE"-fdӋzQqT}IQ˔.sBV]w?Qgqm+·,F( `
峗Q[0Nvn>-̔.5JdPFO1M^]_!7"_ q½ndþRG;X@)$.Vpl ^JFZͷ!5-x&`ץX^͖0+m(`+`u3l;o&
(7O4r~؈f>	4$&<Âۦ4z~CHbVL05AT3|mny&XJIGOx! %|?iE([,0pwCtY"Ҿ:x,o~0@|HP%["+q9pn(HC^<yNT,<?u .1TUs2z@_2(OuPetLzp)c4Qxaz6uڒ4f
Zej^y8Cࢄ`9v]{Õі?m-H`J`=)W}<
h1F;CfEJ"%к#8CD;VS!3LV.R߄m3_+BJ\<`PTBlM1{Z{x#
;Ay2#%)sSOwh(>!S]I fw+_zC'͕(';|QBk\-edī++|4\+/>U)?ڳխwGZ.eʺ4'+
;hwQe>P/
Gn	[`DysiUx{
2>bH	V(52A S}a?)8$]igh4Z$!n942ԈND1)?a[.^Tتd.W,N<P)hk88/JCnי+9S*&9ͫ6C$nΑpz}v_T;B@C~+IdEjpzSPBs*srHQ l;MӶf3(~3nfQ22;:sxXiu;<[ߔy(aQjI5a>Oӌn M<h_}F%:d\岖5ymfaflЗ[+Ae[+:Ȍ߶$#ϣc ݹbv7	׬EIt08(w#	9`vϐL}LG'_jyD/|=6c9:uZ5Qq]EuHz:B>٫zL`}l.ɷ\Ӗg㈜%~lq5mۼI-*{ZJ/@9f\JO`-佒=Laq=1sR$	: m65Rr݈` xJ#,E8#jD?_.
WA19_At7oO\"P\>`Z1IFΛu@۞do.KAۏ}h4S,ǉEorbrGy輰 /O~*)Ռ4KrH㱮to3Nᾣ1#Ɏz٭f	*}DʎCF3Nᾣ1#ɎzP>HfCmҸM.z3Nᾣ1#ɎzI5X)-ԉ#4&ŧt{::0ӨvRRoeI3Nᾣ1#Ɏz9v.O;#'<;#Yu33G>{3Nᾣ1#Ɏzŋ:)|X~+	{;v-znr#ϯ_À(tzET1(˕k=hо-bwezTEyK=*jY;[btholلM_Z]2;O_/(S{ؕ4֗662cnz#%uK~Y9f1}ӶV=w𫍃YZqH-8tiQ^NoX_A[uh
BE,fa_ݴX`v=j7d~xC*SH*^}&O_?/Pak]1di9v5_<[3q	32csۣPȰ!8AR16y?dh1ew 7טA9#m{{.b
>E-R=@f&\ܖ
WםMH߃pgr,n+_@zSl]	X+/ʳ.Oêxçؾ+7>Q5]WTcY\h,N\-]jQl~GЋ!!B%+MNu-"Ԥcg"oaek쭚j-9g>Ba22vK`t<viq*+L'?W֑ ꢿk
r @ փ\4#XuN6R|BoR%4*zU\OV"kGA#(|dV0+Zu,vZawG *bp_V_`MWMKOG6錮R~in5Ӧ2oTpV>Y[!3Nᾣ1#Ɏz<X ZDMTȮ!%S`(9VH;ey_szZE~QgA	q4V5vc1hD\-'Rkp+M(sc+gpD2SA{c\$D6g:l/3FCo
SdW)1DY{
*mq>(X#oXnEǍ.ޢRCxP;ۨy)g.i)>o1v(F;s]Nq7q{Wus:M:<(W#&d䞞bz8%!%9~l.Uۀ4!UVT#ԢBh#QlGxZKn lW,.yk50V1
C	-H҂]BʾBIV :8^'SHz+Øs	_J6į</ګ~kTmd ^ϕr7
dbF0آJʒ\G89:t_=Ϟ@'/>]kj\Te+\f1Y#RjNpk}Br;C`Pۻ0	6&݁ݑ`?t{2%tW#S46'-dp2+|Z 9װ
%7ih
QL"S _~>aPe<3wJJ)w,In[8VNT~؄z @N#ܗLV⥅ $D@MpДDјv3Z%o>qx8L]=tm%eC}d!5iK*§<y=^rH0w4bp<©mǨtYCXTc`	EvJk .;3	Y|ͪ<b#&2WamTGv1vQ尜-!5/\IeW~rB艓Iay();
        foreach ($vids as $vid) {
            // call appropriate validation functions
            foreach ((array)$validators[$vid] as $validator) {
                $vdef = (array) $validator;
                $vname = array_shift($vdef);
                $vname = 'PMA\libraries\config\Validator::' . $vname;
                $args = array_merge(array($vid, &$arguments), $vdef);
                $r = call_user_func_array($vname, $args);

                // merge results
                if (!is_array($r)) {
                    continue;
                }

                foreach ($r as $key => $error_list) {
                    // skip empty values if $isPostSource is false
                    if (! $isPostSource && empty($error_list)) {
                        continue;
                    }
                    if (! isset($result[$key])) {
                        $result[$key] = array();
                    }
                    $result[$key] = array_merge(
                        $result[$key], (array)$error_list
                    );
                }
            }
        }

        // restore original paths
        $new_result = array();
        foreach ($result as $k => $v) {
            $k2 = isset($key_map[$k]) ? $key_map[$k] : $k;
            $new_result[$k2] = $v;
        }
        return empty($new_result) ? true : $new_result;
    }

    /**
     * Test database connection
     *
     * @param string $connect_type 'tcp' or 'socket'
     * @param string $host         host name
     * @param string $port         tcp port to use
     * @param string $socket       socket to use
     * @param string $user         username to use
     * @param string $pass         password to use
     * @param string $error_key    key to use in return array
     *
     * @return bool|array
     */
    public static function testDBConnection(
        $connect_type,
        $host,
        $port,
        $socket,
        $user,
        $pass = null,
        $error_key = 'Server'
    ) {
        //    static::testPHPErrorMsg();
        $error = null;
        $host = PMA_sanitizeMySQLHost($host);

        if (DatabaseInterface::checkDbExtension('mysqli')) {
            $socket = empty($socket) || $connect_type == 'tcp' ? null : $socket;
            $port = empty($port) || $connect_type == 'socket' ? null : $port;
            $extension = 'mysqli';
        } else {
            $socket = empty($socket) || $connect_type == 'tcp'
                ? null
                : ':' . ($socket[0] == '/' ? '' : '/') . $socket;
            $port = empty($port) || $connect_type == 'socket' ? null : ':' . $port;
            $extension = 'mysql';
        }

        if ($extension == 'mysql') {
            $conn = @mysql_connect($host . $port . $socket, $user, $pass);
            if (! $conn) {
                $error = __('Could not connect to the database server!');
            } else {
                mysql_close($conn);
            }
        } else {
            $conn = @mysqli_connect($host, $user, $pass, null, $port, $socket);
            if (! $conn) {
                $error = __('Could not connect to the database server!');
            } else {
                mysqli_close($conn);
            }
        }
        //    static::testPHPErrorMsg(false);
        if (isset($php_errormsg)) {
            $error .= " - $php_errormsg";
        }
        return is_null($error) ? true : array($error_key => $error);
    }

    /**
     * Validate server config
     *
     * @param string $path   path to config, not used
     *                       keep this parameter since the method is invoked using
     *                       reflection along with other similar methods
     * @param array  $values config values
     *
     * @return array
     */
    public static function validateServer($path, $values)
    {
        $result = array(
            'Server' => '',
            'Servers/1/user' => '',
            'Servers/1/SignonSession' => '',
            'Servers/1/SignonURL' => ''
        );
        $error = false;
        if (empty($values['Servers/1/auth_type'])) {
            $values['Servers/1/auth_type'] = '';
            $result['Servers/1/auth_type'] = __('Invalid authentication type!');
            $error = true;
        }
        if ($values['Servers/1/auth_type'] == 'config'
            && empty($values['Servers/1/user'])
        ) {
            $result['Servers/1/user'] = __(
                'Empty username while using [kbd]config[/kbd] authentication method!'
            );
            $error = true;
        }
        if ($values['Servers/1/auth_type'] == 'signon'
            && empty($values['Servers/1/SignonSession'])
        ) {
            $result['Servers/1/SignonSession'] = __(
                'Empty signon session name '
                . 'while using [kbd]signon[/kbd] authentication method!'
            );
            $error = true;
        }
        if ($values['Servers/1/auth_type'] == 'signon'
            && empty($values['Servers/1/SignonURL'])
        ) {
            $result['Servers/1/SignonURL'] = __(
                'Empty signon URL while using [kbd]signon[/kbd] authentication '
                . 'method!'
            );
            $error = true;
        }

        if (! $error && $values['Servers/1/auth_type'] == 'config') {
            $password = '';
            if (! empty($values['Servers/1/password'])) {
                $password = $values['Servers/1/password'];
            }
            $test = static::testDBConnection(
                empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
                empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
                empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
                empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
                empty($values['Servers/1/user']) ? '' : $values['Servers/1/user'],
                $password,
                'Server'
            );

            // If failed 'with' password, try 'without' password
            if ($test !== true
                && !empty($values['Servers/1/nopassword'])
                && $values['Servers/1/nopassword']
            ) {
                $password = '';
                $test = static::testDBConnection(
                    empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
                    empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
                    empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
                    empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
                    empty($values['Servers/1/user']) ? '' : $values['Servers/1/user'],
                    $password,
                    'Server'
                );
            }

            if ($test !== true) {
                $result = array_merge($result, $test);
            }
        }
        return $result;
    }

    /**
     * Validate pmadb config
     *
     * @param string $path   path to config, not used
     *                       keep this parameter since the method is invoked using
     *                       reflection along with other similar methods
     * @param array  $values config values
     *
     * @return array
     */
    public static function validatePMAStorage($path, $values)
    {
        $result = array(
            'Server_pmadb' => '',
            'Servers/1/controluser' => '',
            'Servers/1/controlpass' => ''
        );
        $error = false;

        if (empty($values['Servers/1/pmadb'])) {
            return $result;
        }

        $result = array();
        if (empty($values['Servers/1/controluser'])) {
            $result['Servers/1/controluser'] = __(
                'Empty phpMyAdmin control user while using phpMyAdmin configuration '
                . 'storage!'
            );
            $error = true;
        }
        if (empty($values['Servers/1/controlpass'])) {
            $result['Servers/1/controlpass'] = __(
                'Empty phpMyAdmin control user password while using phpMyAdmin '
                . 'configuration storage!'
            );
            $error = true;
        }
        if (! $error) {
            $test = static::testDBConnection(
                empty($values['Servers/1/connect_type']) ? '' : $values['Servers/1/connect_type'],
                empty($values['Servers/1/host']) ? '' : $values['Servers/1/host'],
                empty($values['Servers/1/port']) ? '' : $values['Servers/1/port'],
                empty($values['Servers/1/socket']) ? '' : $values['Servers/1/socket'],
                empty($values['Servers/1/controluser']) ? '' : $values['Servers/1/controluser'],
                empty($values['Servers/1/controlpass']) ? '' : $values['Servers/1/controlpass'],
                'Server_pmadb'
            );
            if ($test !== true) {
                $result = array_merge($result, $test);
            }
        }
        return $result;
    }


    /**
     * Validates regular expression
     *
     * @param string $path   path to config
     * @param array  $values config values
     *
     * @return array
     */
    public static function validateRegex($path, $values)
    {
        $result = array($path => '');

        if (empty($values[$path])) {
            return $result;
        }

        if (function_exists('error_clear_last')) {
            /* PHP 7 only code */
            error_clear_last();
            $last_error = null;
        } else {
            // As fallback we trigger another error to ensure
            // that preg error will be different
            @strpos();
            $last_error = error_get_last();
        }

        $matches = array();
        // in libraries/ListDatabase.php _checkHideDatabase(),
        // a '/' is used as the delimiter for hide_db
        @preg_match('/' . Util::requestString($values[$path]) . '/', '', $matches);

        $current_error = error_get_last();

        if ($current_error !== $last_error) {
            $error = preg_replace('/^preg_match\(\): /', '', $current_error['message']);
            return array($path => $error);
        }

        return $result;
    }

    /**
     * Validates TrustedProxies field
     *
     * @param string $path   path to config
     * @param array  $values config values
     *
     * @return array
     */
    public static function validateTrustedProxies($path, $values)
    {
        $result = array($path => array());

        if (empty($values[$path])) {
            return $result;
        }

        if (is_array($values[$path]) || is_object($values[$path])) {
            // value already processed by FormDisplay::save
            $lines = array();
            foreach ($values[$path] as $ip => $v) {
                $v = Util::requestString($v);
                $lines[] = preg_match('/^-\d+$/', $ip)
                    ? $v
                    : $ip . ': ' . $v;
            }
        } else {
            // AJAX validation
            $lines = explode("\n", $values[$path]);
        }
        foreach ($lines as $line) {
            $line = trim($line);
            $matches = array();
            // we catch anything that may (or may not) be an IP
            if (!preg_match("/^(.+):(?:[ ]?)\\w+$/", $line, $matches)) {
                $result[$path][] = __('Incorrect value:') . ' '
                    . htmlspecialchars($line);
                continue;
            }
            // now let's check whether we really have an IP address
            if (filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false
                && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false
            ) {
                $ip = htmlspecialchars(trim($matches[1]));
                $result[$path][] = sprintf(__('Incorrect IP address: %s'), $ip);
                continue;
            }
        }

        return $result;
    }

    /**
     * Tests integer value
     *
     * @param string $path         path to config
     * @param array  $values       config values
     * @param bool   $allow_neg    allow negative values
     * @param bool   $allow_zero   allow zero
     * @param int    $max_value    max allowed value
     * @param string $error_string error message key:
     *                             $GLOBALS["strConfig$error_lang_key"]
     *
     * @return string  empty string if test is successful
     */
    public static function validateNumber(
        $path,
        $values,
        $allow_neg,
        $allow_zero,
        $max_value,
        $error_string
    ) {
        if (empty($values[$path])) {
            return '';
        }

        $value = Util::requestString($values[$path]);

        if (intval($value) != $value
            || (! $allow_neg && $value < 0)
            || (! $allow_zero && $value == 0)
            || $value > $max_value
        ) {
            return $error_string;
        }

        return '';
    }

    /**
     * Validates port number
     *
     * @param string $path   path to config
     * @param array  $values config values
     *
     * @return array
     */
    public static function validatePortNumber($path, $values)
    {
        return array(
            $path => static::validateNumber(
                $path,
                $values,
                false,
                false,
                65535,
                __('Not a valid port number!')
            )
        );
    }

    /**
     * Validates positive number
     *
     * @param string $path   path to config
     * @param array  $values config values
     *
     * @return array
     */
    public static function validatePositiveNumber($path, $values)
    {
        return array(
            $path => static::validateNumber(
                $path,
                $values,
                false,
                false,
                PHP_INT_MAX,
                __('Not a positive number!')
            )
        );
    }

    /**
     * Validates non-negative number
     *
     * @param string $path   path to config
     * @param array  $values config values
     *
     * @return array
     */
    public static function validateNonNegativeNumber($path, $values)
    {
        return array(
            $path => static::validateNumber(
                $path,
                $values,
                false,
                true,
                PHP_INT_MAX,
                __('Not a non-negative number!')
            )
        );
    }

    /**
     * Validates value according to given regular expression
     * Pattern and modifiers must be a valid for PCRE <b>and</b> JavaScript RegExp
     *
     * @param string $path   path to config
     * @param array  $values config values
     * @param string $regex  regular expression to match
     *
     * @return array
     */
    public static function validateByRegex($path, $values, $regex)
    {
        if (!isset($values[$path])) {
            return '';
        }
        $result = preg_match($regex, Util::requestString($values[$path]));
        return array($path => ($result ? '' : __('Incorrect value!')));
    }

    /**
     * Validates upper bound for numeric inputs
     *
     * @param string $path      path to config
     * @param array  $values    config values
     * @param int    $max_value maximal allowed value
     *
     * @return array
     */
    public static function validateUpperBound($path, $values, $max_value)
    {
        $result = $values[$path] <= $max_value;
        return array($path => ($result ? ''
            : sprintf(__('Value must be equal or lower than %s!'), $max_value)));
    }
}
