<   2009年 09月 ( 26 )   > この月の画像一覧
(Linux)yum updateが失敗する
(会社辞めるとなかなか書くネタがなくなることを感じてる今日この頃です。)

Cent OS で yum update をしようとしたら下記のようなエラーがでました。

TypeError : unsubscriptable object


とりあえずググってみるとNire.Com:CentOS 5 の yum に失敗 (TypeError: unsubscriptable object)でどんぴしゃな回答が。。。


yum clean metadata
とするといいようです。
たしかに、上記コマンド実行した後、 yum update すると無事にアップデートが終了しました。
[PR]
by jehoshaphat | 2009-09-29 01:23 | Linux | Trackback | Comments(0)
(PHP)XServerでXOOPSが真っ白に。。。
レンタルサーバのXServer上で動かしてるXOOPSが真っ白になっているということで調査開始しました。

まず、PHPエラーを調べるために、phpMyAdmin で MySQL の xoops_config テーブル conf_name列= debug_mode レコードの conf_value の値を1にします。

これでリロードするとこんなエラーが。。

Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}'
in /home/ユーザ名/public_html/xoops/modules/Analyzer/preload/Preload.class.php on line 10

なんか文法エラーとか言ってます。

このファイルは更新した記憶はまったくないので、もしかしてと思って phpinfo で実行環境の情報を探ってみました。
すると、PHP5 で動かしてたはずなのに、PHP4 になってます。

とりあず、PHP5 に戻せば動くと思って、ServerPanel の "PHP Ver.切替" より PHP5 に戻しました。


その後なぜPHP5から4になってしまったかの調査です。

調べていくと、Xserver は PHP4 と 5 の切り替えは、public_html/.htaccess の中で

AddHandler x-httpd-php5 .php .phps

という定義で行っていることが分かりました。

つまり、この記述がないと PHP4 で動くみたいです。

そういえば、PEAR の include_path を設定するときにこの辺触ったので、その時にこの記述を上書きしてしまったことが今回の障害の原因のようです。
[PR]
by jehoshaphat | 2009-09-18 12:55 | PHP開発 | Trackback | Comments(0)
(PHP)携帯電話から取得したGPS位置情報から半径xxKm内のデータを探したい
(PHP)携帯電話でGPS位置情報取得したいの続きです。

最終的にしたいことは、携帯から取得したGPS座標から任意の距離内にある施設(DBに登録)を探したいということです。

DBに置いておく施設情報には、位置情報が入っていないといけないため、緯度、経度を入れておくフィールドを用意してやります。
今回は MySQL で、"latitude" , "longitude" という DOUBLE 型のフィールドを用意。また、"id","name" 列もあるとします。
で、携帯電話で計測した位置から半径5km以内のデータを探すという処理してます。
(なお、このソースはここの続きなので、"$lat" や "$lon" は携帯から取得した座標が入っているとします。)

//$lat,$lon は時小数点形式の緯度経度が入っているものとする
//DB接続は省略
 
//クエリ生成
$query = "SELECT * FROM store WHERE latitude IS NOT NULL AND longitude IS NOT NULL ";
//クエリ実行
$result = mysql_query($query);
//条件にあうデータを格納する配列
$findAry = array();
while ($row = mysql_fetch_assoc($result)) {
if (isset($lat) && isset($lon)){
//GPSからのクエリの場合距離計算(m)
$dist = distance( $lat , $lon , $row["latitude"] ,$row["longitude"] ,true);
//debug
//echo "dist:" . $dist . " lat:" . $row["latitude"] . " lot:" . $row["longitude"] . "<br>";
//指定距離内なら配列追加 (今回は5km)
if ($dist < 5000){
array_push($findAry ,array( "id" => $row["id"] ,
"name" => mb_convert_encoding(htmlspecialchars($row["name"]),"sjis-win" , "UTF-8") , //DB,PHPがUFT8のため携帯向けのshift-jisに変換
"lat" => $row["latitude"] ,
"lon" => $row["longitude"] , ));
}
}
}
//$findAryに結果が入ってるので、これをSmartyに渡すなり、そのまま出力したりする。
 
 
/**
* 2地点間の直線距離を求める(Hubenyの簡易式による)携帯電話GPSの測地系はwgs84なので世界測地系使用
* @param string $a_lati A地点の緯度(時小数点形式 33.000000)
* @param string $a_long A地点の経度(時小数点形式 132.000000)
* @param string $b_lati B地点の緯度(時小数点形式 33.000000)
* @param string $b_long B地点の経度(時小数点形式 132.000000)
* @return double 直線距離(メートル)
*/

