<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>『株式会社シンプル・アイ』 ブログ &#187; PHP</title>
	<atom:link href="http://blog.simple-eye.com/cat/technology/php/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.simple-eye.com</link>
	<description>PHP+MySQLのWEBシステム開発の現場からお届け</description>
	<lastBuildDate>Sat, 10 Jul 2010 10:36:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>OpenPNEのインストールにはpdo_mysqlが必要</title>
		<link>http://blog.simple-eye.com/archives/307</link>
		<comments>http://blog.simple-eye.com/archives/307#comments</comments>
		<pubDate>Thu, 13 May 2010 15:04:19 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[OpenPNE]]></category>
		<category><![CDATA[pdo_mysql]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=307</guid>
		<description><![CDATA[OpenPNEのインストールで、

./symfony openpne:install


を実行した際に、

Couldn&#8217;t locate driver named mysql


と怒られたなら、それはPHPにpdo_mysqlエクステンションが入っていないから。ソースディレクトリからエクステンションをコンパイルする。

cd /usr/local/src/php/php-5.2.5/ext/pdo_mysql/
phpize
./configure &#8211;with-php-config=/usr/local/php5/bin/php-config \
   &#8211;with-pdo-mysql=/usr/local/mysql5.0
make
make install


でインストールし、php.iniに、

extension=pdo_mysql.so


を加えてApacheリスタート。
起動ＯＫと出て、安心できない。ブラウザでPHPのページをみると閲覧できない。Apacheが起動していない。。。

php -i


で、確認しようとすると、

php: symbol lookup error: /usr/local/php5/lib/php/20060613/pdo_mysql.so:
   undefined symbol: php_pdo_declare_long_constant

とでる。これは、/usr/local/php5/include/php/ext/pdo/php_pdo_driver.hのバージョンがよろしくないようだ。PHPをソースインストールした際のソースディレクトリからコピーしてやる。

cp /usr/local/src/php/php-5.2.5/ext/pdo/php_pdo_driver.h \
   /usr/local/php5/include/php/ext/pdo/php_pdo_driver.h


いったんpdo_mysqlをアンインストールする。

rm -f /usr/local/php5/lib/php/20060613/pdo_mysql.so


上記、ソースから再度インストール。make cleanしてからね。これでApache再起動でいけました。OpnePNEもインストール完了。
]]></description>
			<content:encoded><![CDATA[<p>OpenPNEのインストールで、</p>
<blockquote><p>
./symfony openpne:install
</p>
</blockquote>
<p>を実行した際に、</p>
<blockquote><p>
Couldn&#8217;t locate driver named mysql
</p>
</blockquote>
<p>と怒られたなら、それはPHPにpdo_mysqlエクステンションが入っていないから。ソースディレクトリからエクステンションをコンパイルする。</p>
<blockquote><p>
cd /usr/local/src/php/php-5.2.5/ext/pdo_mysql/<br />
phpize<br />
./configure &#8211;with-php-config=/usr/local/php5/bin/php-config \<br />
   &#8211;with-pdo-mysql=/usr/local/mysql5.0<br />
make<br />
make install
</p>
</blockquote>
<p>でインストールし、php.iniに、</p>
<blockquote><p>
extension=pdo_mysql.so
</p>
</blockquote>
<p>を加えてApacheリスタート。<br />
起動ＯＫと出て、安心できない。ブラウザでPHPのページをみると閲覧できない。Apacheが起動していない。。。</p>
<blockquote><p>
php -i
</p>
</blockquote>
<p>で、確認しようとすると、</p>
<blockquote><p>
php: symbol lookup error: /usr/local/php5/lib/php/20060613/pdo_mysql.so:<br />
   undefined symbol: php_pdo_declare_long_constant</pre>
</blockquote>
<p>とでる。これは、/usr/local/php5/include/php/ext/pdo/php_pdo_driver.hのバージョンがよろしくないようだ。PHPをソースインストールした際のソースディレクトリからコピーしてやる。</p>
<blockquote><p>
cp /usr/local/src/php/php-5.2.5/ext/pdo/php_pdo_driver.h \<br />
   /usr/local/php5/include/php/ext/pdo/php_pdo_driver.h
</p>
</blockquote>
<p>いったんpdo_mysqlをアンインストールする。</p>
<blockquote><p>
rm -f /usr/local/php5/lib/php/20060613/pdo_mysql.so
</p>
</blockquote>
<p>上記、ソースから再度インストール。make cleanしてからね。これでApache再起動でいけました。OpnePNEもインストール完了。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/307/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>preg_matchのサブキャッチパターンの文字数が多いと落ちます！！</title>
		<link>http://blog.simple-eye.com/archives/298</link>
		<comments>http://blog.simple-eye.com/archives/298#comments</comments>
		<pubDate>Sun, 02 May 2010 15:15:39 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[問題]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=298</guid>
		<description><![CDATA[PHPのpreg_matchにおいて、カッコを使って、サブキャッチパターンを作ることがあるだろう。ただ、そのサブキャッチパターンにマッチする文字数（バイト数）が10万文字（バイト）を超えると、エラーも発生させず、ただ単に、「マッチせずに」終了となる。（PHP５．２．５にて検証）　以下にサンプルコードを示す。
&#60;?php
for ( $i=1; $i&#60;=1000000000; $i++ ) {
$src .= &#8216;1234567890&#8242;;
 if ( !preg_match( &#8216;/&#60;(.+?)&#62;/&#8217;, &#8216;&#60;&#8217;.$src.&#8217;&#62;&#8217;, $matches ) ) {
  echo &#8220;not match at &#8220;.$i;
  break;
 }
}
?&#62;
&#60;?php
for ( $i=1; $i&#60;=1000000000; $i++ ) {
$src .= &#8216;1234567890&#8242;;
if ( !preg_match( &#8216;/&#60;(.+?)&#62;/&#8217;, &#8216;&#60;&#8217;.$src.&#8217;&#62;&#8217;, $matches ) ) {
echo &#8220;not match at &#8220;.$i;
break;
}
}
?&#62;
上記コードでは、決して「not match at ???」とは表示されることはないように思われるだろう。しかし実際はそうではない。実行してしばらく待つと以下の結果が出る。

not match at 10000

(.+?)というサブキャッチパターンにマッチする文字列が、10000×10文字＝10万文字になった時点で、マッチしなくなり、echoして、breakしていることが分かるはずだ。ちなみに、以下のコードでは、どうだろう。
&#60;?php
for ( $i=1; [...]]]></description>
			<content:encoded><![CDATA[<p>PHPのpreg_matchにおいて、カッコを使って、サブキャッチパターンを作ることがあるだろう。ただ、そのサブキャッチパターンにマッチする文字数（バイト数）が10万文字（バイト）を超えると、エラーも発生させず、ただ単に、「マッチせずに」終了となる。（PHP５．２．５にて検証）　以下にサンプルコードを示す。</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">for ( $i=1; $i&lt;=1000000000; $i++ ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$src .= &#8216;1234567890&#8242;;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if ( !preg_match( &#8216;/&lt;(.+?)&gt;/&#8217;, &#8216;&lt;&#8217;.$src.&#8217;&gt;&#8217;, $matches ) ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span> echo &#8220;not match at &#8220;.$i;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span> break;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<blockquote><p>&lt;?php<br />
for ( $i=1; $i&lt;=1000000000; $i++ ) {<br />
$src .= &#8216;1234567890&#8242;;<br />
if ( !preg_match( &#8216;/&lt;(.+?)&gt;/&#8217;, &#8216;&lt;&#8217;.$src.&#8217;&gt;&#8217;, $matches ) ) {<br />
echo &#8220;not match at &#8220;.$i;<br />
break;<br />
}<br />
}<br />
?&gt;</p></blockquote>
<p>上記コードでは、決して「not match at ???」とは表示されることはないように思われるだろう。しかし実際はそうではない。実行してしばらく待つと以下の結果が出る。</p>
<blockquote>
<div>not match at 10000</div>
</blockquote>
<p>(.+?)というサブキャッチパターンにマッチする文字列が、10000×10文字＝10万文字になった時点で、マッチしなくなり、echoして、breakしていることが分かるはずだ。ちなみに、以下のコードでは、どうだろう。</p>
<blockquote><p>&lt;?php<br />
for ( $i=1; $i&lt;=1000000000; $i++ ) {<br />
$src .= &#8216;1234567890&#8242;;<br />
$src2 .= &#8216;1234567890&#8242;;<br />
if ( !preg_match( &#8216;/&lt;(.+?)&gt;&lt;(.+?)&gt;/&#8217;, &#8216;&lt;&#8217;.$src.&#8217;&gt;&lt;&#8217;.$src2.&#8217;&gt;&#8217;, $matches ) ) {<br />
echo &#8220;not match at &#8220;.$i;<br />
break;<br />
}<br />
}<br />
?&gt;</p></blockquote>
<p>上記の場合、以下のような結果となる。</p>
<blockquote><p>not match at 5000</p></blockquote>
<p>おわかりだろう。やはり10万文字だ。(5000×10文字)＋(5000×10文字)＝10万文字なのである。</p>
<p>そんな長い文字をサブキャッチなんかしないといわれるかもしれない。しかし、私がこれに気付いたのは、XML-RPCのリクエストのパースを実装していた時だ。XML-RPCで、データを登録するリクエストにおいて、&lt;base64&gt;&lt;/base64&gt;タグで、画像データを受け取った際に、preg_matchのサブキャッチパターンで中身を取得したのだ。結果、大きな画像を受け取ったときに、マッチしないという事態に陥ったのだ。</p>
<p>たちが悪いのは、エラーをはいてプログラムが停止するのではなく、単にマッチしなくなって次の処理に進んでしまうことだ。ぜひ、気をつけていただきたい。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/298/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XREAやCORESERVERのsession_start()でエラー</title>
		<link>http://blog.simple-eye.com/archives/289</link>
		<comments>http://blog.simple-eye.com/archives/289#comments</comments>
		<pubDate>Mon, 12 Apr 2010 02:00:54 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[CORESERVER]]></category>
		<category><![CDATA[XREA]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=289</guid>
		<description><![CDATA[XREAやCORESRVERのPHPで、モジュール版とCGI版のPHPを合わせて使って、セッションが引き継がれると以下のようなエラーが出る。
Warning: session_start() [function.session-start]:  open(/tmp/sess_ｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘ, O_RDWR) failed: Permission denied  (13) in  /virtual/ｘｘｘｘ/public_html/index.php on  line xx
これはCGI版では、セッションファイルが、/tmp/にて、FTPユーザー権限で書きこまれ、一方モジュール版ではApacheユーザー権限で書きこまれるからだ。それで、CGI版PHPで作成されたセッションファイルをモジュール版PHPから読み込む際にパーミッションエラーとなるのだ。逆もまたしかり。
]]></description>
			<content:encoded><![CDATA[<p>XREAやCORESRVERのPHPで、モジュール版とCGI版のPHPを合わせて使って、セッションが引き継がれると以下のようなエラーが出る。</p>
<blockquote><p><strong>Warning</strong>: session_start() [<a href="http://www.shinko-grandsha.jp/contact/function.session-start">function.session-start</a>]:  open(/tmp/sess_ｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘｘ, O_RDWR) failed: Permission denied  (13) in  <strong>/virtual/ｘｘｘｘ/public_html/index.php</strong> on  line <strong>xx</strong></p></blockquote>
<p>これはCGI版では、セッションファイルが、/tmp/にて、FTPユーザー権限で書きこまれ、一方モジュール版ではApacheユーザー権限で書きこまれるからだ。それで、CGI版PHPで作成されたセッションファイルをモジュール版PHPから読み込む際にパーミッションエラーとなるのだ。逆もまたしかり。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/289/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPでFTP通信する際の注意</title>
		<link>http://blog.simple-eye.com/archives/256</link>
		<comments>http://blog.simple-eye.com/archives/256#comments</comments>
		<pubDate>Tue, 30 Mar 2010 05:34:37 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[サーバ・ネットワーク]]></category>
		<category><![CDATA[FTP]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=256</guid>
		<description><![CDATA[PHPでftp_put()関数などでFTP通信をする際に、
Warning:  ftp_put() [function.ftp-put]: Ok  to send data. in /path/to/script.php on line 99
のようなエラーに出くわすことはないだろうか。この場合、PHPが動作しているマシンのiptablesに注意が必要である。FTPログインはできたものの、相手からデータ通信のコネクションが張れないままタイムアウトしているのであろう。
通信相手のFTPサーバがアクティブモードで動作している場合、こちらから相手FTPサーバの２１番ポートにコネクトしたのち、相手FTPサーバの２０番ポートから、 こちらが通知した1024-65535の間のポートにコネクトしようとしてくる。
なので、こちら（PHPが動作しているマシン）のiptablesのINPUTチェーンで制限を加えている場合、INPUTチェーンでは、 1024-65535の間のポートが空いている必要が出てしまう。
これはあまりにも危険だし、その必要もない。以下のようにする。
iptables -L
を行い、INPUTチェーンに
ACCEPT  all  &#8211;  anywhere  anywhere  state RELATED,ESTABLISHED
の行があることを確認する。これは、確立済みのコネクションと、関連するコネクションを許可するものだ。なければ以下のように作る。
iptables -I INPUT 5 -p udp -m state &#8211;state ESTABLISHED,RELATED -j ACCEPT
上記、5の部分は挿入するINPUTチェーンの行番号です。
次にiptables関連のカーネルモジュールを確認する。
lsmod
を実行し、ip_conntrack_ftpと、ip_nat_ftpの行があることを確認し、ないものを入れる。それぞれ以下の通り。（多くの場合、ip_conntrack_ftpは入っている。）
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
これで、アクティブモードのFTPサーバに対して、PHPでFTP通信ができるようになった。
このままではサーバが再起動したら元に戻ってしまう。
/etc/sysconfig/iptables-config
で、使用するモジュールを以下のように設定する。
IPTABLES_MODULES=&#8221;ip_nat_ftp&#8221;
また、先のiptables設定を保存する。
service iptables save

IPTABLES_MODULES=&#8221;ip_nat_ftp
]]></description>
			<content:encoded><![CDATA[<p>PHPでftp_put()関数などでFTP通信をする際に、</p>
<blockquote><p><strong>Warning</strong>:  ftp_put() [<a href="http://219.94.179.46/function.ftp-put">function.ftp-put</a>]: Ok  to send data. in <strong>/path/to/script.php</strong> on line <strong>99</strong></p></blockquote>
<p>のようなエラーに出くわすことはないだろうか。この場合、PHPが動作しているマシンのiptablesに注意が必要である。FTPログインはできたものの、相手からデータ通信のコネクションが張れないままタイムアウトしているのであろう。</p>
<p>通信相手のFTPサーバがアクティブモードで動作している場合、こちらから相手FTPサーバの２１番ポートにコネクトしたのち、相手FTPサーバの２０番ポートから、 こちらが通知した1024-65535の間のポートにコネクトしようとしてくる。</p>
<p>なので、こちら（PHPが動作しているマシン）のiptablesのINPUTチェーンで制限を加えている場合、INPUTチェーンでは、 1024-65535の間のポートが空いている必要が出てしまう。<br />
これはあまりにも危険だし、その必要もない。以下のようにする。</p>
<blockquote><p>iptables -L</p></blockquote>
<p>を行い、INPUTチェーンに</p>
<blockquote><p>ACCEPT  all  &#8211;  anywhere  anywhere  state RELATED,ESTABLISHED</p></blockquote>
<p>の行があることを確認する。これは、確立済みのコネクションと、関連するコネクションを許可するものだ。なければ以下のように作る。</p>
<blockquote><p>iptables -I INPUT 5 -p udp -m state &#8211;state ESTABLISHED,RELATED -j ACCEPT</p></blockquote>
<p>上記、5の部分は挿入するINPUTチェーンの行番号です。</p>
<p>次にiptables関連のカーネルモジュールを確認する。</p>
<blockquote><p>lsmod</p></blockquote>
<p>を実行し、ip_conntrack_ftpと、ip_nat_ftpの行があることを確認し、ないものを入れる。それぞれ以下の通り。（多くの場合、ip_conntrack_ftpは入っている。）</p>
<blockquote><p>modprobe ip_conntrack_ftp<br />
modprobe ip_nat_ftp</p></blockquote>
<p>これで、アクティブモードのFTPサーバに対して、PHPでFTP通信ができるようになった。</p>
<p>このままではサーバが再起動したら元に戻ってしまう。<br />
/etc/sysconfig/iptables-config<br />
で、使用するモジュールを以下のように設定する。</p>
<blockquote><p>IPTABLES_MODULES=&#8221;ip_nat_ftp&#8221;</p></blockquote>
<div>また、先のiptables設定を保存する。</div>
<blockquote><p>service iptables save</p></blockquote>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 390px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
<p>IPTABLES_MODULES=&#8221;ip_nat_ftp</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/256/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>libxml2.7.0 &#8211; 2.7.2で、実体参照が消える</title>
		<link>http://blog.simple-eye.com/archives/49</link>
		<comments>http://blog.simple-eye.com/archives/49#comments</comments>
		<pubDate>Thu, 20 Aug 2009 23:16:18 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[技術情報]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=49</guid>
		<description><![CDATA[libxml2.7.0以降で、実態参照が消失する不具合があり、これを使ってコンパイルされたPHPでは、XMLをパースする際に問題になる。
■実態参照とは
XML文書内で直接記述できない文字や記号（たとえば、 &#8220;&#60;&#8221; や &#8220;&#62;&#8221; など）を表記する際に用いられる記述方法です。以下のようなものがある。

「&#38;」 ・・・ 「&#38;amp;」
「&#60; 」・・・ 「&#38;lt;」
「&#62; 」・・・ 「&#38;gt;」
「&#8221; 」・・・ 「&#38;quot;」
「&#8217; 」・・・ 「&#38;apos;」

XML内の、&#60;description&#62;タグ、&#60;content&#62;タグなどの中にHTMLを記述する場合、多くの場合以下のような記述を用いる。
&#60;description&#62;
&#60;![CDATA[
&#60;h1&#62;タイトル&#60;/h1&#62;
&#60;p&#62;文章がここにはいる&#60;/p&#62;
]]&#62;
&#60;/description&#62;
このようにしてCDATAセクションを使うことで、実態参照を用いずに記述することが可能である。しかし、CDATAを使わずに実態参照を用いて記述されているXMLも数多く存在する。
&#60;description&#62;
&#38;lt;h1&#38;gt;タイトル&#38;lt;/h1&#38;gt;
&#38;lt;p&#38;gt;文章がここにはいる&#38;lt;/p&#38;gt;
&#60;/description&#62;
このようになる。
■実態参照が使われたXMLをパースする際の問題
こういったXML文書をlibxml2.7.0以降を使ったPHP関数でパースすると、実態参照だけが消失し、以下のような見るに堪えない結果となる。
h1タイトル/h1
p文章がここにはいる/p
さくらインターネットのレンタルサーバでは、各種ミドルウェアのバージョンアップが早く、libxml2.7.2などがすでに導入されており、そのサーバを利用している場合、RSSやXMLから情報収集しているプログラムで不具合が生じることになるだろう。
■対処方法
専用サーバであれば、libxmlのバージョンを2.6.30に落とすなどして対処できるが、そうでない場合には別の対処が必要となるだろう。考えられるひとつの方法は、XML内の実態参照をデコードし、CDATAを使った記述に書き換えた上でパースすることだ。以下にPHPでそれを行うための関数を示す。
function insertCDATA( $xml_str )
{
 $target_tags = array( &#8216;description&#8217;, &#8216;content&#8217;, &#8216;content:encoded&#8217; );
 foreach ( $target_tags as $tag ) {
 $ent = false;
 if ( preg_match_all( &#8216;/&#60;&#8217;.$tag.&#8217;[^&#62;]*&#62;(.*?)&#60;\/&#8217;.$tag.&#8217;&#62;/ims&#8217;, $xml_str, $matches ) ) {
 if ( is_array( $matches[1] ) &#38;&#38; count( $matches[1] ) ) {
 foreach [...]]]></description>
			<content:encoded><![CDATA[<p>libxml2.7.0以降で、実態参照が消失する不具合があり、これを使ってコンパイルされたPHPでは、XMLをパースする際に問題になる。</p>
<p>■実態参照とは</p>
<p>XML文書内で直接記述できない文字や記号（たとえば、 &#8220;&lt;&#8221; や &#8220;&gt;&#8221; など）を表記する際に用いられる記述方法です。以下のようなものがある。</p>
<ul>
<li>「&amp;」 ・・・ 「&amp;amp;」</li>
<li>「&lt; 」・・・ 「&amp;lt;」</li>
<li>「&gt; 」・・・ 「&amp;gt;」</li>
<li>「&#8221; 」・・・ 「&amp;quot;」</li>
<li>「&#8217; 」・・・ 「&amp;apos;」</li>
</ul>
<p>XML内の、&lt;description&gt;タグ、&lt;content&gt;タグなどの中にHTMLを記述する場合、多くの場合以下のような記述を用いる。</p>
<blockquote><p>&lt;description&gt;<br />
&lt;![CDATA[<br />
&lt;h1&gt;タイトル&lt;/h1&gt;<br />
&lt;p&gt;文章がここにはいる&lt;/p&gt;<br />
]]&gt;<br />
&lt;/description&gt;</p></blockquote>
<p>このようにしてCDATAセクションを使うことで、実態参照を用いずに記述することが可能である。しかし、CDATAを使わずに実態参照を用いて記述されているXMLも数多く存在する。</p>
<blockquote><p>&lt;description&gt;<br />
&amp;lt;h1&amp;gt;タイトル&amp;lt;/h1&amp;gt;<br />
&amp;lt;p&amp;gt;文章がここにはいる&amp;lt;/p&amp;gt;<br />
&lt;/description&gt;</p></blockquote>
<p>このようになる。</p>
<p>■実態参照が使われたXMLをパースする際の問題</p>
<p>こういったXML文書をlibxml2.7.0以降を使ったPHP関数でパースすると、実態参照だけが消失し、以下のような見るに堪えない結果となる。</p>
<blockquote><p>h1タイトル/h1<br />
p文章がここにはいる/p</p></blockquote>
<p>さくらインターネットのレンタルサーバでは、各種ミドルウェアのバージョンアップが早く、libxml2.7.2などがすでに導入されており、そのサーバを利用している場合、RSSやXMLから情報収集しているプログラムで不具合が生じることになるだろう。</p>
<p>■対処方法</p>
<p>専用サーバであれば、libxmlのバージョンを2.6.30に落とすなどして対処できるが、そうでない場合には別の対処が必要となるだろう。考えられるひとつの方法は、XML内の実態参照をデコードし、CDATAを使った記述に書き換えた上でパースすることだ。以下にPHPでそれを行うための関数を示す。</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">function insertCDATA( $xml_str )</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">{</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>$target_tags = array( &#8216;description&#8217;, &#8216;content&#8217;, &#8216;content:encoded&#8217; );</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>foreach ( $target_tags as $tag ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>$ent = false;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if ( preg_match_all( &#8216;/&lt;&#8217;.$tag.&#8217;[^&gt;]*&gt;(.*?)&lt;\/&#8217;.$tag.&#8217;&gt;/ims&#8217;, $xml_str, $matches ) ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if ( is_array( $matches[1] ) &amp;&amp; count( $matches[1] ) ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>foreach ( $matches[1] as $m ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if ( !preg_match( &#8216;/^&lt;!\[CDATA\[/im', $m ) &amp;&amp; preg_match( '/&amp;gt;|&amp;lt;|&amp;amp;|&amp;quot;|&amp;apos;/ims', $m ) ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>$ent = true;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>break;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if ( !$ent ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>continue;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>$encode = mb_detect_encoding( $xml_str );</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>$xml_str = preg_replace( '/(&lt;'.$tag.'[^&gt;]*&gt;)(?!\s*&lt;!\[CDATA\[)(.*)(&lt;\/'.$tag.'&gt;)/Ueims',</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>'"\\1&lt;![CDATA[".html_entity_decode("\\2",ENT_COMPAT,"$encode")."]]&gt;\\3&#8243;&#8216;, $xml_str );</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>return $xml_str;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<blockquote><p>function insertCDATA( $xml_str )<br />
{<br />
<span style="white-space:pre"> </span>$target_tags = array( &#8216;description&#8217;, &#8216;content&#8217;, &#8216;content:encoded&#8217; );<br />
<span style="white-space:pre"> </span>foreach ( $target_tags as $tag ) {<br />
<span style="white-space:pre"> </span>$ent = false;<br />
<span style="white-space:pre"> </span>if ( preg_match_all( &#8216;/&lt;&#8217;.$tag.&#8217;[^&gt;]*&gt;(.*?)&lt;\/&#8217;.$tag.&#8217;&gt;/ims&#8217;, $xml_str, $matches ) ) {<br />
<span style="white-space:pre"> </span>if ( is_array( $matches[1] ) &amp;&amp; count( $matches[1] ) ) {<br />
<span style="white-space:pre"> </span>foreach ( $matches[1] as $m ) {<br />
<span style="white-space:pre"> </span>if ( !preg_match( &#8216;/^&lt;!\[CDATA\[/im', $m ) &amp;&amp;<br />
preg_match( '/&amp;gt;|&amp;lt;|&amp;amp;|&amp;quot;|&amp;apos;/ims', $m ) ) {<br />
<span style="white-space:pre"> </span>$ent = true;<br />
<span style="white-space:pre"> </span>break;<br />
<span style="white-space:pre"> </span>}<br />
<span style="white-space:pre"> </span>}<br />
<span style="white-space:pre"> </span>}<br />
<span style="white-space:pre"> </span>if ( !$ent ) { continue; }<br />
<span style="white-space:pre"> </span>$encode = mb_detect_encoding( $xml_str );<br />
<span style="white-space:pre"> </span>$xml_str = preg_replace(<br />
'/(&lt;'.$tag.'[^&gt;]*&gt;)(?!\s*&lt;!\[CDATA\[)(.*)(&lt;\/'.$tag.'&gt;)/Ueims',<br />
<span style="white-space:pre"> </span>'"\\1&lt;![CDATA[".html_entity_decode("\\2",ENT_COMPAT,"$encode")."]]&gt;\\3&#8243;&#8216;, $xml_str );<br />
}<br />
}<br />
return $xml_str;<br />
}</p></blockquote>
<p>この関数にXML文字列を渡すと、&lt;description&gt;タグ、&lt;content&gt;タグ、&lt;content:enceded&gt;タグを調べて、そこに実態参照があれば、CDATAによる記述に書き換えて返してくれます。</p>
<p>RSSをパースする際に、MagpieRSS（<a href="http://magpierss.sourceforge.net/">http://magpierss.sourceforge.net/</a>）をご利用の方も多いだろう。このライブラリもlibxml2.7.xの影響を受ける。その場合、rss_fetch.incを開き、上記の関数を書き加えたうえで、_response_to_rss関数のはじめの部分を以下のように書き換えてやるといい。</p>
<blockquote><p>/*===============================================*\<br />
Function:   _response_to_rss<br />
Purpose:    parse an HTTP response object into an RSS object<br />
Input:      an HTTP response object (see Snoopy)<br />
Output:     parsed RSS object (see rss_parse)<br />
\*===============================================*/</p>
<p>function _response_to_rss ($resp) {<br />
/* ++++++++++++++++++++ Simple Eye changed +++++++++++++++++++ */<br />
//    $rss = new MagpieRSS( insertCDATA($resp-&gt;results), MAGPIE_OUTPUT_ENCODING, MAGPIE_INPUT_ENCODING, MAGPIE_DETECT_ENCODING );<br />
/* ++++++++++++++++++++ Simple Eye changed +++++++++++++++++++ */<br />
$rss = new MagpieRSS( $resp-&gt;results, MAGPIE_OUTPUT_ENCODING, MAGPIE_INPUT_ENCODING, MAGPIE_DETECT_ENCODING );</p>
<div>・・・・・・・・つづく・・・・・・・・・</div>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/49/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>session.bug_compat_42 と session.bug_compat_warn</title>
		<link>http://blog.simple-eye.com/archives/34</link>
		<comments>http://blog.simple-eye.com/archives/34#comments</comments>
		<pubDate>Thu, 20 Aug 2009 07:33:16 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[技術情報]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=34</guid>
		<description><![CDATA[Warning: Unknown(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively. in Unknown on [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Warning: Unknown(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively. in Unknown on line 0</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">PHP バージョンが 4.2.3 とそれ以前には、たとえ register_globals が無効の場合でもグローバルスコープでセッション変数の初期化を 許してしまうドキュメント化されていない特徴/バグがあります。 この機能を使用している場合で session.bug_compat_warn も有効にしている場合、 PHP 4.3.0 とそれ以降のバージョンでは警告が発されます。 この特徴/バグは、 以下のディレクティブを無効にすることで無効にすることが可能です。</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session.bug_compat_42</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session.bug_compat_warn</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">上記の「この機能を使用している場合」に相当しているかどうかを</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">ＰＨＰがどんな条件で判断しているかを６つのケースから考える。</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●エラーが出ない[case1.php]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">（$_SESSIONのキーとグローバル変数が違う場合）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session_start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$bbb = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $bbb;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●エラーが出ない[case2.php]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">（$_SESSIONのキーとグローバル変数が同じ場合でも、</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">外部からの変数を受け取っていない場合）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session_start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$aaa = &#8216;abc&#8217;;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $aaa;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●エラーが出る[case3.php]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">（$_SESSIONのキーとグローバル変数が同じ場合で、かつ、</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">外部からの変数を受け取っている場合）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session_start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$aaa = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $aaa;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●エラーが出る[case4.php]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">（$_SESSIONのキーとグローバル変数が同じ場合で、</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">その$_SESSIONが外部からグローバル変数とは関係ない外部変数を受け取っている場合）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session_start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$aaa = &#8216;abc&#8217;;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●エラーが出る[case5.php]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">（$_SESSIONのキーとグローバル変数が同じ場合で、</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">その$_SESSIONが外部からグローバル変数とは関係ない外部変数を</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">別のグローバル変数を介して受け取っている場合）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session_start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$aaa = &#8216;abc&#8217;;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$bbb = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $bbb;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●エラーが出ない[case6.php]</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">（$_SESSIONのキーとグローバル変数が同じものがある場合で、</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">その$_SESSIONとは別の$_SESSIONが外部変数を受け取っている場合）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&lt;?php</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session_start();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$aaa = &#8216;abc&#8217;;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$bbb = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $aaa;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['ccc'] = $bbb;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">?&gt;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●結論（エラーが出る条件）</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">①$_SESSIONのキーと同じ名前のグローバル変数がある</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">例）　$_SESSION['aaa']　と　$aaa</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">②その$_SESSIONが間接的、直接的を問わず、何らかの外部変数を読み込んでいる</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">例１）　$_SESSION['aaa'] = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">例２）　$bbb = $_GET['abc'];</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$_SESSION['aaa'] = $bbb;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">●回避策</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">php.iniの以下のディレクティブをOffにする</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session.bug_compat_42</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">session.bug_compat_warn</div>
<p>■■　以下のエラーを検証する　■■</p>
<blockquote><p>Warning: Unknown(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively. in Unknown on line 0</p></blockquote>
<p>PHP バージョンが 4.2.3 とそれ以前には、たとえ register_globals が無効の場合でもグローバルスコープでセッション変数の初期化を 許してしまうドキュメント化されていない特徴/バグがあります。 この機能を使用している場合で session.bug_compat_warn も有効にしている場合、 PHP 4.3.0 とそれ以降のバージョンでは警告が発されます。 この特徴/バグは、 以下のディレクティブを無効にすることで無効にすることが可能です。</p>
<blockquote><p>session.bug_compat_42<br />
session.bug_compat_warn</p></blockquote>
<p>上記の「この機能を使用している場合」に相当しているかどうかを ＰＨＰがどんな条件で判断しているかを６つのケースから考える。</p>
<p>●エラーが出ない[case1.php]</p>
<p>（$_SESSIONのキーとグローバル変数が違う場合）</p>
<blockquote><p>&lt;?php<br />
session_start();<br />
$bbb = $_GET['abc'];<br />
$_SESSION['aaa'] = $bbb;<br />
?&gt;</p></blockquote>
<p>●エラーが出ない[case2.php]</p>
<p>（$_SESSIONのキーとグローバル変数が同じ場合でも、外部からの変数を受け取っていない場合）</p>
<blockquote><p>&lt;?php<br />
session_start();<br />
$aaa = &#8216;abc&#8217;;<br />
$_SESSION['aaa'] = $aaa;<br />
?&gt;</p></blockquote>
<p>●エラーが出る[case3.php]</p>
<p>（$_SESSIONのキーとグローバル変数が同じ場合で、かつ、外部からの変数を受け取っている場合）</p>
<blockquote><p>&lt;?php<br />
session_start();<br />
$aaa = $_GET['abc'];<br />
$_SESSION['aaa'] = $aaa;<br />
?&gt;</p></blockquote>
<p>●エラーが出る[case4.php]</p>
<p>（$_SESSIONのキーとグローバル変数が同じ場合で、その$_SESSIONが外部からグローバル変数とは関係ない外部変数を受け取っている場合）</p>
<blockquote><p>&lt;?php<br />
session_start();<br />
$aaa = &#8216;abc&#8217;;<br />
$_SESSION['aaa'] = $_GET['abc'];<br />
?&gt;</p></blockquote>
<p>●エラーが出る[case5.php]</p>
<p>（$_SESSIONのキーとグローバル変数が同じ場合で、その$_SESSIONが外部からグローバル変数とは関係ない外部変数を別のグローバル変数を介して受け取っている場合）</p>
<blockquote><p>&lt;?php<br />
session_start();<br />
$aaa = &#8216;abc&#8217;;<br />
$bbb = $_GET['abc'];<br />
$_SESSION['aaa'] = $bbb;<br />
?&gt;</p></blockquote>
<p>●エラーが出ない[case6.php]</p>
<p>（$_SESSIONのキーとグローバル変数が同じものがある場合で、その$_SESSIONとは別の$_SESSIONが外部変数を受け取っている場合）</p>
<blockquote><p>&lt;?php<br />
session_start();<br />
$aaa = &#8216;abc&#8217;;<br />
$bbb = $_GET['abc'];<br />
$_SESSION['aaa'] = $aaa;<br />
$_SESSION['ccc'] = $bbb;<br />
?&gt;</p></blockquote>
<p>●結論（エラーが出る条件）</p>
<p>①$_SESSIONのキーと同じ名前のグローバル変数がある</p>
<blockquote><p>例）　$_SESSION['aaa']　と　$aaa</p></blockquote>
<p>②その$_SESSIONが間接的、直接的を問わず、何らかの外部変数を読み込んでいる</p>
<blockquote><p>例１）　$_SESSION['aaa'] = $_GET['abc'];</p>
<p>例２）</p>
<p>$bbb = $_GET['abc'];<br />
$_SESSION['aaa'] = $bbb;</p></blockquote>
<p>●回避策</p>
<p>php.iniの以下のディレクティブをOffにする</p>
<blockquote><p>session.bug_compat_42<br />
session.bug_compat_warn</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/34/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPデバッガdbgのインストール</title>
		<link>http://blog.simple-eye.com/archives/44</link>
		<comments>http://blog.simple-eye.com/archives/44#comments</comments>
		<pubDate>Wed, 19 Aug 2009 07:46:47 +0000</pubDate>
		<dc:creator>シンプル・アイ社長</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[技術情報]]></category>

		<guid isPermaLink="false">http://blog.simple-eye.com/?p=44</guid>
		<description><![CDATA[●dbgのホームページ
http://dd.cron.ru/dbg/
●ソースコード取得
http://dd.cron.ru/dbg/downloads.php
●インストールマニュアル
http://dd.cron.ru/dbg/installation.php
●準備
①ＰＨＰをインストールしよう。
②PREFIX/bin/にphpizeが作成されていることを確認する。
③ソースdbg-2.11.32-src.tar.gzをダウンロード
④次のプログラムがインストールされていることを確認。
autoconf 2.13　以降
automake 1.4　以降
libtool 1.3.3　以降
●ソース展開
/usr/local/src/dbg/でソースを展開する
tar xzvf dbg-2.11.32-src.tar.gz
●スクリプトdeferphpizeを調整
deferphpizeの初めの方にあるphpizeへのパスを適切なものにする
cd dbg-2.11.32
vi deferphpize
～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・
#!/bin/sh
phpize=${phpize:-&#8221;/usr/local/php/bin/phpize&#8221;}
if test -f $phpize; then
$phpize
else
echo &#8220;You have to make and install php first. Make sure phpize script is located at $phpize&#8221;
exit 1
fi
・・・
～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・
●deferphpizeを走らせる
./deferphpize
これにより、dbg.soライブラリがPHPのモジュールサブディレクトリに作成される。
私の場合は、/usr/local/php/lib/php/extensions/no-debug-non/zts-20050922/dbg.so
に作成された。これを/usr/local/php/lib/php/extensions/dbg.soに移動した。
PHP4の場合、ソースディレクトリの/usr/local/src/dbg/dbg-2.11.32/modules/dbg.so
に作成された。
●エラー対処
In file included from /usr/local/src/dbg/dbg-2.11.32/dbg.c:21:
/usr/local/php4-4apache1.3/include/php/main/php_network.h:78:25: openssl/ssl.h: No such file or directory
In file included from /usr/local/src/dbg/dbg-2.11.32/dbg.c:21:
/usr/local/php4-4apache1.3/include/php/main/php_network.h:129: error: syntax error before &#8220;SSL&#8221;
/usr/local/php4-4apache1.3/include/php/main/php_network.h:129: warning: no semicolon at end of struct [...]]]></description>
			<content:encoded><![CDATA[<p>●dbgのホームページ</p>
<blockquote><p>http://dd.cron.ru/dbg/</p></blockquote>
<p>●ソースコード取得</p>
<blockquote><p>http://dd.cron.ru/dbg/downloads.php</p></blockquote>
<p>●インストールマニュアル</p>
<blockquote><p>http://dd.cron.ru/dbg/installation.php</p></blockquote>
<p>●準備</p>
<p>①ＰＨＰをインストールしよう。</p>
<p>②PREFIX/bin/にphpizeが作成されていることを確認する。</p>
<p>③ソースdbg-2.11.32-src.tar.gzをダウンロード</p>
<p>④次のプログラムがインストールされていることを確認。</p>
<p>autoconf 2.13　以降</p>
<p>automake 1.4　以降</p>
<p>libtool 1.3.3　以降</p>
<p>●ソース展開</p>
<p>/usr/local/src/dbg/でソースを展開する</p>
<blockquote><p>tar xzvf dbg-2.11.32-src.tar.gz</p></blockquote>
<p>●スクリプトdeferphpizeを調整</p>
<p>deferphpizeの初めの方にあるphpizeへのパスを適切なものにする</p>
<blockquote><p>cd dbg-2.11.32</p>
<p>vi deferphpize</p>
<p>～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・</p>
<p>#!/bin/sh</p>
<p>phpize=${phpize:-&#8221;/usr/local/php/bin/phpize&#8221;}</p>
<p>if test -f $phpize; then</p>
<p>$phpize</p>
<p>else</p>
<p>echo &#8220;You have to make and install php first. Make sure phpize script is located at $phpize&#8221;</p>
<p>exit 1</p>
<p>fi</p>
<p>・・・</p>
<p>～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・～・</p></blockquote>
<p>●deferphpizeを走らせる</p>
<blockquote><p>./deferphpize</p></blockquote>
<p>これにより、dbg.soライブラリがPHPのモジュールサブディレクトリに作成される。</p>
<p>私の場合は、/usr/local/php/lib/php/extensions/no-debug-non/zts-20050922/dbg.so</p>
<p>に作成された。これを/usr/local/php/lib/php/extensions/dbg.soに移動した。</p>
<p>PHP4の場合、ソースディレクトリの/usr/local/src/dbg/dbg-2.11.32/modules/dbg.so</p>
<p>に作成された。</p>
<p>●エラー対処</p>
<blockquote><p>In file included from /usr/local/src/dbg/dbg-2.11.32/dbg.c:21:</p>
<p>/usr/local/php4-4apache1.3/include/php/main/php_network.h:78:25: openssl/ssl.h: No such file or directory</p>
<p>In file included from /usr/local/src/dbg/dbg-2.11.32/dbg.c:21:</p>
<p>/usr/local/php4-4apache1.3/include/php/main/php_network.h:129: error: syntax error before &#8220;SSL&#8221;</p>
<p>/usr/local/php4-4apache1.3/include/php/main/php_network.h:129: warning: no semicolon at end of struct or union</p>
<p>/usr/local/php4-4apache1.3/include/php/main/php_network.h:132: error: syntax error before &#8216;}&#8217; token</p>
<p>/usr/local/php4-4apache1.3/include/php/main/php_network.h:162: error: syntax error before &#8220;SSL_METHOD&#8221;</p>
<p>make: *** [dbg.lo] エラー 1</p></blockquote>
<p>このエラーが出たら、openssl-devel パッケージをインストールする必要がある。</p>
<blockquote><p>yum install openssl-devel</p></blockquote>
<p>●php.iniの設定</p>
<p>エクステンションへのパスの指定</p>
<blockquote><p>extension_dir = &#8220;/usr/local/php/lib/php/extensions&#8221;</p></blockquote>
<p>利用するエクステンションの指定</p>
<blockquote><p>extension=dbg.so</p></blockquote>
<p>dbgのセクション</p>
<blockquote><p>[debugger]</p>
<p>debugger.enabled=on</p>
<p>debugger.profiler_enabled=on</p></blockquote>
<p>●apacheの再起動</p>
<p>apacheを再起動させてphpinfo()を表示させて、ZENDのロゴ付近に以下の記述があり、dbgのセクションがあればインストール成功。</p>
<blockquote><p>This program makes use of the Zend Scripting Language Engine:</p>
<p>Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies</p>
<p>with DBG v2.11.32, (C) 2000,2005, by Dmitri Dmitrienko</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.simple-eye.com/archives/44/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
