dポイントプレゼントキャンペーン実施中!

form(POST)で変数をSQL文のinsertを用いてDBにいれていました。

ある日、アポストロフィ(シングルクォーテーション)の入っている変数があった場合、insert自体がうまくいっておらず、レコードが作られていないことに気づきました。


mysql_connect 以降 insert 以前に、
「mysql_real_escape_stringaddslashes」をいれることで、シングルクォーテーションも
問題なくinsertされるようになりましたが、半角エンマーク(バックスラッシュ?)を入れた場合にその文字が消えてDBに格納されます。
エスケープの記号とみなされてしまいます。

たとえば商品の値段として「\100」と書こうとしても、「100」になってしまいます。

全角でも閲覧するには支障がないので、
str_replace('\','¥',$str); のように修正しようとしてもうまくいきませんでした。

エスケープにエスケープしようとして、
str_replace('\','\\',$str); のように修正しようとしてもうまくいきませんでした。


最悪addslashesに変えないとダメかと思っていますが、
どうもaddslashesのほうはセキュリティ上、前者に劣るとも聞きましたので、このままなんとか「mysql_real_escape_stringaddslashes」で行きたいのですが。

うまい方法があるでしょうか?

A 回答 (5件)

今現在、どういう手順でDBに格納されていますか?「mysql_real_escape_stringaddslashes」という関数はありませんが、mysql_real_escape_stringとaddslashesを両方通しているわけではありませんよね。

mysql_real_escape_stringのみということでよろしいでしょうか。

  ・http://jp2.php.net/manual/ja/function.mysql-real …

たとえば、下記のようなテストソースで確認すると、問題なくinsertされます。

<?php
mysql_connect('localhost', 'username', 'password');
mysql_select_db('database');
// リテラル
$sql = sprintf("insert into testtable (id, a, b) values (%d, '%s', '%s')",
1,
mysql_real_escape_string('\100'),
mysql_real_escape_string('it\'s fine day'));
mysql_query($sql) or die(mysql_error());
// 変数
$id = 2;
$a = '\123,456';
$b = 'it\'s rainy day';
$sql = sprintf("insert into testtable (id, a, b) values (%d, '%s', '%s')",
$id,
mysql_real_escape_string($a),
mysql_real_escape_string($b));
mysql_query($sql) or die(mysql_error());
// 結果確認
$sql = "select * from testtable";
$res = mysql_query($sql) or die(mysql_error());
while ($row = mysql_fetch_array($res)) {
print "<pre>";
print_r($row);
print "</pre>";
print "<hr>";
}

この回答への補足

>mysql_real_escape_stringとaddslashesを両方通しているわけではありませんよね。mysql_real_escape_stringのみということでよろしいでしょうか。

ごめんなさいコピペミスです。
mysql_real_escape_stringのみです。

こんなソースです。
※magic_quotes_gpc=off
※文字コードはUTF-8
※サーバーはさくらインターネット
-------------

if(get_magic_quotes_gpc()) {
function mres($str){
return mysql_real_escape_string(stripslashes($str));
}
}else{
function mres($str){
return mysql_real_escape_string($str);
}
}
$Pt_data= mres($_POST['変数']);
$Pt_data= mb_convert_kana($Pt_data, "K", "UTF-8");
$Pt_data= preg_replace('/&/','&',$Pt_data);

$sql = "INSERT INTO `tb` ('$Pt_data') VALUES ('$Pt_data')";
$ret = mysql_query($sql);

if($ret){print "<p">入力できました</p>";}
else{print "<p"></p>";}

---------------

formの変数に
「\100\\100」といれると、「100\100」と表示されます。

補足日時:2011/10/18 16:53
    • good
    • 0
この回答へのお礼

ごめんなさい。

なぜかできました。

質問にあげたソースより前のほうに、
別の作業で(メール送信用)

if (get_magic_quotes_gpc()==0){$var = stripslashes($var);}

とかいてあったたところを

if (get_magic_quotes_gpc()){$var = stripslashes($var);}

に直したところ、Mysqlのほうも直りました。原因はわかりません・・・。

お礼日時:2011/10/18 17:12

#2です。



>if (get_magic_quotes_gpc()==0){$var = stripslashes($var);}
>
>とかいてあったたところを
>
>if (get_magic_quotes_gpc()){$var = stripslashes($var);}
>
>に直したところ、Mysqlのほうも直りました。原因はわかりません・・・。

get_magic_quotes_gpcのチェックが逆ですよね。最初のソースではmagoc_quotes_gpcがoff(つまり、== 0 が真)の環境なのに、stripslashesを通してしまっているので「\」は落ちて当然です(magic_quotes_gpcで付加されたと判断されてしまう)。この時点でおかしくなっているわけですから、SQL文を生成する前の段階の各変数の値をprintしていればmysqlへ格納するときのescape処理の問題じゃないことはわかったと思います。


とはいえ、格納前には(addslashesではなく)mysql_real_escape_stringを通すべきですから、結果的には良かったのかもしれません。

この回答への補足

そうなんです、
>if (get_magic_quotes_gpc()==0){$var = stripslashes($var);}

は完全に逆ですよね、もしつけるなら
 if (get_magic_quotes_gpc()==0){$var = addslashes($var);}
 をしたうえで、エスケープ?

それは完全にミスだったのですが、


私が疑問なのは、メール送信用に記述したものと
完全に別のソースなのになぜか
>if (get_magic_quotes_gpc()==0){$var = stripslashes($var);}
を通過しているみたいなんです。
通過した後で、あらためて$_POST[変数]と読み込んでいるのにもかかわらず。です。

補足日時:2011/10/19 11:16
    • good
    • 0

私だったらmysql_real_escape_string()はデータベースに突っ込む直前に掛けます。


つまり
$Pt_data= mres($_POST['変数']);
$Pt_data= mb_convert_kana($Pt_data, "K", "UTF-8");
$Pt_data= preg_replace('/&/','&',$Pt_data);
ではなく、
$Pt_data = $_POST['変数'];
$Pt_data= mb_convert_kana($Pt_data, "K", "UTF-8");
$Pt_data= preg_replace('/&/','&',$Pt_data);
$Pt_data= mres($Pt_data);
てな順番で。
    • good
    • 0
この回答へのお礼

ありがとうございます。
本件とは直接関係なさそうですが、このやり方も参考にします!

お礼日時:2011/10/19 11:18

↓これを回答した(もはや質問者さんとの交換日記状態で誰も読まないと思う)関係で、ちょっと この質問にも回答させていただきたいと思います。


http://questionbox.jp.msn.com/qa7060370.html

んで、#2の補足 見ました。

↓ここ

if(get_magic_quotes_gpc()) {
function mres($str){
return mysql_real_escape_string(stripslashes($str));
}

ん?stripslashes??
ここで円マーク 削っちゃってません?

あー、俺が これ書いてる間に #2にお礼もついてますね。

> に直したところ、Mysqlのほうも直りました。原因はわかりません・・・。

stripslashes() を通ってないから直ったんですよー。っと思います。

この回答への補足

交換日記、SQLインジェクションなどの勉強になりそうなので
また時間をとって読んでみます。
みなさまへのお礼はまた改めて。今日は野球を見せてください。

補足日時:2011/10/18 19:56
    • good
    • 0

> どうもaddslashesのほうはセキュリティ上、前者に劣るとも聞きましたので、


どこかで聞きかじった情報じゃなくて、公式ドキュメントを見れば済む話なのに…が率直な感想です。

mysql_real_escape_string
http://php.net/manual/ja/function.mysql-real-esc …
引用
mysql_real_escape_string() は、MySQL のライブラリ関数 mysql_real_escape_string をコールしています。 これは以下の文字について先頭にバックスラッシュを付加します。 \x00, \n, \r, \, ', " そして \x1a.

addslashes
http://php.net/manual/ja/function.addslashes.php
引用
データベースへの問い合わせなどに際してクォートされるべき文字の前に バックスラッシュを挿入した文字列を返します。 クォートされるべき文字とは、シングルクォート('), ダブルクォート("),バックスラッシュ (\) ,NUL (NULL バイト) です。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!