[ Avaa Bypassed ]




Upload:

Command:

www-data@3.16.48.173: ~ $
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
 * Holds the PhpMyAdmin\Controllers\Table\TableSearchController
 *
 * @package PhpMyAdmin\Controllers
 */
namespace PhpMyAdmin\Controllers\Table;

use PhpMyAdmin\Controllers\TableController;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Relation;
use PhpMyAdmin\Sql;
use PhpMyAdmin\Template;
use PhpMyAdmin\Util;

/**
 * Class TableSearchController
 *
 * @package PhpMyAdmin\Controllers
 */
class TableSearchController extends TableController
{
    /**
     * Normal search or Zoom search
     *
     * @access private
     * @var string
     */
    private $_searchType;
    /**
     * Names of columns
     *
     * @access private
     * @var array
     */
    private $_columnNames;
    /**
     * Types of columns
     *
     * @access private
     * @var array
     */
    private $_columnTypes;
    /**
     * Collations of columns
     *
     * @access private
     * @var array
     */
    private $_columnCollations;
    /**
     * Null Flags of columns
     *
     * @access private
     * @var array
     */
    private $_columnNullFlags;
    /**
     * Whether a geometry column is present
     *
     * @access private
     * @var boolean
     */
    private $_geomColumnFlag;
    /**
     * Foreign Keys
     *
     * @access private
     * @var array
     */
    private $_foreigners;
    /**
     * Connection charset
     *
     * @access private
     * @var string
     */
    private $_connectionCharSet;

    protected $url_query;

    /**
     * @var Relation $relation
     */
    private $relation;

    /**
     * Constructor
     *
     * @param string $searchType Search type
     * @param string $url_query  URL query
     */
    public function __construct(
        $response,
        $dbi,
        $db,
        $table,
        $searchType,
        $url_query
    ) {
        parent::__construct($response, $dbi, $db, $table);

        $this->url_query = $url_query;
        $this->_searchType = $searchType;
        $this->_columnNames = array();
        $this->_columnNullFlags = array();
        $this->_columnTypes = array();
        $this->_columnCollations = array();
        $this->_geomColumnFlag = false;
        $this->_foreigners = array();
        $this->relation = new Relation();
        // Loads table's information
        $this->_loadTableInfo();
        $this->_connectionCharSet = $this->dbi->fetchValue(
            "SELECT @@character_set_connection"
        );
    }

    /**
     * Gets all the columns of a table along with their types, collations
     * and whether null or not.
     *
     * @return void
     */
    private function _loadTableInfo()
    {
        // Gets the list and number of columns
        $columns = $this->dbi->getColumns(
            $this->db, $this->table, null, true
        );
        // Get details about the geometry functions
        $geom_types = Util::getGISDatatypes();

        foreach ($columns as $row) {
            // set column name
            $this->_columnNames[] = $row['Field'];

            $type = $row['Type'];
            // check whether table contains geometric columns
            if (in_array($type, $geom_types)) {
                $this->_geomColumnFlag = true;
            }
            // reformat mysql query output
            if (strncasecmp($type, 'set', 3) == 0
                || strncasecmp($type, 'enum', 4) == 0
            ) {
                $type = str_replace(',', ', ', $type);
            } else {
                // strip the "BINARY" attribute, except if we find "BINARY(" because
                // this would be a BINARY or VARBINARY column type
                if (! preg_match('@BINARY[\(]@i', $type)) {
                    $type = preg_replace('@BINARY@i', '', $type);
                }
                $type = preg_replace('@ZEROFILL@i', '', $type);
                $type = preg_replace('@UNSIGNED@i', '', $type);
                $type = mb_strtolower($type);
            }
            if (empty($type)) {
                $type = '&nbsp;';
            }
            $this->_columnTypes[] = $type;
            $this->_columnNullFlags[] = $row['Null'];
            $this->_columnCollations[]
                = ! empty($row['Collation']) && $row['Collation'] != 'NULL'
                ? $row['Collation']
                : '';
        } // end for

        // Retrieve foreign keys
        $this->_foreigners = $this->relation->getForeigners($this->db, $this->table);
    }

