忍者ブログ

カウンター

プロモーション

カレンダー

12 2025/01 02
S M T W T F S
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

AntinomyMy の実験室

   私のWEBアプリ実験室です!

ブログ内検索

楽天でお買い物

twitter

最新トラックバック

最新コメント

忍者アナライズ

ウェザーニュース

バーコード

本を買う

アクセス解析

Google+

[PR]

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


No Image

POST とPHP だけでリロード対策!JavaScript Cookie session GET データベース一切無し!

PHP の調べ物

PHP だけの言語を用いて、JavaScript Cookie session データベース使用無しのリロード対策作りました。
GET でアドレス後から付け加える方法も無しで、POST情報だけで実現しています。


やり方は、自分のページのAは描画をPHPで行う最に、自分のページA内に
任意のPOSTデータを含む情報を持つページAの形をした別物A’を読む、
そのA'はPOSTデータだけが違うという物。

つまり自分自身の分身A’を読み込んでPOSTデータ処理させる。


以下で説明するスクリプトの場合、初回と同様になる様に
空のデータを0扱いする様にしてあり、処理される。

私のブログにしては妙に短いのはお酒を・・・いるからですw(朝じゃん・・・・)

さてもう眠いですが、うれしさも何も無く酔い・・・いや、軽く頭が軽い状態で、
プログラムを組んでいた訳なんですが、そのソースを惜しげもなく(無様な汚いコードですw)
ここにメモ書きとして掲載しようじゃないか>w<;(早く寝たいですw)


さて、もとい。
ブラウザの違いとか検証は、いい加減にやってみました。(何度も言いますが眠いですw)
Internet Explorer 8 と、 Mozilla Firefox 3.6.17 そして、Safari 5.0.5(7533.21.1 ) ですが、
なぜか私の場合以下のファイル名がフルパスで
http://localhost/flipflop_reload_protect.php
なのですが、Safari だけは最後に / を追加した
http://localhost/flipflop_reload_protect.php/
とアドレス入力に入力しなければ初回の画面が見られませんでした。
Safari の意味不明な仕様に驚き、良いブラウザハックの拾い物をした!と思いつつ?
時間も時間なので次に進みたいと思いますw


では本ソースです。



 

 

<?php
header('Content-type: text/html; charset=UTF-8');
echo '前のPOSTだよ!';
var_dump($_POST);
if(!$_POST['flipflopProtect'])
{
 echo '0の時だけ<br/><br/>';
 //POSTデータ
 $originalPOST = array(
  'flipflopProtect' =>  !(boolean)$_POST['flipflopProtect'],
  'count_submit' => 1 + (integer)$_POST['count_submit']
 );
 $mergePOST = array_merge($_POST,$originalPOST);
 
 
 $contentData = http_build_query($mergePOST, "", "&");
 
 //header
 $header = array(
     "Content-Type: application/x-www-form-urlencoded",
     "Content-Length: ".strlen($contentData)
 );
 
 $context = array(
     "http" => array(
         "method"  => "POST",
         "header"  => implode("\r\n", $header),
         "content" => $contentData
     )
 );
 
 $url = "http://localhost/flipflop_reload_protect.php";
 echo file_get_contents($url, false, stream_context_create($context));
 die();
}
?>

/* 本文(ホームページなど) */
うんたらうんたら・・・
<?php echo "<br/>\$_POST['flipflopProtect']がずっとブラウザ内では1なんですよ! 実際の値:" . $_POST['flipflopProtect'] ?>
<form id="reloadBlock" method="POST" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
 <input type="hidden" name="flipflopProtect" value="0" />
 <input type="hidden" name="count_submit" value="<?php echo $_POST['count_submit']?>" />
 <input id="submitBottun" type="submit" value="<?php echo $_POST['flipflopProtect']==1?'プロテクト中':'何処かにバグ' ?>" />
</form>


 こんな感じでした。

簡単に説明すると
POSTデータの$_POST['flipflopProtect'] は、開始直後はstringでは''で、
これは数値式のinteger で表せば0です。
その0か''の時だけ、自分自身を参照しに行き、
その処理の時に$_POST['flipflopProtect'] を1にしてプロテクトをかけ、
リロード出来ない状態にして、リロードしても処理しない部分を作り上げています、
つまり自分自身にPOSTする処理を無くしています。