function calc_distance($a_lati , $a_long , $b_lati , $b_long ) {
//ラジアンに変換
$a_long = deg2rad($a_long);
$a_lati = deg2rad($a_lati);
$b_long = deg2rad($b_long);
$b_lati = deg2rad($b_lati);
 
$latave = ($a_lati + $b_lati) / 2;
$latidiff = $a_lati - $b_lati;
$longdiff = $a_long - $b_long;
 
//子午線曲率半径
//$meridian = 6334834 / sqrt(pow(1 - 0.006674 * sin($latave) * sin($latave), 3)); //日本測地系
$meridian = 6335439 / sqrt(pow(1 - 0.006694 * sin($latave) * sin($latave), 3)); //世界測地系
 
//卯酉線曲率半径
//$primevertical = 6377397 / sqrt(1 - 0.006674 * sin($latave) * sin($latave)); //日本測地系
$primevertical = 6378137 / sqrt(1 - 0.006694 * sin($latave) * sin($latave)); //世界測地系
 
//Hubenyの簡易式
$x = $meridian * $latidiff;
$y = $primevertical * cos($latave) * $longdiff;
 
return sqrt($x * $x + $y * $y);
}


いろいろ試した結果、Google MAP API で計測した時の距離とどうも誤差があるようです。(Google Maps:地図から距離、方角方位、面積を得るっていうサイトで簡単に半径とか求められれます。)
それが少しではなく、結構あるんですよね。。。

まぁ時間あればこの誤差についても調べて見ようかと思います。



参考:
ぱふぅ家のホームページ:PHPで2地点間の直線距離を求める 位置計算はほぼこちらで作られた関数使わしてもらってます。
katyos開発室:PHPで2点間の距離を計算する(ヒュベニの公式)

緯度経度、距離計測WEBサービス:
Plus-α.net:緯度経度検索 地図上でクリックした位置の緯度経度を表示。
【R1web】地図上の直線距離計測ページv3-1 地図上の2点間の直線距離を計測。
2点間の直線距離がわかる距離計算サイト 2点間の距離計測。
[PR]
by jehoshaphat | 2009-09-17 17:19 | PHP開発 | Trackback | Comments(0)
(PHP)携帯電話でGPS位置情報取得したい
携帯電話でのGPS位置情報の取得方法です。(ほとんど参考元リンクまんまですが。。)

まず、Net_UserAgent_Mobile という PEAR クラスライブラリを使って、キャリア毎にGPS位置情報送信リンクを作成してやります。

今回は Docomo なら FOMA かつGPS機能付き携帯、ソフトバンクなら3G携帯、auはそのままという条件でリンクを作成してます。(auについては Net_UserAgent_Mobile で判断できる情報が少ないため)

で、携帯側でそのリンクを押下すると、GETパラメータで位置情報が渡されるので、それを計算しやすい時の小数点形式にするところまでのソースをのっけてます。

まず、位置情報送信リンク作成側のソースです。

require_once('Net/UserAgent/Mobile.php');
 
//位置情報のリンク
$linkGps = "";
//携帯電話判断 測地系はWGS84
$agent = Net_UserAgent_Mobile::singleton();
if($agent->isDoCoMo() && $agent->isFOMA() && $agent->isGPS() ){
//DocomoかつFOMAかつGPS端末のみ
$linkGps = '<a href="findstore.php" lcs>(docomo)位置情報から検索</a>';
}elseif($agent->isSoftbank() && $agent->isType3GC() ){
$linkGps = '<a href="location:gps?url=findstore.php">(ソフトバンク)位置情報から検索</a>';
}elseif($agent->isEZweb()){
$linkGps = '<a href="device:gpsone?url=http://realstyle.xsrv.jp/m/findstore.php&amp;ver=1&amp;datum=0&amp;unit=0">(au)位置情報から検索</a>';
}
//この後、$linkGps を表示してやります。