    /**
     * Index action
     *
     * @return void
     */
    public function indexAction()
    {
        switch ($this->_searchType) {
        case 'replace':
            if (isset($_POST['find'])) {
                $this->findAction();

                return;
            }
            $this->response
                ->getHeader()
                ->getScripts()
                ->addFile('tbl_find_replace.js');

            if (isset($_POST['replace'])) {
                $this->replaceAction();
            }

            // Displays the find and replace form
            $this->displaySelectionFormAction();
            break;

        case 'normal':
            $this->response->getHeader()
                ->getScripts()
                ->addFiles(
                    array(
                        'makegrid.js',
                        'sql.js',
                        'tbl_select.js',
                        'tbl_change.js',
                        'vendor/jquery/jquery.uitablefilter.js',
                        'gis_data_editor.js',
                    )
                );

            if (isset($_POST['range_search'])) {
                $this->rangeSearchAction();

                return;
            }

            /**
             * No selection criteria received -> display the selection form
             */
            if (!isset($_POST['columnsToDisplay'])
                && !isset($_POST['displayAllColumns'])
            ) {
                $this->displaySelectionFormAction();
            } else {
                $this->doSelectionAction();
            }
            break;

        case 'zoom':
            $this->response->getHeader()
                ->getScripts()
                ->addFiles(
                    array(
                        'makegrid.js',
                        'sql.js',
                        'vendor/jqplot/jquery.jqplot.js',
                        'vendor/jqplot/plugins/jqplot.canvasTextRenderer.js',
                        'vendor/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js',
                        'vendor/jqplot/plugins/jqplot.dateAxisRenderer.js',
                        'vendor/jqplot/plugins/jqplot.highlighter.js',
                        'vendor/jqplot/plugins/jqplot.cursor.js',
                        'tbl_zoom_plot_jqplot.js',
                        'tbl_change.js',
                    )
                );

            /**
             * Handle AJAX request for data row on point select
             *
             * @var boolean Object containing parameters for the POST request
             */
            if (isset($_POST['get_data_row'])
                && $_POST['get_data_row'] == true
            ) {
                $this->getDataRowAction();

                return;
            }
            /**
             * Handle AJAX request for changing field information
             * (value,collation,operators,field values) in input form
             *
             * @var boolean Object containing parameters for the POST request
             */
            if (isset($_POST['change_tbl_info'])
                && $_POST['change_tbl_info'] == true
            ) {
                $this->changeTableInfoAction();

                return;
            }

            //Set default datalabel if not selected
            if (!isset($_POST['zoom_submit']) || $_POST['dataLabel'] == '') {
                $dataLabel = $this->relation->getDisplayField($this->db, $this->table);
            } else {
                $dataLabel = $_POST['dataLabel'];
            }

            // Displays the zoom search form
            $this->displaySelectionFormAction($dataLabel);

            /*
             * Handle the input criteria and generate the query result
             * Form for displaying query results
             */
            if (isset($_POST['zoom_submit'])
                && $_POST['criteriaColumnNames'][0] != 'pma_null'
                && $_POST['criteriaColumnNames'][1] != 'pma_null'
                && $_POST['criteriaColumnNames'][0] != $_POST['criteriaColumnNames'][1]
            ) {
                if (! isset($goto)) {
                    $goto = Util::getScriptNameForOption(
                        $GLOBALS['cfg']['DefaultTabTable'], 'table'
                    );
                }
                $this->zoomSubmitAction($dataLabel, $goto);
            }
            break;
        }
    }

    /**
     * Zoom submit action
     *
     * @param string $dataLabel Data label
     * @param string $goto      Goto
     *
     * @return void
     */
    public function zoomSubmitAction($dataLabel, $goto)
    {
        //Query generation part
        $sql_query = $this->_buildSqlQuery();
        $sql_query .= ' LIMIT ' . $_POST['maxPlotLimit'];

        //Query execution part
        $result = $this->dbi->query(
            $sql_query . ";",
            DatabaseInterface::CONNECT_USER,
            DatabaseInterface::QUERY_STORE
        );
        $fields_meta = $this->dbi->getFieldsMeta($result);
        $data = array();
        while ($row = $this->dbi->fetchAssoc($result)) {
            //Need a row with indexes as 0,1,2 for the getUniqueCondition
            // hence using a temporary array
            $tmpRow = array();
            foreach ($row as $val) {
                $tmpRow[] = $val;
            }
            //Get unique condition on each row (will be needed for row update)
            $uniqueCondition = Util::getUniqueCondition(
                $result, // handle
                count($this->_columnNames), // fields_cnt
                $fields_meta, // fields_meta
                $tmpRow, // row
                true, // force_unique
                false, // restrict_to_table
                null // analyzed_sql_results
            );
            //Append it to row array as where_clause
            $row['where_clause'] = $uniqueCondition[0];

            $tmpData = array(
                $_POST['criteriaColumnNames'][0] =>
                    $row[$_POST['criteriaColumnNames'][0]],
                $_POST['criteriaColumnNames'][1] =>
                    $row[$_POST['criteriaColumnNames'][1]],
                'where_clause' => $uniqueCondition[0]
            );
            $tmpData[$dataLabel] = ($dataLabel) ? $row[$dataLabel] : '';
            $data[] = $tmpData;
        }
        unset($tmpData);

        //Displays form for point data and scatter plot
        $titles = array(
            'Browse' => Util::getIcon(
                'b_browse',
                __('Browse foreign values')
            )
        );
        $this->response->addHTML(
            Template::get('table/search/zoom_result_form')->render([
                'db' => $this->db,
                'table' => $this->table,
                'column_names' => $this->_columnNames,
                'foreigners' => $this->_foreigners,
                'column_null_flags' => $this->_columnNullFlags,
                'column_types' => $this->_columnTypes,
                'titles' => $titles,
                'goto' => $goto,
                'data' => $data,
                'data_json' => json_encode($data),
                'zoom_submit' => isset($_POST['zoom_submit']),
                'foreign_max_limit' => $GLOBALS['cfg']['ForeignKeyMaxLimit'],
            ])
        );
    }