そんな感じで見栄えは一緒、でもPOSTデータの内容が違うと言うとてもとても危なげで
奇想天外な事をしています。

これは本当に苦肉の策みたいな物なので、
Webページとしての描画内容はPHPのそのリロードプロテクトの後に
書いている状態なので、その辺を一まとめにするかとか、
色々他のPHPスクリプトを付け加えて実践的にすると
どんな感じになるかとかまでは書いていません
(お酒飲んでいるから早くブログを書き終えたいですw朝ですしw)。

そんな感じです<_ _>


一応ですが書くとすると自身が表示させたい下部の
/* 本文(ホームページなど) */
と書いている部分以降に
if(!$_POST['flipflopProtect']){  ~~~~~  }
この ~~~~~ にリロード時に処理させたくない内容を入れればいいんです。

別に1ページのソース内に細切れに<?php そのソース  ?>でいいと思うんです。

そんな感じで今回のメモは終わりにしたいと思います。
お酒入っているので、見直しは後ほどにします。


お休みっ! ^v^ノシ


追伸:(結構ウェイト大きいです)
なんかやはり、自身を参照している部分が不可思議な表示です。
推測ではキャッシュしている部分とPHP内部で計算してしまう部分と両方を用いて
描画しているのではないかと思います。
以下の修正変更したソースのカウントが動いてしまうのがその良い例です。

A=自身 A’=自身を呼び出した物とします。

また実はAとA'の両方にPOSTメッセージは存在し、別々に処理されています。
この当りもややこしいです。
そしてA'内部からAのグローバル変数やAのPOSTデータは操作できません。

書籍などには無い、不思議なブラウザとサーバ処理(ApacheやPHPの挙動)が見え隠れします、
環境に依存する可能性もあるので気をつけてください。

とりあえず初回もカウントしない様にして、内部の時間も数値化してみました。
A'の描画が不思議であるのがわかると思います。




 <?php
header('Content-type: text/html; charset=UTF-8');
echo '前のPOSTだよ!'.time().'<br/>';
var_dump($_POST);
if($_POST['flipflopProtect'])
{
 echo '0の時だけ'.time().'<br/>' . $_POST['flipflopProtect'] . '<br/>';
 var_dump($_POST);
 //POSTデータ
 $originalPOST = array(
  'flipflopProtect' =>  !$_POST['flipflopProtect'],
  'count_submit' => 1 + (integer)$_POST['count_submit']
 );
 $mergePOST = array_merge($_POST,$originalPOST);
 
 
 $contentData = http_build_query($mergePOST, "", "&");
 
 //header
 $header = array(
     "Content-Type: application/x-www-form-urlencoded",
     "Content-Length: ".strlen($contentData)
 );
 
 $context = array(
     "http" => array(
         "method"  => "POST",
         "header"  => implode("\r\n", $header),
         "content" => $contentData
     )
 );
 
 $url = "http://localhost/flipflop_reload_protect.php";
 echo 'ここから自分を呼んだ後<br/>';
 echo file_get_contents($url, false, stream_context_create($context));
 die();
}else{
 echo '<br/>リロードブロックと初回だけのはずなのに!<br/><br/>';
}
?>

 

/* 本文(ホームページなど) */
うんたらうんたら・・・
<?php echo "<br/>\$_POST['flipflopProtect']がずっとブラウザA内では0か''なんですよ! 実際の値:[" . $_POST['flipflopProtect'] . "]" ?>
<form id="reloadBlock" method="POST" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
 <input type="hidden" name="flipflopProtect" value="1" />
 <input type="hidden" name="count_submit" value="<?php echo $_POST['count_submit']?>" />
 <input id="submitBottun" type="submit" value="<?php echo $_POST['flipflopProtect']==1?'何処かにバグ':'プロテクト中' ?>" />
</form>
<?php echo var_dump($_POST) ?> 


 

'<br/>リロードブロックと初回だけのはずなのに!<br/><br/>' って所が、カウントした場合でも表示されています。
このIF文はどちらかしか動かないからIFなのですが・・・
IFでそうであった場合と、そうでなかった場合、両方の結論が出てしまう様に見える!