そして、パラメータ取得側のソースです。(EscapeHtmlSanitize関数については(PHP)XSSとSQLインジェクション対策を参考)
//携帯からの位置情報パラメータ取得
//docomo,au
if (isset($_GET["lat"]) && isset($_GET["lon"]) ){
$lat = EscapeHtmlSanitize( $_GET['lat']);
$lon = EscapeHtmlSanitize( $_GET['lon']);
}
//softbank
if (isset($_GET["pos"])){
//いっしょくたのパラメータを分割
$pos = EscapeHtmlSanitize( $_GET['pos'] ) ;
preg_match('/([N|S])(.+)([W|E])(.+)/', $pos, $match);
$lat = $match[2];
if($match[1]=='S') $lat = '-' . $lat;
$lon = $match[4];
if($match[3]=='W') $lon = '-' . $lon;
}
 
//位置情報を時の小数点形式に変換
if (isset($lat) && isset($lon) ){
$lat_array = split('[.]', $lat, 3);
$lon_array = split('[.]', $lon, 3);
if(count($lat_array)==3 && count($lon_array)==3){
if( $lat_array[0] >= 0){
$lat = ( ( $lat_array[2] / 60 ) + $lat_array[1] ) /60 + $lat_array[0];
}else{
$lat = ( ( $lat_array[2] / 60 ) + $lat_array[1] ) /60 + $lat_array[0] * -1;
$lat = -1 * $lat;
}
if($lon_array[0] >= 0){
$lon = ( ( $lon_array[2] / 60 ) + $lon_array[1] ) /60 + $lon_array[0];
}else{
$lon = ( ( $lon_array[2] / 60 ) + $lon_array[1] ) /60 + $lon_array[0] * -1;
$lon = -1 * $lon;
}
}
$lon = str_replace('+', '', $lon);
$lat = str_replace('+', '', $lat);
}



簡易位置情報や2Gの携帯とかはまた取得方法が違う用なので、それらも対応しようとすると厄介ですね。。。。


参考:
Utilz: 携帯位置情報(GPS):
GPS携帯 位置情報 基礎知識:
携帯の位置情報を取得する:
日々是作譜:DoCoMo、au、SoftbankのGPSで位置情報をphpで取得する方法 (このサイトが一番わかりやすかったかも)
[PR]
by jehoshaphat | 2009-09-17 16:30 | PHP開発 | Trackback | Comments(0)
(PHP)echoで変数デバッグしようとするとauで「リクエストされたページは表示できません」って怒られた
PHPでSmartyを使った携帯向けページを表示してたんですが、変数デバッグをしたいと思い、Smarty表示前に echo で変数をauの携帯で表示さすと、「リクエストされたページは表示できません」って怒られれます。
(PCでは普通に表示されます。)


で、調べてみると、携帯電話 WEBページ構築に関する PHP: 「リクエストされたページは表示できません」と表示されます。で答え載ってました。

<html></html>が必要みたいです。

あと、どっかのページにヘッダもあったほうがいいとあったので、こんな感じで解決です。
header("Content-Type: text/html; charset=Shfit_JIS");
echo "<html>";
echo "lon:" . $lon . "<br>";
echo "lat:" . $lat . "<br>";
echo "</html>";
die;
//この後Smarty

[PR]
by jehoshaphat | 2009-09-17 14:08 | PHP開発 | Trackback | Comments(0)
(PHP)XServerにPEARインストール
(PHP)携帯のキャリア振り分け方法で書いたように、PEARのNet_UserAgent_Mobileパッケージをレンタルサーバ上で使う予定です。
しかし、今回使用予定の共用レンタルサーバ(XServer)は PEAR が入っていません。

ということで、共用レンタルサーバへのPEARインストール方法探すとどんぴしゃなのがありました。
The Butterfly Effect:XServerにPEARをインストールする。です。(revolutionaryさんにほんと感謝です)