    /**
     * Change table info action
     *
     * @return void
     */
    public function changeTableInfoAction()
    {
        $field = $_POST['field'];
        if ($field == 'pma_null') {
            $this->response->addJSON('field_type', '');
            $this->response->addJSON('field_collation', '');
            $this->response->addJSON('field_operators', '');
            $this->response->addJSON('field_value', '');
            return;
        }
        $key = array_search($field, $this->_columnNames);
        $search_index
            = ((isset($_POST['it']) && is_numeric($_POST['it']))
                ? intval($_POST['it']) : 0);

        $properties = $this->getColumnProperties($search_index, $key);
        $this->response->addJSON(
            'field_type', htmlspecialchars($properties['type'])
        );
        $this->response->addJSON('field_collation', $properties['collation']);
        $this->response->addJSON('field_operators', $properties['func']);
        $this->response->addJSON('field_value', $properties['value']);
    }

    /**
     * Get data row action
     *
     * @return void
     */
    public function getDataRowAction()
    {
        $extra_data = array();
        $row_info_query = 'SELECT * FROM ' . Util::backquote($_POST['db']) . '.'
            . Util::backquote($_POST['table']) . ' WHERE ' .  $_POST['where_clause'];
        $result = $this->dbi->query(
            $row_info_query . ";",
            DatabaseInterface::CONNECT_USER,
            DatabaseInterface::QUERY_STORE
        );
        $fields_meta = $this->dbi->getFieldsMeta($result);
        while ($row = $this->dbi->fetchAssoc($result)) {
            // for bit fields we need to convert them to printable form
            $i = 0;
            foreach ($row as $col => $val) {
                if ($fields_meta[$i]->type == 'bit') {
                    $row[$col] = Util::printableBitValue(
                        $val, $fields_meta[$i]->length
                    );
                }
                $i++;
            }
            $extra_data['row_info'] = $row;
        }
        $this->response->addJSON($extra_data);
    }

    /**
     * Do selection action
     *
     * @return void
     */
    public function doSelectionAction()
    {
        /**
         * Selection criteria have been submitted -> do the work
         */
        $sql_query = $this->_buildSqlQuery();

        /**
         * Add this to ensure following procedures included running correctly.
         */
        $db = $this->db;

        $sql = new Sql();
        $sql->executeQueryAndSendQueryResponse(
            null, // analyzed_sql_results
            false, // is_gotofile
            $this->db, // db
            $this->table, // table
            null, // find_real_end
            null, // sql_query_for_bookmark
            null, // extra_data
            null, // message_to_show
            null, // message
            null, // sql_data
            $GLOBALS['goto'], // goto
            $GLOBALS['pmaThemeImage'], // pmaThemeImage
            null, // disp_query
            null, // disp_message
            null, // query_type
            $sql_query, // sql_query
            null, // selectedTables
            null // complete_query
        );
    }