キャッシュやインスタンスなどの絡みと読み込みの絡み、AとA'の関係から、
結果的にブラウザの持つAの変数操作はされている様な挙動を
かろうじて実現出来ている様ですが、実際の絡みが不明な為、
よーく考えて使うべきです。

私はフォームメールに実装しようと思います。

A'内で処理する部分にブラウザへの描画関数は用いない方が無難だと思います。

それはキャッシュやインスタンス内の何かをAで妙な反映をさせない対策になると思います。
Aはブラウザで表示できる物全ての処理をし、
A'は間違っても表示処理を入れない方が良いと言うことです。


多分・・・・それが無難で一番良い方法になると思います^^;


以上長ーーーーーいメモでした<_ _>

拍手[2回]

PR

No Image

mb_internal_encoding 関数(mbstring.internal_encoding 設定) とstrlen 関数,mb_strlen 関数の不思議な関係

PHP の調べ物

さてさて、毎回Web上にある設定の変更できないレンタルのサーバの環境とローカル環境の違いを把握して・・・どうのこうの・・・
みたいなややこしいことをしてきた結果、当たり前であろう事により一段と近づく結論が浮かんだ。

それは設定の修正が効かない側のサーバ(レンタルサーバ)の環境に極力ローカルの開発環境も整えること。

という結論が出た、とても当たり前と言えば当たり前だ・・・。

文字化け以外にも、文字カウントを失敗するないていうことが、
デフォルトの 内部文字エンコーディング ->mbstring.internal_encoding (php.ini内)

関数で指定した内部文字エンコーディング ->mb_internal_encoding 関数
によって起こる事が判明した。

まず、この結論にたどり着くまでに気がついた事柄を述べる。
<まずテストする為のソースコード>
<?php
$string = '内部文字エンコーディング環境のTESTです!'.mt_rand(0,9).mt_rand(0,9).mt_rand(0,9);

// 文字の長さの検出の色々な仕方
var_dump(strlen($string));     //内部文字エンコーディングが違う環境に依存しない(バイト数)
var_dump(mb_strlen($string));    //内部文字エンコーディングが違う環境に確実に左右される
var_dump(mb_strlen($string ,'UTF-8'));  
//内部文字エンコーディングが違う環境に依存しにくい
?>

これを参考に以下、1. 2. 3. を見てもらえば判ると思う。

1.文字数をカウントする計算式に狂いが生じる。
内部エンコーディング:ISO-8859-1

内部エンコーディング:UTF-8
では部分的に違う出力結果になる。

内部エンコーディング:UTF-8 の場合、上から答えが int 61、 int 25、 int 25 となる。
内部エンコーディング:ISO-8859-1の場合、上から答えが int 61、 int 61、 int 25 となる。

2.カウントしたい文字列が1文字が1バイト以上の文字である場合には、
 文字数カウントに使えない関数がある。

つまりこの例のスクリプトの場合は、
var_dump(mb_strlen($string));    //内部文字エンコーディングが違う環境に依存しない
がバイト数でしか文字列がカウントできないです。

そしてまた、文字としてカウントできるとしても、正しい文字エンコーディングを指定していない場合、
存在しない文字を他の文字に読み違えたりして間違って文字を認識したりした結果、
文字数が変わってしまうのが、
var_dump(mb_strlen($string));    //内部文字エンコーディングが違う環境に確実に左右される
です。

また、内部エンコーディングを指定して文字数をカウントさせているので、一番文字数のカウント間違えが
少ないと思われる、
var_dump(mb_strlen($string ,'UTF-8'));  //内部文字エンコーディングが違う環境に依存しにくい
ですが、
依存しにくいと書いているのは、保存形式によって保存された文字が
本当に指定したコードで文字を間違えて文字化けなどをせずに解釈できるのかどうかの
テストは今回行っていないからです。

3.サーバの環境によってデフォルトの設定があるので、
 文字数カウントの関数の引数が任意であっても指定した方が環境が変わっても、
 スクリプトが同様に動く可能性が高くなる。

さて、ではサーバ側が例えばレンタルサーバであって、
php.ini 内のmbstring.internal_encoding の値がない(no value)場合なども考えられる。
その場合には、私のテスト環境のWindows とレンタルLinuxサーバ ではどちらもISO-8859-1 になってしまった。