ほとんどここに書いてるようにやればできました。

手順的には、go-pear.phpを配備し、それをブラウザからたたき、PEARをインストールする場所と、PHPの実行ファイルのパス(XServerの場合 /usr/bin/php5 )を指定します。

PEARをインストールするパスが、public_html以外の場合は、パッケージのインストールがそのままでは出来ないため、いったんインストールした PEAR ディレクトリを FTP でダウンし、public_html 配下にUPし、ブラウザで index.php をたたくとパッケージ管理画面が表示できます。
ここでパッケージインストールすると、勝手に PEAR をインストールしたパス(ドキュメントルート以外でも)にパッケージのクラスファイルが作成されます。

で、インストールが終わったらパッケージインストールために置いておいた PEAR ディレクトリは消しておいたほうがセキュリティ上いいかもしれません。


後は include_path を通す作業です。

.htaccess でやる方法があるらしいんですが、これすると php_value が定義されていないって怒られてます。
その上、他のPHPアプリも動かなくなりました。


ということで、もう一つの php.ini で設定する方法を使うことにしました。

今回は sv50サーバー以降 なので、php.ini をFTPでアクセスしたときのルート(フルパスは/home/ユーザID/)に置きます。
中身はこんな感じ。

include_path = "/home/xxxx/xxxx.xsrv.jp/PEAR/PEAR"



(余談ですが、最近exciteブログの検索が早くなったような。。。
DBサーバ入れ替えたことがよかったんでしょうか。。。
いずれにせよ、昔のメモ探す時に助かります。)
[PR]
by jehoshaphat | 2009-09-17 11:57 | PHP開発 | Trackback | Comments(0)
(PHP)携帯のキャリア振り分け方法
ユーザーエージェントを使って、各キャリアを判断したいと思ってます。
できれば、GPSのありなしや 3G かどうかなども知りたいと思ってます。(今回の要件が、位置情報取得用のリンクを張るというものなので。。)

手で書く方法もあるんですが、面倒なので Net_UserAgent_Mobile という PEAR ライブラリを使うことにしました。

まず、開発用PCに Net_UserAgent_Mobile をインストールします。(PEARのインストール方法は、Windows環境に OPEN PNE 2.14.1をインストールしてみたの"■PEAR のインストール"を参考)
コマンドプロンプトで下記のように pear install コマンド叩くだけ。

pear install Net_UserAgent_Mobile-1.0.0
downloading Net_UserAgent_Mobile-1.0.0.tgz ...
Starting to download Net_UserAgent_Mobile-1.0.0.tgz (43,849 bytes)
............done: 43,849 bytes
install ok: channel://pear.php.net/Net_UserAgent_Mobile-1.0.0

使い方はいたって簡単でした。
こんな感じです。
require_once('Net/UserAgent/Mobile.php');
$agent = Net_UserAgent_Mobile::singleton();
if($agent->isDoCoMo() && $agent->isFOMA() && $agent->isGPS() ){
echo "Docomo and FOMA and GPS";
}elseif($agent->isSoftbank() && $agent->isType3GC() ){
echo "SoftBank and 3G";
}elseif($agent->isEZweb()){
echo "au";
}


FOMAかどうかやGPS(Docomoのみ)かどうかも判断できます。
どんな情報が判別できるかはぺんたん info:Net_UserAgent_Mobile 携帯判別PEARパッケージの使い方と注意点でわかりやすく表にまとめられています。

さて、問題はこの Net_UserAgent_Mobile をどうレンタルサーバで動かすかです。

それについては、(PHP)XServerにPEARインストールに書いてます。
[PR]
by jehoshaphat | 2009-09-15 18:05 | PHP開発 | Trackback | Comments(0)
(PHP)XSSとSQLインジェクション対策
今回 PHP と Smarty でモバイル向けWEBサイト作ってるんですが、やはりセキュリティ対策は講じないといけません。

とりあえず、XSS,SQLインジェクション対策としてサニタイズをしようかと思います。
(まぁモバイル機上ではスクリプト動くことはあんまりないと思うんですが、念のため。。)

