2013-02-05 61 views
1

我有一个使用oracle-db的大型php应用程序(纯粹是php,没有框架等)。 所有查询都这样执行:在查询字符串中转义'它甚至有可能吗?

oci_parse($conn_id,"insert into table (bla) values ('bla')"); 
oci_execute($stmt) 

我知道这是不好的!不需要指出像“使用绑定”或类似的东西。我知道,但我无法改变这一点。

我们都知道的是,你必须转义角色。 这个问题特别是关于' charcter。

我有许多的疑问是这样的:

$query = "INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub', 'mimi'm', 'mu's'c'hle')"; 
$query2 = "UPDATE table SET field1 = 'bla,bla', field2 = 'blub', field3 = 'mimi'm', field4 = 'mu's'c'hle' WHERE field5 = 'lol'zj'd'" 

当然,通常他们没有那么多的'中 - 但那只是为了演示。

现在的问题: 有什么办法来验证/转义整个查询字符串在PHP?不管我怎么想,我都无法想到/找到一种方法来实现这一目标。

很明显,很容易构建查询串,仅通过更换'''之前转义所有值 - 但有可能当你只有整个查询作为字符串(如上面的例子)?我个人想不出一个“通用解决方案”...

+0

所以你不想使用PDO,但想要的好处?甚至不会考虑,[oci_bind_by_name()](http://www.php.net/manual/en/function.oci-bind-by-name.php) – ficuscr

+0

我梦想使用这个 - 我没有写过这个申请(我可能会自杀,如果Id有)...并且它不喜欢“哦,我可以改变它到PDO,只需要10个小时的工作......” –

+2

瑙,我听到你的声音。我的同情心。 – ficuscr

回答

2

我认为这是不溶于传统的手段,在查询的时候已经建成时间:

  1. 尝试只是一个斜线添加到每个撇号,当然是行不通的,因为你在逃避分隔符撇号以及“价值”撇号。
  2. 没有函数或正则表达式来确定哪些是值中的撇号,哪些是值分隔的撇号。
  3. 即使解析器也不会帮助你,因为解析器的一部分工作是告诉你何时查询具有无效的语法,但不能修复该语法;只要它碰到一个撇号不合适的位置,并且下面的字符不是逗号,它就会失败。

让我们把你的第二个例子的一部分:

field3 = 'mimi'm', field4 = 'mu's'c'hle' 

一个正常的查询分析器会看到field3'mini'后跟一个错误m,它需要一个逗号。这不是解析器设计用来处理的内容。

因此,假设我们写了一些自定义来处理这个问题。假设我们认为撇号后面没有逗号,这个撇号必须是价值的一部分。没关系,但是下一个撇号的意图是分隔符呢?

我们的代码如何知道撇号是否是分隔符,而不是实际包含撇号后跟逗号的值?实际上,该值可能包含与查询其余部分完全相同的内容! (此外,一旦我们以这种方式开始质疑查询本身的结构,我们将如何检测实际上无效的查询)。

TL;博士

在GIGO =垃圾进,垃圾出

你不能写(传统)软件进行梳理任意胡来!

+0

也许人工智能可能是一种选择? ;-P – leftclickben

+0

这就是我想要的。只是确认它不起作用。我有点类似的想法......也很有趣,看起来你是唯一能够阅读而不只是写点东西的人。 –

+0

其实我希望有人_really smart_会来证明我错了...... – leftclickben

0

你可以使用只是做一个简单的str_replace()。 I.E. str_replace("'", "\'", $string);

编辑: 你也可以做

$str = "INSERT INTO table(field1, field2) 
         VALUES (
           replace(" . $value . ", Chr(39), Chr(39) & Chr(39)), 
           replace(" . $value . ", Chr(39), Chr(39) & Chr(39)) 
           );"; 

由于CHR(39)是指”。

+0

为什么倒票? 'addslashes'不是一个有效的答案吗? – ficuscr

+0

这将取代所有''',但他只想逃离''' –

+0

'里面的内容为什么downvotes?他是对的。替代方法:'preg_replace(“/'/”,“\'”,$ query_arg);' – Sammitch

-1
$query = "INSERT INTO table(field) Values('".addslashes("'")."')"; 

我认为这是failsave,或者甚至更好

$query = sprintf("INSERT INTO table(field) Values('%s')", addslashes("'")); 

,因为这是最容易liekely的情况下,阅读你想哪天扩展插件。

据我所知,如果您只想让字符串转义,那么您使用的是哪种风格的SQL并不重要,但为了防止addslashes在这里也能正常工作。 是的...有一些专门的SQL转义功能在PHP中,

And ..重读这个问题..只是有查询字符串,没有初始值是很难妥善逃避一切。

+0

这是正确的吗?想要说Oracle更像Postgres,当谈到引用转义...如果有什么可能[pg_escape_string](http://php.net/manual/en/function.pg-escape-string.php)? – ficuscr

0

如果我明白你的问题,它应该工作

$name = addslashes("mu's'c'hle"); 
$query = "INSERT INTO teste (teste) VALUES ('$name')"; 
+0

我不认为你了解这个问题。 – leftclickben

+0

为什么你给downvote?我的答案有什么问题? BBe建设性的,或者我会给你一个downvote到 – Heberfa

+0

你的回答没有解决这个问题。查询已经建立,值''mu's'c'hle“'不被称为离散值 - 它已经在查询中混乱了。此外,威胁不恰当地使用降价来进行个人报复的形式非常糟糕。特别是当你实际上甚至没有赢得这种特权的声望时。 – leftclickben

-1

除非你想要写的东西可以解释查询并确定错误是在然后以某种方式确定适当的解决办法是什么,有没有办法。此外,如果你这样做,你仍然没有解决你的更大的问题,这是sql注入。

+0

只需要清楚,正确的方法是在将数据放入字符串之前清理数据。 –

+0

反对票不支持。 他特别指出: 很明显,很容易构建查询串,仅通过'与'取代之前转义所有值 - 但有可能当你只有整个查询作为字符串(如上面的例子)?我个人无法想到一个“通用解决方案”...... –

2

好吧,这是DEFINETELY不failproof,甚至是优雅的,但它确实在给定的querys工作,作为一个这么说的“概念证明” ......

请不要在生产中使用的功能服务器..这将打破越早(不晚;))

<?php 


$query = "INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub','mimi'm','mu's'c'hle')"; 
$query2 = "UPDATE table SET field1 = 'bla,bla', field2 = 'blub', field3 = 'mimi'm', field4 = 'mu's'c'hle' WHERE field5 = 'lol'zj'd'"; 

function clean_given_query($qry) 
{ 
    if(strpos($qry , " VALUES ")) 
    { 
     //the easy way, since we know exactly how many fields we have here 
     $qra = explode('VALUES', $qry); 
     if(count($qra) == 2) 
     { 
      // qra[0] = "INSERT INTO table (field1, field2,field3,field4)" 
      // qra[1] = "('bla,bla','blub', 'mimi'm', 'mu's'c'hle')"; 
      $qtemp = explode('(', $qra[0]); 
      $qtemp = $qtemp[1]; // we can loose the insert -part for now 
      $fieldcount = count(explode(',',$qtemp)); // now we know how many fields we want to populate 
      $qra[1] = explode("','", $qra[1]); // dirty values.... 
      if(count($qra[1]) === $fieldcount) //make sure we have the correkt value count 
      { 
       $values = array(); 
       foreach($qra[1] as $i => $val) 
       { 
        if($i==0) 
         $val = substr($val, 3); // we know $val is a string and index 0 starts with (' which we need to remove! 
        if($i == count($qra[1])-1) // last item needs to be cropped at the end 
         $val = substr($val, 0, count($val)-3); //also a string as we know. 

        $val = addslashes($val); //escape the string according to your needs 
        $values[] = $val; 
       } 
       return $qra[0]." VALUES ('".implode("','", $values)."')"; 
      } 

     } 
    } 
    else if (strpos($qry, "SET")) 
    { 
     $qra = explode('=', $qry); 
     // $qra[0] = "UPDATE table SET field1"; 
     // $qra[1] = "'bla,bla', field2"; 
     $save = $qra[0]."='"; 

     foreach($qra as $i => $mixed) 
     { 
      if($i == 0) // qra[0] holds nothing to edit! 
       continue; 

      $parts = explode(',', $mixed); // [0] 'bla [1] bla' [2] field2 
      $nextfield = array_pop($parts); 

      $val = implode(',', $parts); // $val = 'bla,bla' 
      if(strpos($nextfield , "WHERE")) 
      { 
       list($val, $nextfield) = explode("WHERE",$nextfield); 
       $nextfield = " WHERE ".$nextfield; 
      } 
      $val = trim($val); 
      $val = substr($val, 1, count($val)-2); //$val bla,bla 
      $val = addslashes($val); // escape according to your needs 

      if($val!=="" and strpos($nextfield , "WHERE") === false) 
       $save .= $val."', ".$nextfield."='"; 
      elseif($val!=="" and strpos($nextfield , "WHERE")) 
       $save .= $val."' ".$nextfield."='"; 
      else 
      { 
       $val = trim($nextfield); 
       $val = substr($val, 1, count($val)-2); //$val bla,bla 
       $val = addslashes($val); // escape according to your needs 
       $save .= $val."'"; 
      } 
     } 
     return $save; 
    } 
} 

echo $query.PHP_EOL; 
echo clean_given_query($query).PHP_EOL; 

echo $query2.PHP_EOL; 
echo clean_given_query($query2).PHP_EOL; 

?> 

输出:

INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub','mimi'm','mu's'c'hle') 
INSERT INTO table (field1, field2,field3,field4) VALUES ('bla,bla','blub','mimi\'m','mu\'s\'c\'hle') 
UPDATE table SET field1 = 'bla,bla', field2 = 'blub', field3 = 'mimi'm', field4 = 'mu's'c'hle' WHERE field5 = 'lol'zj'd' 
UPDATE table SET field1 ='bla,bla', field2 ='blub', field3 ='mimi\'m', field4 ='mu\'s\'c\'hle' WHERE field5 ='lol\'zj\'d' 

随着一点点努力和正确的reg_exp,而不是简单的爆炸/内爆和适当的ES海角功能为您的需求,你可以建立一个功能,能够清洗给定的查询

+0

哈哈老兄,这是相当令人印象深刻,尤其是因为它看起来像你有一些工作要做书面......我很欣赏这一点,现在我不搞不清哪个标记正确的答案,因为您的解决方案确实工作...:d –

+0

@tenhouse,谢谢你..是的,因为我的第一个短(尤其是“不正确的问题回答”)的回答得到了downvoted我以为 - 就像妈妈告诉我 - 再试一次......这次更好;) – itsid

+0

是的,这很有趣。我认为它可能在问题的一小部分上起作用。有一些问题,正如@itsid所指出的那样。例如,如果逗号后面有一个空格,比如“value”,“value”(如果标有“脏值”的行,那里没有空格),我认为它不会起作用。我也想知道如何处理,其中包括这样的值的情况下(这是为了产生一个值,中间的单引号和逗号都“的价值”,输入部分查询) :“这是”,“实际上是一个单一的价值”。 – leftclickben

相关问题