phpinfo 関数で調べると、ISO-8859-1 になっている箇所が
iconv.input_encoding, iconv.internal_encoding, iconv.output_encoding
だけであったが、この設定以外にISO-8859-1 が使われている場所が
内部的にあるのかどうか?までは調べていない。

1つの環境内でphp.ini 内でデフォルトの内部エンコーディングが変化することなどは
開発環境では望ましくないが、他のサーバの設定も把握してスクリプトを書くのならば、
やはり環境を一致させた状態、つまりphp.ini を一緒にして完全に作るか、
それかスクリプト内部で

// 内部文字エンコーディングをUTF-8に設定
mb_internal_encoding('UTF-8');

とかするしかないと思う。

しかし確実なのは両方の対策をとっているのが望ましい気がした。



最後にphp はHTML やXHTML に埋め込み使うのであるが、
ヘッダーを出力できるという利点がある。

ヘッダーを解釈するのはWebサーバ上のApache などがMIME を解決して
クライアントのブラウザの挙動に繋げているのは前回説明したが、
それ以外にもブラウザの挙動に直接つながっているのだと分かる指定の仕方があった。

//ブラウザがこのスクリプトの出力の文字コードを割り出す為のヘッダー
header('Content-type: text/html; charset=UTF-8');

これを組み込んでおくことと、組み込まずにおくことでは
文字が化けるか化けないかが変わるのである。

ブラウザで確認したのは、IEであるが、
自動でUTF-8 になっているか、それとも今回のスクリプトソースをUTF-8で保存し
header('Content-type: text/html; charset=UTF-8');
をつけず、表示しようとすれば、環境にもよる(php.iniの設定に依存すると思う)が
シフトJISとなってしまって文字化けしてしまうことがある。

しかし不思議なことに、ブラウザのソースを見ても
<html>
<head>
ココ
</head>
などという場所に文字コードの指定や書いた形跡は無い。
それなのに文字コードは間違えがない設定になって表示されるのである。

また、文字コードを間違えない状況になった後でも、
ブラウザの自動選択を指定するとなぜか文字化けを起こすと思う。
これはブラウザが送ったヘッダーで表示の仕方が指定されていたが、
ブラウザの持つ文字の自動認識の方法を使って文字列を再検出した為だろうと
予測される。

これはブラウザの更新(F5キー)でヘッダー関数ででUTF-8 を指定しているのであれば
再び元に戻るのでとても面白い仕組み的な側面が見えると思う。

最後に神経質に直したスクリプトの例を載せておこうと思う。

<?php
//ブラウザがこのスクリプトの出力の文字コードを割り出す為のヘッダー
header('Content-type: text/html; charset=UTF-8');

// 内部文字エンコーディングをUTF-8に設定
mb_internal_encoding('UTF-8');


$string
= '内部文字エンコーディング環境のTESTです!'.mt_rand(0,9).mt_rand(0,9).mt_rand(0,9);

// 文字の長さの検出の色々な仕方
var_dump(strlen($string));     //内部文字エンコーディングが違う環境に依存しない
var_dump(mb_strlen($string));    //内部文字エンコーディングが違う環境に確実に左右される
var_dump(mb_strlen($string ,'UTF-8'));  
//内部文字エンコーディングが違う環境に依存しにくい
?>



こんなこんな感じだろうと思う。


そして余談だが、UTF-8 でソースを保管する場合に、
もしソース中で文字を自身が指定したフォントを用いた画像で出力する為の、
imagefttext imagettftext 関数で画像を使う場合、
保存形式をUTF-8(BOMあり)ではなくUTF-8(BOMなし)にして保存しなければ、
画像データの先頭まで、ファイル形式の構造情報が3バイト付加されてしまうので、
画像データとして用いることができなくなるので注意が必要です。
UTF-16だと2バイトのBOMが付き、それは意味があるそうですが、
UTF-8でのBOMは実際には無意味なものらしいです。
詳しくは、BOM をどうぞ。

また画像を出力するスクリプトに
//ブラウザがこのスクリプトの出力の文字コードを割り出す為のヘッダー
header('Content-type: text/html; charset=UTF-8');
という内容は必要ないです。