まず、クロスサイトスクリプティング対策として、スクリプトに使われそうな文字をエスケープするという方法をとってます。
で、(CakePHP)$form->textareaはサニタイジングしてくれない!?でも使った h() 関数を使おうと思ったんですが、そんな関数無いって怒られます。
どうやら、h() って CakePHP オリジナルの関数なんですね。ってきり標準で入ってるのかと思ってました。。。

ということで、h() の実体である htmlspecialchars() でフォーム入力やDBから取得のタイミングでサニタイズします。

参考:
WEBデザイナーの為のXSS(クロスサイトスクリプティング)入門[to-R]


次にSQLインジェクション対策です。
こちらも基本的にはサイニタイズで対処することにします。
今回 MySQL を使ってるんですが、MySQLは基本的に一回にひとつのクエリしか発行できないため(クエリスタックができない)、他のRDMSのように ; で区切って別クエリを走らしてDBの情報を盗み出すみたいなことはできません。
それでも、テキストボックスに OR とかでクエリつながれたりしたら終わりです。

ということで、MySQLの場合もちゃんとしたサニタイズをしないといけません。

PHP の場合、各DB毎に専用にエスケープ関数が用意されています。(一部用意されてないRDBMSもあるようですが。。)
MySQL だと mysql_real_escape_string() という関数です。

この関数はDB接続がされてないと使えないので実際にクエリに値を埋め込むときに使ったほうがいいようですね。

また、すでにエスケープされているものに対し mysql_real_escape_string() 使うと2重エスケープで意味がなくなるので、ここも注意が必要です。
特にマジッククォート機能が有効の場合は、これを無効にするかエスケープを一旦取り除いてから処理したらいいようです。
この辺の情報は、MySQLとPHPにおけるSQLインジェクション対策についてで詳しく説明されてました。

firegoby » PHP+MySQLでSQLインジェクション対策によると、mysql_real_escape_string() を使う場合は、MySQL への文字コードの指定に、set names ではなく、mysql_set_charset() を使わないと意味が無いようです。
(set names と mysql_set_charset() については、(PHP)MySQLへの接続時SET NAMESは使わないほうがいいで書いてます。)
たぶん、この問題は(PHP)HTML側がShift-JISだと SET NAMES sjis でのMySQLクエリはおかしくなるとも関連してると思います。
mysql_set_charset() を使ってやるのがベータですが、それができないサーバの場合は、別文字コードに変換して処理してやるのがいいでしょう。
(どっちにしろ、set names sjis で Shift-JIS 使うと文字化けの問題も発生するので。。。)

MySQLにもプレースホルダ(プリペアードクエリとも言うらしい)があるみたいですが、mysqli や PEAR などの拡張モジュールやクラス使わないといけないので、いまいち使おうという気になりません。。。


ということで、XSS対策とSQLインジェクション対策の場合のDBアクセスを書いてみました。

//パラメータ取得 このときXSSサニタイズ
$findName = EscapeHtmlSanitize(trim(urldecode($_GET["findname"])));
$findTEL = EscapeHtmlSanitize(trim(urldecode($_GET["findtel"])));
 
 
//DB接続
$cn = DB_Connect();
if (! $cn ){die;}
 
//クエリ生成 このときSQLインジェクションのためのサニタイズ
$query = sprintf("SELECT * FROM tablename WHERE name LIKE '%s' AND tel = '%s' ",
SqlSanitize("%" . $findName . "%") ,
SqlSanitize("%" . $findTEL . "%") );
 
//クエリ実行
$result = mysql_query($query);
//結果出力
while ($row = mysql_fetch_assoc($result)) {
echo htmlspecialchars($row["name"]) . "<br>";
echo htmlspecialchars($row["tel"]) . "<br>";
}
 
//DB接続
function DB_Connect(){
$db_host = "localhost";
$db_user = "root";
$db_passwd = "passwd";
$db = mysql_connect($db_host,$db_user,$db_passwd);
if ( ! $db ){
return false;
}
// MySQL DB 選択
if (!(mysql_select_db("realstyle_web"))) {die;}
mysql_set_charset(文字コード , $db); //mysql_set_charset が使えないときでShift-JISの場合は、別文字コードに変換するのがいい。
return $db;
}
 