    /**
     * Display selection form action
     *
     * @param string $dataLabel Data label
     *
     * @return void
     */
    public function displaySelectionFormAction($dataLabel = null)
    {
        $this->url_query .= '&amp;goto=tbl_select.php&amp;back=tbl_select.php';
        if (! isset($goto)) {
            $goto = Util::getScriptNameForOption(
                $GLOBALS['cfg']['DefaultTabTable'], 'table'
            );
        }
        // Displays the table search form
        $this->response->addHTML(
            Template::get('secondary_tabs')
                ->render(
                    array(
                        'url_params' => array(
                            'db'    => $this->db,
                            'table' => $this->table,
                        ),
                        'sub_tabs'   => $this->_getSubTabs(),
                    )
                )
        );
        $this->response->addHTML(
            Template::get('table/search/selection_form')->render(array(
                'search_type' => $this->_searchType,
                'db' => $this->db,
                'table' => $this->table,
                'goto' => $goto,
                'self' => $this,
                'geom_column_flag' => $this->_geomColumnFlag,
                'column_names' => $this->_columnNames,
                'column_types' => $this->_columnTypes,
                'column_collations' => $this->_columnCollations,
                'data_label' => $dataLabel,
                'criteria_column_names' => isset($_POST['criteriaColumnNames']) ? $_POST['criteriaColumnNames'] : null,
                'criteria_column_types' => isset($_POST['criteriaColumnTypes']) ? $_POST['criteriaColumnTypes'] : null,
                'sql_types' => $GLOBALS['dbi']->types,
                'max_rows' => intval($GLOBALS['cfg']['MaxRows']),
                'max_plot_limit' => ((! empty($_POST['maxPlotLimit']))
                    ? intval($_POST['maxPlotLimit'])
                    : intval($GLOBALS['cfg']['maxRowPlotLimit'])),
            ))
        );
    }

    /**
     * Range search action
     *
     * @return void
     */
    public function rangeSearchAction()
    {
        $min_max = $this->getColumnMinMax($_POST['column']);
        $this->response->addJSON('column_data', $min_max);
    }

    /**
     * Find action
     *
     * @return void
     */
    public function findAction()
    {
        $useRegex = array_key_exists('useRegex', $_POST)
            && $_POST['useRegex'] == 'on';

        $preview = $this->getReplacePreview(
            $_POST['columnIndex'],
            $_POST['find'],
            $_POST['replaceWith'],
            $useRegex,
            $this->_connectionCharSet
        );
        $this->response->addJSON('preview', $preview);
    }

    /**
     * Replace action
     *
     * @return void
     */
    public function replaceAction()
    {
        $this->replace(
            $_POST['columnIndex'],
            $_POST['findString'],
            $_POST['replaceWith'],
            $_POST['useRegex'],
            $this->_connectionCharSet
        );
        $this->response->addHTML(
            Util::getMessage(
                __('Your SQL query has been executed successfully.'),
                null, 'success'
            )
        );
    }

    /**
     * Returns HTML for previewing strings found and their replacements
     *
     * @param int     $columnIndex index of the column
     * @param string  $find        string to find in the column
     * @param string  $replaceWith string to replace with
     * @param boolean $useRegex    to use Regex replace or not
     * @param string  $charSet     character set of the connection
     *
     * @return string HTML for previewing strings found and their replacements
     */
    function getReplacePreview(
        $columnIndex, $find, $replaceWith, $useRegex, $charSet
    ) {
        $column = $this->_columnNames[$columnIndex];
        if ($useRegex) {
            $result = $this->_getRegexReplaceRows(
                $columnIndex, $find, $replaceWith, $charSet
            );
        } else {
            $sql_query = "SELECT "
                . Util::backquote($column) . ","
                . " REPLACE("
                . Util::backquote($column) . ", '" . $find . "', '"
                . $replaceWith
                . "'),"
                . " COUNT(*)"
                . " FROM " . Util::backquote($this->db)
                . "." . Util::backquote($this->table)
                . " WHERE " . Util::backquote($column)
                . " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
            // change the collation of the 2nd operand to a case sensitive
            // binary collation to make sure that the comparison
            // is case sensitive
            $sql_query .= " GROUP BY " . Util::backquote($column)
                . " ORDER BY " . Util::backquote($column) . " ASC";

            $result = $this->dbi->fetchResult($sql_query, 0);
        }

        return Template::get('table/search/replace_preview')->render(
            array(
                'db' => $this->db,
                'table' => $this->table,
                'column_index' => $columnIndex,
                'find' => $find,
                'replace_with' => $replaceWith,
                'use_regex' => $useRegex,
                'result' => $result
            )
        );
    }

