Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] MySQL error при поисковом запросе (http://forum.oszone.net/showthread.php?t=276975)

qurbanoff@vk 02-02-2014 23:06 2301528

MySQL error при поисковом запросе
 
Есть сайт. Сайт работает на движке DataLife Engine 10.1
На сайте установлен модуль "поиск по дополнительным полям" называется "SearchXField v5.0"
Модуль поддерживает сортировку по одному полю содержащему только числовые значения (Цена, количество, год рождения и т.д.)

форма поиска настраивается вручную.
Например: если я хочу найти товара по диапазону цен то это будет выглядеть так


HTML код:

<form action="/" name="search_xf" method="GET">
<input type="hidden" name="do" value="search_xf" />
<input type="hidden" name="loc" value="1" />
Диапазон цен:
От <input type="text" name="int_start_price" />
 До <input type="text" name="int_end_price" />
</form>


Если значение полей между 100 и 200 то URL выглядет так:

_http://site.ru//sf/int_start_price:100/int_end_price:200
Проблем нет!

Проблема в том что если в поле диапазона цен в место цифр написать текс например:Москва при этом URL выглядет так:
_http://site.ru//sf/int_start_price:Москва/int_end_price:200
то запрос выдает MySQL error
Код ошибки такой:

HTML код:

MySQL error in file: /engine/modules/show.short.php at line 64
Error Number: 1054
The Error returned was:
Unknown column 'Москва' in 'where clause'
SQL query:

SELECT id, autor, date, short_story, SUBSTRING(full_story, 1, 15) as full_story, xfields, title, category, alt_name, comm_num, allow_comm, approve, tags FROM ad_post where SUBSTRING_INDEX( SUBSTRING_INDEX( xfields, 'price|', -1 ) , '||', 1 )>Москва AND SUBSTRING_INDEX( SUBSTRING_INDEX( xfields, 'price|', -1 ) , '||', 1 )<200 AND approve AND date < '2014-02-02 13:53:54' ORDER BY date+0 DESC LIMIT 0,10

Помогите решить проблему..

Заранее огромное спасибо.

PHP код который обрабатыват данные:

PHP код:

<?php

if (!defined('DATALIFEENGINE')) {
    die(
"Hacking attempt!");
}

$disables = array( 'do''cstart''page''loc''news_direction_by''news_sort_by' );
$request $_SERVER['REQUEST_URI'];
$query_string $_SERVER['QUERY_STRING'];

if (
$config['allow_alt_url'] == 'yes')
{
    if (
$_GET['loc'])
    {
        
$location '';
        foreach (
$_GET as $key => $value)
        {
            if ( 
$key != 'do' && $key != 'loc' && !is_array($value)){
                
$location .= $key ':' $value '/';
            }else if(
is_array($value)){
                
$location .= $key ':' implode(";"$value) . '/';
            }
        }

        
header ("Location: $config[http_home_url]sf/$location");
    }

    
$tmp_array explode('/'$_GET['q']);
    
$in_array '';

    unset(
$_GET);
    
$_GET['do'] = 'search_xf';
    
$request substr($request1);
    
    foreach(
$tmp_array as $value)
    {
        if (
$value != '')
        {
            
$in_array explode(":"$value);
            
$_GET[$in_array[0]] = $in_array[1];
            if(
$in_array[0] == 'page')
                
$cstart $in_array[1];
        }
    }
}

$url_page $config['http_home_url'] . $request;

if(
$_GET['page'] > 1){
    
$url_page preg_replace"/(page:[0-9]+\\/|cstart:[0-9]+)/"""$url_page );
}else{
    
$url_page preg_replace"/(\\/page:[0-9]+\\/|\\/cstart:[0-9]+)/"""$url_page );
}

if(
strpos($query_string'cstart') !== false)
{
    
$query_string preg_replace'/cstart=[0-9]+/'""$query_string );
    
$query_string substr($query_string1);
}
    
$user_query str_replace("&","&amp;",$query_string);

if (
$cstart) {
    
$cstart $cstart 1;
    
$cstart $cstart $config['news_number'];
}

$newsmodule true;

if (isset(
$_GET['news_sort_by'])) $news_sort_by $_GET['news_sort_by'];
else 
$news_sort_by 'date';
    
if (isset(
$_GET['news_direction_by'])) $news_direction_by $_GET['news_direction_by'];
else 
$news_direction_by 'DESC';

if (
$news_sort_by != 'date')
    
$select ", SUBSTRING_INDEX( SUBSTRING_INDEX( xfields,  '{$news_sort_by}|', -1 ) ,  '||', 1 ) as $news_sort_by";


$searchQuery = array();
$searchEngine $_GET;