//XSSのサイニタイズとマジッククォート対策
function EscapeHtmlSanitize($inputStr){
//XSS対策(HTMLエスケープ)
$inputStr = htmlspecialchars($inputStr);
//マジッククォートの有り無し
if(get_magic_quotes_gpc()) {
//余計なエスケープ文字を取り除く
$inputStr = stripslashes( $inputStr );
}
return $inputStr;
}
 
function SqlSanitize($inputStr){
//SQLインジェクション対策
$inputStr = mysql_real_escape_string($inputStr);
return $inputStr;
}

たぶん↑で問題ないですよね?


参考:
@IT:今夜分かるSQLインジェクション対策
ThinIT:第1回:SQLインジェクションによるデータベース操作
mysql_real_escape_string ここの例 3. "うまいやり方" のクエリが参考になります。
[PR]
by jehoshaphat | 2009-09-15 18:03 | PHP開発 | Trackback(1) | Comments(0)
(PHP)HTML側がShift-JISだと SET NAMES sjis でのMySQLクエリはおかしくなる
PHPで Shift-JIS使うなってことは前から聞いてたんで、今まで使ってなかったんですが、今回は携帯向けってことで仕方なくHTML側でシフトJIS使うことになりました。

環境としては下記のような感じです。

MySQL<--->PHP<---->HTML(Smarty)
UTF-8 UTF-8 Shift-JIS

MySQLには MySQL Administrator を使ってテストデータを入れています。

問題に気づいたのは下記のような HTML 側のテキストエリアに入れた文字をDBで検索する部分を作っていたときでした。
●HTML側(文字コードは シフトJIS)
<form id="order" action="find.php" method="GET">
<input type="text" name="searchname" size="10" maxlength="100" >
<input type="submit" name="search" value="検索"><br>
</form>

●PHP側(find.php)
$findStr = trim(urldecode($_GET["searchname"]));
echo "入力データ:" . $findStr . "<br>";
//DB接続省略
mysql_query('SET NAMES sjis');
//クエリ生成
$query = sprintf("SELECT * FROM tablename WHERE name LIKE '%s' ",
mysql_real_escape_string($findStr ));
//クエリ実行
$result = mysql_query($query);
 
while ($row = mysql_fetch_assoc($result)) {
echo $row["store_name"] . "<br>";
}

で、DBに MySQL Administrator で name列に文字化けやすい代表文字である "表" という文字をいれ、上記のHTMLのテキストボックスに "表" といれ検索しました。
本来ならヒットしないといけないのに、ヒットしません。


いろいろググって見るとマジッククォートっていうものがあるようです。
詳細は後ほど書くとして、これはOFFになってるので、関係なさそうです。


おそらく Shift-JIS が悪いんだろうってことは予想ついてるんですが、それをはっきりさせるために、HTML側を EUC-JP にし、SET NAMES も EUC-JP(ujis) にしてやってみました。
すると、ちゃんとヒットします。

やはり Shift-JIS が関係してますね。


条件追加した後のクエリとかも除いてみましたが、特に問題なさげです。
さらにググるとDBへのデータ挿入で文字化けっていう事例が多いので、ためしに INSERT するクエリを作ってみました。
$findStr = trim(urldecode($_GET["searchname"]));
echo "入力データ:" . $findStr . "<br>";
//DB接続省略
mysql_query('SET NAMES sjis');
 
$query = sprintf("insert into tablename ( name ) values ( '%s')",
mysql_real_escape_string( $findStr ));
$result = mysql_query($query);
echo mysql_error();


これで、HTMLに"表"って入れてPHPからDBに登録してみました。
すると、下記のようなエラーが。。。

You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for
the right syntax to use near ''表\' , 1 )' at line


やっぱり、MySQL内でのクエリ実行時には勝手にエスケープされてます。

SET NAMES と mysql_set_charset は内部的に違う処理をしてるようです。
そこら辺は、symfony × MySQL × Shift_JIS: 0×5c関連:で詳しく説明されてました。
簡単に言うと、mysql_set_charset()を使った場合はmysqlコネクションオブジェクトに文字コードを設定するため、Shift-JISの2バイト目の0x5cをエスケープしたりしないようです。