    /**
     * Finds and returns Regex pattern and their replacements
     *
     * @param int    $columnIndex index of the column
     * @param string $find        string to find in the column
     * @param string $replaceWith string to replace with
     * @param string $charSet     character set of the connection
     *
     * @return array Array containing original values, replaced values and count
     */
    private function _getRegexReplaceRows(
        $columnIndex, $find, $replaceWith, $charSet
    ) {
        $column = $this->_columnNames[$columnIndex];
        $sql_query = "SELECT "
            . Util::backquote($column) . ","
            . " 1," // to add an extra column that will have replaced value
            . " COUNT(*)"
            . " FROM " . Util::backquote($this->db)
            . "." . Util::backquote($this->table)
            . " WHERE " . Util::backquote($column)
            . " RLIKE '" . $GLOBALS['dbi']->escapeString($find) . "' COLLATE "
            . $charSet . "_bin"; // here we
        // change the collation of the 2nd operand to a case sensitive
        // binary collation to make sure that the comparison is case sensitive
        $sql_query .= " GROUP BY " . Util::backquote($column)
            . " ORDER BY " . Util::backquote($column) . " ASC";

        $result = $this->dbi->fetchResult($sql_query, 0);

        if (is_array($result)) {
            /* Iterate over possible delimiters to get one */
            $delimiters = array('/', '@', '#', '~', '!', '$', '%', '^', '&', '_');
            $found = false;
            for ($i = 0, $l = count($delimiters); $i < $l; $i++) {
                if (strpos($find, $delimiters[$i]) === false) {
                    $found = true;
                    break;
                }
            }
            if (! $found) {
                return false;
            }
            $find = $delimiters[$i] . $find . $delimiters[$i];
            foreach ($result as $index=>$row) {
                $result[$index][1] = preg_replace(
                    $find,
                    $replaceWith,
                    $row[0]
                );
            }
        }
        return $result;
    }

    /**
     * Replaces a given string in a column with a give replacement
     *
     * @param int     $columnIndex index of the column
     * @param string  $find        string to find in the column
     * @param string  $replaceWith string to replace with
     * @param boolean $useRegex    to use Regex replace or not
     * @param string  $charSet     character set of the connection
     *
     * @return void
     */
    public function replace($columnIndex, $find, $replaceWith, $useRegex,
        $charSet
    ) {
        $column = $this->_columnNames[$columnIndex];
        if ($useRegex) {
            $toReplace = $this->_getRegexReplaceRows(
                $columnIndex, $find, $replaceWith, $charSet
            );
            $sql_query = "UPDATE " . Util::backquote($this->table)
                . " SET " . Util::backquote($column) . " = CASE";
            if (is_array($toReplace)) {
                foreach ($toReplace as $row) {
                    $sql_query .= "\n WHEN " . Util::backquote($column)
                        . " = '" . $GLOBALS['dbi']->escapeString($row[0])
                        . "' THEN '" . $GLOBALS['dbi']->escapeString($row[1]) . "'";
                }
            }
            $sql_query .= " END"
                . " WHERE " . Util::backquote($column)
                . " RLIKE '" . $GLOBALS['dbi']->escapeString($find) . "' COLLATE "
                . $charSet . "_bin"; // here we
            // change the collation of the 2nd operand to a case sensitive
            // binary collation to make sure that the comparison
            // is case sensitive
        } else {
            $sql_query = "UPDATE " . Util::backquote($this->table)
                . " SET " . Util::backquote($column) . " ="
                . " REPLACE("
                . Util::backquote($column) . ", '" . $find . "', '"
                . $replaceWith
                . "')"
                . " WHERE " . Util::backquote($column)
                . " LIKE '%" . $find . "%' COLLATE " . $charSet . "_bin"; // here we
            // change the collation of the 2nd operand to a case sensitive
            // binary collation to make sure that the comparison
            // is case sensitive
        }
        $this->dbi->query(
            $sql_query,
            DatabaseInterface::CONNECT_USER,
            DatabaseInterface::QUERY_STORE
        );
        $GLOBALS['sql_query'] = $sql_query;
    }

    /**
     * Finds minimum and maximum value of a given column.
     *
     * @param string $column Column name
     *
     * @return array
     */
    public function getColumnMinMax($column)
    {
        $sql_query = 'SELECT MIN(' . Util::backquote($column) . ') AS `min`, '
            . 'MAX(' . Util::backquote($column) . ') AS `max` '
            . 'FROM ' . Util::backquote($this->db) . '.'
            . Util::backquote($this->table);

        $result = $this->dbi->fetchSingleRow($sql_query);

        return $result;
    }