ちょっと独り言:
当たり前って難しい・・・当たり前になるって難しい・・・当たり前に成る頃には忘れていたり、大したことがないこと・・・でも大切・・・

以上長いまとめのメモでした。

拍手[0回]


No Image

php x MySQL x Windows 7

PHP の調べ物

ぶっちゃけかなり長い間悩んだ事

php の構文からMySQL に接続する方法がOS によって違うのだ!
Windows 7 とWindows Xp でこの違いにハマり長い間悩んだ。

これはWindows の初期の設定の違いなのか、挙動の違いなのかは判らないが、
どうも ドメインの名前解決がWindows 7 の場合は行われていなかったのだ!!!


php のMySQL への接続を確立する構文の基礎例:
$conn = mysql_connect("MySQL のドメイン名","MySQL のユーザー名", "MySQL のユーザーのパスワード");

これがXp だと、ローカルホスト(localhost がドメイン名)である状況(まぁ別にそれ以外にしないと思うけど)にしておくのならば、
$conn = mysql_connect("localhost","MySQL のユーザー名", "MySQL のユーザーのパスワード");

で普通に動く。

しかーし、どうもWindows 7 だと動かない・・・・
これをドメインをIPアドレスに直した形にしないと所期の設定の違いなのか、ドメインの名前解決の挙動の違いなのか判らないが
以下の様にしなければ動かない。

$conn = mysql_connect("127.0.0.1","MySQL のユーザー名", "MySQL のユーザーのパスワード");


どうもこれは、Window Xp の方が特殊なのかもしれない、なぜならばApache でもかなり昔に書いた
qualified domain name(FQDN:完全修飾ドメイン名)のエラー
で説明した通り、IPアドレスに直さないと動かないのであった。


今回は短めに。

拍手[0回]


No Image

勘違いで見つけたcURL(Client URL Library)と思ったが!!!

PHP の調べ物

 何時もの様に、自由に迷ってみました、
そしてその迷ったこの思いをやはり何時もの様に、綴っておこうと思います。
(右往左往して毎度毎度間違えから何かを確実に少しづつですが得ていると思いますw)

 複数のURLを意識せずに同時に開きたいと思って、
PHP のマニュアルで色々探してみた。

 プロセス制御環境でPHPのスクリプトを同時に走らせようかと思ったが、
UNIX では動くがWindows では動かないとか、プラットフォームに依存する
関数が多くみられたので困った。

 具体的には、PCNTL — プロセス制御 を使おうと思ったがその
プラットフォームに依存するので、OSに合わせて自動で切り替わる様な
スクリプトを書くのはどうも安定した結果が出せない気がしていました。

 他にもそのプロセス制御で、セマフォ — セマフォ、共有メモリおよび IPC
とか、下記※の様な条件付きでの共有メモリなども含め複数のURLを同時に
取得する方法を入手しようかと思いましたがなかなか見つかりませんでした。

※「Windows 2000 より前のバージョンの Windows では共有メモリをサポートしていません。
Windows では、PHP が Apache や IIS などの web サーバモジュールとして稼動している場合にのみ」

 そしてまたこれもこのブログを書きながら間違えだったと気が付いたのですが、
cURL という物がありました。

 このcURL とは、例えばログイン処理してからしか見られないサイトなどで
ログインのアドレスやパスワードを元にログイン処理をしてから
ログインしてから見られない情報を得るなど、しっかり手順を追って処理出来るように
した物の様です。

 私が欲しい物では無かった様ですが、ネット上で調べるとセオリーの様な話があるので
一応メモ書きをしている訳です^^;

cURL はWindows 環境で有効にするには、php.ini の中にある
;extension=php_curl.dll を使えば良い様です。
これの「;」を取り除き有効にします。
一応私は確認の為にPHP のext フォルダの中身を見て
中にphp_curl.dll がある事を確認しました。

 また導入前のWindows 環境でphpinfo()関数を用いたとしても
cURL と言う言葉すら出てこないので、一瞬これは対応していなのかな?
と思いましたが、しっかりphp_curl.dll をphp.ini のextension を有効にして
Apache(私の場合)を再起動すればすぐに項目が現れました。
(私のApache 用のVC6コンパイルのPHP5.33の環境にて)

 やはりWindow 環境で開発している分、そういうプロセス関係で
