lib/SafeSQL.php
function query($query_string, $query_vars)
    {
        $app = \FelixOnline\Base\App::getInstance();
        $link_id = $app['db']->dbh;

        if(is_array($query_vars)) {

            $_var_count = count($query_vars);

            if($_var_count != preg_match_all('!%[sSiIfFcClLqQnN]!', $query_string, $_match)) {
                $this->_error_msg('unmatched number of vars and % placeholders: ' . $query_string);
            }

            // get string position for each element
            $_var_pos = array();
            $_curr_pos = 0;
            for( $_x = 0; $_x < $_var_count; $_x++ ) {
                $_var_pos[$_x] = strpos($query_string, $_match[0][$_x], $_curr_pos);
                $_curr_pos = $_var_pos[$_x] + 1;
            }
            // build query from passed in variables, escape them
            // start from end of query and work backwards so string
            // positions are not altered during replacement
            $_last_removed_pos = null;
            $_last_var_pos = null;
            for( $_x = $_var_count-1; $_x >= 0; $_x-- ) {
                if(isset($_last_removed_pos) && $_last_removed_pos < $_var_pos[$_x]) {
                    // already removed, skip
                    continue;
                }
                // escape string
                $query_vars[$_x] = $this->_sql_escape($link_id, $query_vars[$_x]);
                if(in_array($_match[0][$_x], array('%S','%I','%F','%C','%L','%Q','%N'))) {
                    // get positions of [ and ]
                    if(isset($_last_var_pos))
                    $_right_pos = strpos($query_string, ']', $_last_var_pos);
                    else
                    $_right_pos = strpos($query_string, ']', $_var_pos[$_x]);

                    // no way to get strpos from the right side starting in the middle
                    // of the string, so slice the first part out then find it
                    $_str_slice = substr($query_string, 0, $_var_pos[$_x]);
                    $_left_pos = strrpos($_str_slice, '[');

                    if($_right_pos === false || $_left_pos === false) {
                        $this->_error_msg('missing or unmatched brackets: ' . $query_string);
                    }
                    if(in_array($query_vars[$_x], $this->_drop_values, true)) {
                        $_last_removed_pos = $_left_pos;
                        // remove entire part of string
                        $query_string = substr_replace($query_string, '', $_left_pos, $_right_pos - $_left_pos + 1);
                        $_last_var_pos = null;
                    } else if ($_x > 0 && $_var_pos[$_x-1] > $_left_pos) {
                        // still variables left in brackets, leave them and just replace var
                        $_convert_var = $this->_convert_var($query_vars[$_x], $_match[0][$_x]);
                        $query_string = substr_replace($query_string, $_convert_var, $_var_pos[$_x], 2);
                        $_last_var_pos = $_var_pos[$_x] + strlen($_convert_var);
                    } else {
                        // remove the brackets only, and replace %S
                        $query_string = substr_replace($query_string, '', $_right_pos, 1);
                        $query_string = substr_replace($query_string, $this->_convert_var($query_vars[$_x], $_match[0][$_x]), $_var_pos[$_x], 2);
                        $query_string = substr_replace($query_string, '', $_left_pos, 1);
                        $_last_var_pos = null;
                    }
                } else {
                    $query_string = substr_replace($query_string, $this->_convert_var($query_vars[$_x], $_match[0][$_x]), $_var_pos[$_x], 2);
                }
            }
        }

        return $query_string;

    }
function query($query_string, $query_vars)
    {
        $app = \FelixOnline\Base\App::getInstance();
        $link_id = $app['db']->dbh;

        if(is_array($query_vars)) {

            $_var_count = count($query_vars);

            if($_var_count != preg_match_all('!%[sSiIfFcClLqQnN]!', $query_string, $_match)) {
                $this->_error_msg('unmatched number of vars and % placeholders: ' . $query_string);
            }

            // get string position for each element
            $_var_pos = array();
            $_curr_pos = 0;
            for( $_x = 0; $_x < $_var_count; $_x++ ) {
                $_var_pos[$_x] = strpos($query_string, $_match[0][$_x], $_curr_pos);
                $_curr_pos = $_var_pos[$_x] + 1;
            }
            // build query from passed in variables, escape them
            // start from end of query and work backwards so string
            // positions are not altered during replacement
            $_last_removed_pos = null;
            $_last_var_pos = null;
            for( $_x = $_var_count-1; $_x >= 0; $_x-- ) {
                if(isset($_last_removed_pos) && $_last_removed_pos < $_var_pos[$_x]) {
                    // already removed, skip
                    continue;
                }
                // escape string
                $query_vars[$_x] = $this->_sql_escape($link_id, $query_vars[$_x]);
                if(in_array($_match[0][$_x], array('%S','%I','%F','%C','%L','%Q','%N'))) {
                    // get positions of [ and ]
                    if(isset($_last_var_pos))
                    $_right_pos = strpos($query_string, ']', $_last_var_pos);
                    else
                    $_right_pos = strpos($query_string, ']', $_var_pos[$_x]);

                    // no way to get strpos from the right side starting in the middle
                    // of the string, so slice the first part out then find it
                    $_str_slice = substr($query_string, 0, $_var_pos[$_x]);
                    $_left_pos = strrpos($_str_slice, '[');

                    if($_right_pos === false || $_left_pos === false) {
                        $this->_error_msg('missing or unmatched brackets: ' . $query_string);
                    }
                    if(in_array($query_vars[$_x], $this->_drop_values, true)) {
                        $_last_removed_pos = $_left_pos;
                        // remove entire part of string
                        $query_string = substr_replace($query_string, '', $_left_pos, $_right_pos - $_left_pos + 1);
                        $_last_var_pos = null;
                    } else if ($_x > 0 && $_var_pos[$_x-1] > $_left_pos) {
                        // still variables left in brackets, leave them and just replace var
                        $_convert_var = $this->_convert_var($query_vars[$_x], $_match[0][$_x]);
                        $query_string = substr_replace($query_string, $_convert_var, $_var_pos[$_x], 2);
                        $_last_var_pos = $_var_pos[$_x] + strlen($_convert_var);
                    } else {
                        // remove the brackets only, and replace %S
                        $query_string = substr_replace($query_string, '', $_right_pos, 1);
                        $query_string = substr_replace($query_string, $this->_convert_var($query_vars[$_x], $_match[0][$_x]), $_var_pos[$_x], 2);
                        $query_string = substr_replace($query_string, '', $_left_pos, 1);
                        $_last_var_pos = null;
                    }
                } else {
                    $query_string = substr_replace($query_string, $this->_convert_var($query_vars[$_x], $_match[0][$_x]), $_var_pos[$_x], 2);
                }
            }
        }

        return $query_string;

    }
/*======================================================================*\
Function: query
Purpose:  process the query string
\*======================================================================