foreach (
$searchEngine as $key => $value
{
    if (!
in_array($key$disables) and $value !="" and $value != NULL
    {
        
preg_match_all('#int_(.*)_(.*)#'$key$matchesPREG_SET_ORDER);
        if(
$matches)
        {
            if(
$matches[0][1]=='start')
            {
                
$searchQuery[] = "SUBSTRING_INDEX( SUBSTRING_INDEX( xfields,  '{$matches[0][2]}|', -1 ) ,  '||', 1 )>$value";    
            }
            else
            {
                
$searchQuery[] = "SUBSTRING_INDEX( SUBSTRING_INDEX( xfields,  '{$matches[0][2]}|', -1 ) ,  '||', 1 )<$value";
            }
        } 
        else
        {
            
// if(strpos($_SERVER['REQUEST_URI'], "?do=searchfields") || strpos($_SERVER['REQUEST_URI'], '/sf/'))
            // {
                // $value = $db->safesql(htmlspecialchars(stripslashes($value)));
            // }
            // else
            // {
                // $value = iconv("utf-8","windows-1251",$db->safesql(htmlspecialchars(stripslashes($value))));
            // }
            
if ($key != 'category')
            {
                if(
strpos($value";") === false)
                {
                    
$searchArr = array($key$value);
                    
$searchQuery[] = "xfields LIKE '%" implode('|'$searchArr) . "%'";
                }else{
                    
$searchRes explode(";"$value); 
                    foreach(
$searchRes as $kent){
                        
$searchArr = array($key$kent); 
                        
$searchLS[] = "xfields LIKE '%" implode('|'$searchArr) . "%'";
                    }
                    
$searchRes implode(" OR "$searchLS);
                    
$searchQuery[] = '(' .$searchRes')';
                    
                }
                
            }
            else
            {
                if (
$config['allow_multi_category'] == 'yes')
                {
                    
$searchQuery[] = "category regexp '[[:<:]]( $value  )[[:>:]]'";
                }
                else
                {
                    
$searchQuery[] = "category = '$value'";
                }
            }
        }
    }
}

unset(
$matches);
if(
$searchQuery)
    
$where .= implode(' AND ',$searchQuery)." AND";

$sql_select "SELECT id, autor, date, short_story, SUBSTRING(full_story, 1, 15) as full_story, xfields, title, category, alt_name, comm_num, allow_comm  $select FROM " PREFIX "_post where {$where} approve" $where_date " ORDER BY " $news_sort_by "+0 " $news_direction_by " LIMIT " $cstart "," $config['news_number'];  
$sql_count "SELECT COUNT(*) as count FROM " PREFIX "_post where {$where} approve" $where_date;
$allow_active_news true;

?>


Sham 03-02-2014 11:44 2301718

это уязвимость на sql-injection.
подразумевается (вроде бы), что $value число, но не проверяется и не приводится к типу int. Сделайте хотя бы intval($value) или в условии and is_numeric($value).
Цитата:

Цитата qurbanoff@vk
$searchEngine = $_GET;
foreach ($searchEngine as $key => $value)
{
if (!in_array($key, $disables) and $value !="" and $value != NULL)
{
preg_match_all('#int_(.*)_(.*)#', $key, $matches, PREG_SET_ORDER);
if($matches)
{
if($matches[0][1]=='start')
{
$searchQuery[] = "SUBSTRING_INDEX( SUBSTRING_INDEX( xfields, '{$matches[0][2]}|', -1 ) , '||', 1 )>$value";
}
else
{
$searchQuery[] = "SUBSTRING_INDEX( SUBSTRING_INDEX( xfields, '{$matches[0][2]}|', -1 ) , '||', 1 )<$value";
}
}
else »


qurbanoff@vk 03-02-2014 12:00 2301723

Цитата:

Цитата Sham
is_numeric($value) »

А что делать если форма поиска такой?
в БД и есть текстовые значении которые производится поиск

<form action="/" name="search_xf" method="GET">
<input type="hidden" name="do" value="search_xf" />
<input type="hidden" name="loc" value="1" />
Диапазон цен:
От <input type="text" name="int_start_price" />
До <input type="text" name="int_end_price" />

<select name="cat" class="find3">
<option value=""></option>
<option value="Продажа">Продажа</option>
<option value="Покупка">Покупка</option>
</select>

</form>

Sham 03-02-2014 14:25 2301796

повторюсь, приведённый код уязвимый, поскольку не вижу, чтобы данные экранировались перед вставкой в запрос.
Цитата:

Цитата qurbanoff@vk
А что делать если форма поиска такой?
в БД и есть текстовые значении которые производится поиск »

очевидно, там где name="int_* подразумевается числовой тип. В остальных случаях вставляется как строка. То бишь пробуйте разные name. Например name="category" ищет по полю category
Цитата:

Цитата qurbanoff@vk
if ($config['allow_multi_category'] == 'yes')
{
$searchQuery[] = "category regexp '[[:<:]]( $value )[[:>:]]'";
}
else
{
$searchQuery[] = "category = '$value'";
} »

по движку конкретно ничего не могу сказать.

qurbanoff@vk 03-02-2014 14:51 2301811

Sham,
Проблему решил с помошью добавлением сторк

PHP код:

is_numeric $value ) && $value = ( (int) $value ); 

над

PHP код:

$searchQuery[] = "SUBSTRING_INDEX( SUBSTRING_INDEX( xfields, '{$matches[0][2]}|', -1 ) , '||', 1 )>$value"

и

PHP код:

$searchQuery[] = "SUBSTRING_INDEX( SUBSTRING_INDEX( xfields,  '{$matches[0][2]}|', -1 ) ,  '||', 1 )<$value"

это безопасно ?

Sham 03-02-2014 15:36 2301842

после
Цитата:

Цитата qurbanoff@vk
if($matches)
{ »

$value = (int) $value;

в остальных случаях $value обработайте этим (или подобным, что используется в движке).

qurbanoff@vk 03-02-2014 16:09 2301859

Спасибо вам огромное.
Еще один вопрос.
Если в диапазоне цен указать от 100 до 200 тогда товары с ценой 100 и 200 не отображается... отображается интервал с 101 до 199.
В чем может быть проблема?

Sham 03-02-2014 16:19 2301869

Цитата:

Цитата qurbanoff@vk
>$value »

>=$value и ниже <=$value в запросах

Цитата:

Цитата qurbanoff@vk
{$matches[0][2]} »

это тоже не обработано. лучше всё переделать с нуля, так не годится...


Время: 20:31.

Время: 20:31.
© OSzone.net 2001-