PHP のスクリプトを呼び出すなどは現在のPHP ではプラットフォームに
依存する様な書き方が一番性能が良い様で、プラットフォームを選ばない方法で
これだ!と思える関数やライブラリは無い様でした。

 とりあえずは、Window の環境でのなんらかの方法を見つけ、
その後でWindow環境とLinux 環境でも使えるスクリプトを作れるなら
作ってみようと思った、しかしプラットフォームごとにプロセスの仕方が違うと
レスポンスなどは全く変わってしまうだろうと思う、私が思うに最大のネットアクセス数か
何かがWindow で改良というか改造を加えなければ、10にも満たない記憶がある、
これはDoS攻撃かなにかの踏み台にされない為にそうなったハズだが、
これを外す方法はある、いずれにせよやはりサーバはLinux(UNIX)の方が
有利であることは良くわかった・・・・PHPでさえも!・・・・

 私は欲張った構想と、小さなテストプログラムを幾度も頭の中や紙や
ソース(スクリプト)上で書いてみて色々するタイプだが、考える事の方が
時間を取られる事もあり、頭の整理や実感をする為にこのブログを書いた事は
私らしくも恥ずかしいが否定できないだろうと思った。

                                以上メモでした。

追伸:


以上だと思ったが!!!

まだ桎梏(しつこく この漢字生まれて初めて使う、脱線気味でごめんw)追求していると
どうもこのcURL で並列に実行できそうだ!!!!!!!!!!

  並列処理にもっていくには、cURL マルチハンドルに、通常の cURL ハンドルを追加するらしい。
その関数は、curl_multi_add_handle() という関数みたいだ。

 ぶっちゃけ目から鱗&目から涙だ;v;wwww うれしすぎるw

 これで私のしたい事がいっぱい終わりそうだ。
何度も言うがうれしいw よくやったPHP これからも期待している><bw

拍手[0回]


No Image

php 5.3.2 php 5.3.3 へ やっぱり個人メモw

PHP の調べ物

 またも本格的に開発を進める前に、
Windows 7 のPC を手に入れてしまったので、
そちらのPC へ開発環境を入れようとした時にPHP のバージョンが
上がっていたのでついでにバージョンアップしようと思った。

私の行うWindows 環境のPHP の以降は極めて簡単で、
httpd はApache を用い、そこそこのマルチスレッドのPCなので
PHP のダウンロードはVC6 x86 Thread Safe のダウンロードをして
php.ini の内容を比較し、エディターで書き換えた物を用意し、
元のディレクトリーにあるPHP を消して、新しい物と置き換え、
Apache サービスを再開してみるだけである。

 今回設定としてバージョンアップとして項目が関係しているのは
session.entropy_file の様です。

 この項目は、session.entropy_file で指定したリソースに関しての
設定の様で、バイト数を指定し、デフォルトは、0 (無効)だそうです。
 特にPHP 5.3.3 でこのsession.entropy_file で変わった所は、
ランダムでファイルパスと言うかIDを作ることの様です、この表現は間違っているかも
しれませんので、具体的には公式のページを見てください。

 元々このsession xxx の設定の意味がよくわからなかったのですが
よく調べてみると、phpやWebでのセッションの意味が私が良くわかっていなかったのが
良くわかりました。

 この場合のPHPのセッションとは、個別のコンピュータごとに
違う結果を残す為の仕組みの様です。

 その場合のセッションの情報を残す為の場所を指定するのが、
session.entropy_file であり、その情報の読み取るバイト数を
session.entropy_length で決める様です。

関連の関数としては、
session_start 関数
session_register 関数
などがある様です。

 まだセッションの設定は色々ある様ですが、
私はまだプログラミング出来ない、していない段階なので、
詳しくはgoogle検索をした方が良いでしょう。(私がwですww)

さて、後は元のphp 5.3.2 のphp.ini の内容を
5.3.3 の新しく使うphp.ini の設定に変更点や修正を書き込むだけです。

本当に個人的なメモになります、全く他人には当てにならないメモなので悪しからず。

拍手[0回]


[PR]