    /**
     * Returns an array with necessary configurations to create
     * sub-tabs in the table_select page.
     *
     * @return array Array containing configuration (icon, text, link, id, args)
     * of sub-tabs
     */
    private function _getSubTabs()
    {
        $subtabs = array();
        $subtabs['search']['icon'] = 'b_search';
        $subtabs['search']['text'] = __('Table search');
        $subtabs['search']['link'] = 'tbl_select.php';
        $subtabs['search']['id'] = 'tbl_search_id';
        $subtabs['search']['args']['pos'] = 0;

        $subtabs['zoom']['icon'] = 'b_select';
        $subtabs['zoom']['link'] = 'tbl_zoom_select.php';
        $subtabs['zoom']['text'] = __('Zoom search');
        $subtabs['zoom']['id'] = 'zoom_search_id';

        $subtabs['replace']['icon'] = 'b_find_replace';
        $subtabs['replace']['link'] = 'tbl_find_replace.php';
        $subtabs['replace']['text'] = __('Find and replace');
        $subtabs['replace']['id'] = 'find_replace_id';

        return $subtabs;
    }

    /**
     * Builds the sql search query from the post parameters
     *
     * @return string the generated SQL query
     */
    private function _buildSqlQuery()
    {
        $sql_query = 'SELECT ';

        // If only distinct values are needed
        $is_distinct = (isset($_POST['distinct'])) ? 'true' : 'false';
        if ($is_distinct == 'true') {
            $sql_query .= 'DISTINCT ';
        }

        // if all column names were selected to display, we do a 'SELECT *'
        // (more efficient and this helps prevent a problem in IE
        // if one of the rows is edited and we come back to the Select results)
        if (isset($_POST['zoom_submit']) || ! empty($_POST['displayAllColumns'])) {
            $sql_query .= '* ';
        } else {
            $sql_query .= implode(
                ', ',
                Util::backquote($_POST['columnsToDisplay'])
            );
        } // end if

        $sql_query .= ' FROM '
            . Util::backquote($_POST['table']);
        $whereClause = $this->_generateWhereClause();
        $sql_query .= $whereClause;

        // if the search results are to be ordered
        if (isset($_POST['orderByColumn']) && $_POST['orderByColumn'] != '--nil--') {
            $sql_query .= ' ORDER BY '
                . Util::backquote($_POST['orderByColumn'])
                . ' ' . $_POST['order'];
        } // end if
        return $sql_query;
    }

    /**
     * Provides a column's type, collation, operators list, and criteria value
     * to display in table search form
     *
     * @param integer $search_index Row number in table search form
     * @param integer $column_index Column index in ColumnNames array
     *
     * @return array Array containing column's properties
     */
    public function getColumnProperties($search_index, $column_index)
    {
        $selected_operator = (isset($_POST['criteriaColumnOperators'][$search_index])
            ? $_POST['criteriaColumnOperators'][$search_index] : '');
        $entered_value = (isset($_POST['criteriaValues'])
            ? $_POST['criteriaValues'] : '');
        $titles = array(
            'Browse' => Util::getIcon(
                'b_browse', __('Browse foreign values')
            )
        );
        //Gets column's type and collation
        $type = $this->_columnTypes[$column_index];
        $collation = $this->_columnCollations[$column_index];
        //Gets column's comparison operators depending on column type
        $typeOperators = $GLOBALS['dbi']->types->getTypeOperatorsHtml(
            preg_replace('@\(.*@s', '', $this->_columnTypes[$column_index]),
            $this->_columnNullFlags[$column_index], $selected_operator
        );
        $func = Template::get('table/search/column_comparison_operators')->render(
            array(
                'search_index' => $search_index,
                'type_operators' => $typeOperators
            )
        );
        //Gets link to browse foreign data(if any) and criteria inputbox
        $foreignData = $this->relation->getForeignData(
            $this->_foreigners, $this->_columnNames[$column_index], false, '', ''
        );
        $value = Template::get('table/search/input_box')->render(
            array(
                'str' => '',
                'column_type' => (string) $type,
                'column_id' => 'fieldID_',
                'in_zoom_search_edit' => false,
                'foreigners' => $this->_foreigners,
                'column_name' => $this->_columnNames[$column_index],
                'column_name_hash' => md5($this->_columnNames[$column_index]),
                'foreign_data' => $foreignData,
                'table' => $this->table,
                'column_index' => $search_index,
                'foreign_max_limit' => $GLOBALS['cfg']['ForeignKeyMaxLimit'],
                'criteria_values' => $entered_value,
                'db' => $this->db,
                'titles' => $titles,
                'in_fbs' => true
            )
        );
        return array(
            'type' => $type,
            'collation' => $collation,
            'func' => $func,
            'value' => $value
        );
    }