MSN相談箱:MySQL5.1の文字化けにも SET NAMES ではなく mysql_set_charset() を使うように提案されています。

ただ、今回使うレンタルサーバはPHPのバージョンが5.1のため mysql_set_charset() が使用できません。


ということで、どっかで書いていたようにGETやPOSTの値を別の文字コードに変換して、SET NAMES のその文字コードでやってやるという方向に落ち着きました。
こんな感じです。
$findStr = mb_convert_encoding(trim(urldecode($_GET["searchname"]) , "EUC-JP", "SJIS"));
//DB接続省略
mysql_query('SET NAMES ujis');
$query = sprintf("insert into tablename ( name ) values ( '%s')",
mysql_real_escape_string( $findStr ));
$result = mysql_query($query);
echo mysql_error();


ただ、上記の場合 Shift-JIS から EUC-JP に変換してますが、これを UTF-8 に変換するときはまた注意が必要のようです。
その場合は、"SJIS" では無く "sjis-win" を使うのがベータみたいですね。
mb_convert_encoding( $string , "UTF-8", "sjis-win");


ここら辺の話は、下記サイトに乗ってました。
-OASIS- - 今日のメモ「mb_convert_encodingの文字化け(PHP)」
地方で活動するweb制作者の日々を綴るblog:PHPで UTF-8←→SJIS の変換を行う場合の注意
( しゃいん☆のブログ ):[php] mb_convert_encoding と UTF-8 の誤変換問題


さて、途中でチラッと出てきたマジッククォートですが、これが有効になってると Shift-JIS の場合さらにややこしくなるようです。
(PHP.ini では magic_quotes_gpc という項目で設定できます。)
レンタルサーバによってはこれが on になっているところが多いんですよね。(まぁセキュリティ対策といえば確かにそうかもしれません)


マジッククォートが有効になっていると GET,POST,Cookie でのユーザからサーバに来る文字の中に、'(シングルクオート)、" (ダブルクオート)、\(バックスラッシュ) 、NULL があれば自動的にバックスラッシュでエスケープするようです。

で、HTML側がShift-JISだと、文字の2バイト目の値が 0x5c だと、これをバックスラッシュとして勘違いし、勝手にエスケープ(バックスラッシュをさらに加える)するようです。(文字コード 0x5c 単体は\と定義されてるため)

たとえばHTMLで "表"(0x 95 5c) と打ってサーバに送信すると、PHPで受けたときには、"表\"(0x 95 5c 5c)となっちゃうわけですね。

対処法としては、Magic Quote GPC機能をoffにする、文字コードにShift-JISを使わない、受信した文字列に「\」を取り除く処理を行う があるようですが、今回の場合だと、前二つは要件、サーバ環境的に無理なので、最後の3つめを行うことに。

下記のように Magic Quote GPC機能が有効かどうかを見て、有効なら余計なバックスラッシュをのけるため stripslashes() を走らせばいいようです。
if(get_magic_quotes_gpc()) {
$inputStr = stripslashes( $inputStr );
}

これはサニタイズと同じように関数化して必ず書くようなクセつけとくといいかもしれませんね。

ここら辺の詳細は、第3回 PHP と Shift-JIS 環境での文字化けについてに詳しく載っています。


しかし、ほんと文字コードがらみは厄介ですわ。。。。
[PR]
by jehoshaphat | 2009-09-15 18:01 | .Net開発 | Trackback | Comments(2)
(PHP)連想配列の特定のキーがあるかどうかを確認
isset() と array_key_exists() とが使えるようです。
isset() の場合、キーがあっても値が null だと false が返るようなので、 array_key_exists() を使ったほうがいいようです。
詳しくは、参考先を。。。

参考:
kotori::log 連想配列のキーチェック
そふぃのphp入門:isset
PHP マニュアル:array_key_exists
[PR]
by jehoshaphat | 2009-09-15 12:31 | PHP開発 | Trackback(2) | Comments(0)