    /**
     * Generates the where clause for the SQL search query to be executed
     *
     * @return string the generated where clause
     */
    private function _generateWhereClause()
    {
        if (isset($_POST['customWhereClause'])
            && trim($_POST['customWhereClause']) != ''
        ) {
            return ' WHERE ' . $_POST['customWhereClause'];
        }

        // If there are no search criteria set or no unary criteria operators,
        // return
        if (! isset($_POST['criteriaValues'])
            && ! isset($_POST['criteriaColumnOperators'])
            && ! isset($_POST['geom_func'])
        ) {
            return '';
        }

        // else continue to form the where clause from column criteria values
        $fullWhereClause = array();
        foreach ($_POST['criteriaColumnOperators'] as $column_index => $operator) {
            $unaryFlag =  $GLOBALS['dbi']->types->isUnaryOperator($operator);
            $tmp_geom_func = isset($_POST['geom_func'][$column_index])
                ? $_POST['geom_func'][$column_index] : null;

            $whereClause = $this->_getWhereClause(
                $_POST['criteriaValues'][$column_index],
                $_POST['criteriaColumnNames'][$column_index],
                $_POST['criteriaColumnTypes'][$column_index],
                $operator,
                $unaryFlag,
                $tmp_geom_func
            );

            if ($whereClause) {
                $fullWhereClause[] = $whereClause;
            }
        } // end foreach

        if (!empty($fullWhereClause)) {
            return ' WHERE ' . implode(' AND ', $fullWhereClause);
        }
        return '';
    }

    /**
     * Return the where clause in case column's type is ENUM.
     *
     * @param mixed  $criteriaValues Search criteria input
     * @param string $func_type      Search function/operator
     *
     * @return string part of where clause.
     */
    private function _getEnumWhereClause($criteriaValues, $func_type)
    {
        if (! is_array($criteriaValues)) {
            $criteriaValues = explode(',', $criteriaValues);
        }
        $enum_selected_count = count($criteriaValues);
        if ($func_type == '=' && $enum_selected_count > 1) {
            $func_type    = 'IN';
            $parens_open  = '(';
            $parens_close = ')';

        } elseif ($func_type == '!=' && $enum_selected_count > 1) {
            $func_type    = 'NOT IN';
            $parens_open  = '(';
            $parens_close = ')';

        } else {
            $parens_open  = '';
            $parens_close = '';
        }
        $enum_where = '\''
            . $GLOBALS['dbi']->escapeString($criteriaValues[0]) . '\'';
        for ($e = 1; $e < $enum_selected_count; $e++) {
            $enum_where .= ', \''
                . $GLOBALS['dbi']->escapeString($criteriaValues[$e]) . '\'';
        }

        return ' ' . $func_type . ' ' . $parens_open
        . $enum_where . $parens_close;
    }

    /**
     * Return the where clause for a geometrical column.
     *
     * @param mixed  $criteriaValues Search criteria input
     * @param string $names          Name of the column on which search is submitted
     * @param string $func_type      Search function/operator
     * @param string $types          Type of the field
     * @param bool   $geom_func      Whether geometry functions should be applied
     *
     * @return string part of where clause.
     */
    private function _getGeomWhereClause($criteriaValues, $names,
        $func_type, $types, $geom_func = null
    ) {
        $geom_unary_functions = array(
            'IsEmpty' => 1,
            'IsSimple' => 1,
            'IsRing' => 1,
            'IsClosed' => 1,
        );
        $where = '';

        // Get details about the geometry functions
        $geom_funcs = Util::getGISFunctions($types, true, false);

        // If the function takes multiple parameters
        if(strpos($func_type, "IS NULL") !== false || strpos($func_type, "IS NOT NULL") !== false) {
            $where = Util::backquote($names) . " " . $func_type;
            return $where;
        } elseif ($geom_funcs[$geom_func]['params'] > 1) {
            // create gis data from the criteria input
            $gis_data = Util::createGISData($criteriaValues, $this->dbi->getVersion());
            $where = $geom_func . '(' . Util::backquote($names)
                . ', ' . $gis_data . ')';
            return $where;
        }

        // New output type is the output type of the function being applied
        $type = $geom_funcs[$geom_func]['type'];
        $geom_function_applied = $geom_func
            . '(' . Util::backquote($names) . ')';

        // If the where clause is something like 'IsEmpty(`spatial_col_name`)'
        if (isset($geom_unary_functions[$geom_func])
            && trim($criteriaValues) == ''
        ) {
            $where = $geom_function_applied;

        } elseif (in_array($type, Util::getGISDatatypes())
            && ! empty($criteriaValues)
        ) {
            // create gis data from the criteria input
            $gis_data = Util::createGISData($criteriaValues, $this->dbi->getVersion());
            $where = $geom_function_applied . " " . $func_type . " " . $gis_data;

        } elseif (strlen($criteriaValues) > 0) {
            $where = $geom_function_applied . " "
                . $func_type . " '" . $criteriaValues . "'";
        }
        return $where;
    }

    /**
     * Return the where clause for query generation based on the inputs provided.
     *
     * @param mixed  $criteriaValues Search criteria input
     * @param string $names          Name of the column on which search is submitted
     * @param string $types          Type of the field
     * @param string $func_type      Search function/operator
     * @param bool   $unaryFlag      Whether operator unary or not
     * @param bool   $geom_func      Whether geometry functions should be applied
     *
     * @return string generated where clause.
     */
    private function _getWhereClause($criteriaValues, $names, $types,
        $func_type, $unaryFlag, $geom_func = null
    ) {
        // If geometry function is set
        if (! empty($geom_func)) {
            return $this->_getGeomWhereClause(
                $criteriaValues, $names, $func_type, $types, $geom_func
            );
        }

        $backquoted_name = Util::backquote($names);
        $where = '';
        if ($unaryFlag) {
            $where = $backquoted_name . ' ' . $func_type;
        } elseif (strncasecmp($types, 'enum', 4) == 0 && (! empty($criteriaValues) || $criteriaValues[0] === '0')) {
            $where = $backquoted_name;
            $where .= $this->_getEnumWhereClause($criteriaValues, $func_type);

        } elseif ($criteriaValues != '') {
            // For these types we quote the value. Even if it's another type
            // (like INT), for a LIKE we always quote the value. MySQL converts
            // strings to numbers and numbers to strings as necessary
            // during the comparison
            if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types)
                || mb_strpos(' ' . $func_type, 'LIKE')
            ) {
                $quot = '\'';
            } else {
                $quot = '';
            }

            // LIKE %...%
            if ($func_type == 'LIKE %...%') {
                $func_type = 'LIKE';
                $criteriaValues = '%' . $criteriaValues . '%';
            }
            if ($func_type == 'REGEXP ^...$') {
                $func_type = 'REGEXP';
                $criteriaValues = '^' . $criteriaValues . '$';
            }

            if ('IN (...)' != $func_type
                && 'NOT IN (...)' != $func_type
                && 'BETWEEN' != $func_type
                && 'NOT BETWEEN' != $func_type
            ) {
                return $backquoted_name . ' ' . $func_type . ' ' . $quot
                        . $GLOBALS['dbi']->escapeString($criteriaValues) . $quot;
            }
            $func_type = str_replace(' (...)', '', $func_type);

            //Don't explode if this is already an array
            //(Case for (NOT) IN/BETWEEN.)
            if (is_array($criteriaValues)) {
                $values = $criteriaValues;
            } else {
                $values = explode(',', $criteriaValues);
            }
            // quote values one by one
            $emptyKey = false;
            foreach ($values as $key => &$value) {
                if ('' === $value) {
                    $emptyKey = $key;
                    $value = 'NULL';
                    continue;
                }
                $value = $quot . $GLOBALS['dbi']->escapeString(trim($value))
                    . $quot;
            }

            if ('BETWEEN' == $func_type || 'NOT BETWEEN' == $func_type) {
                $where = $backquoted_name . ' ' . $func_type . ' '
                    . (isset($values[0]) ? $values[0] : '')
                    . ' AND ' . (isset($values[1]) ? $values[1] : '');
            } else { //[NOT] IN
                if (false !== $emptyKey) {
                    unset($values[$emptyKey]);
                }
                $wheres = array();
                if (!empty($values)) {
                    $wheres[] = $backquoted_name . ' ' . $func_type
                        . ' (' . implode(',', $values) . ')';
                }
                if (false !== $emptyKey) {
                    $wheres[] = $backquoted_name . ' IS NULL';
                }
                $where = implode(' OR ', $wheres);
                if (1 < count($wheres)) {
                    $where = '(' . $where . ')';
                }
            }
        } // end if

        return $where;
    }
}

Filemanager

Name Type Size Permission Actions
TableChartController.php File 7.17 KB 0644
TableGisVisualizationController.php File 6.78 KB 0644
TableIndexesController.php File 4.97 KB 0644
TableRelationController.php File 11.99 KB 0644
TableSearchController.php File 39.65 KB 0644
TableStructureController.php File 55.53 KB 0644