わけあってPHPでSHA256を書いた

PHP4の環境でHMAC-SHA256が必要になったわけだけど当然hash_hmac()はPHP5からなので使えない。

Pearのライブラリもいろいろと探してみたけど、内部でmhash()つかってたり、自分でサーバー環境いじれない状態のところでやらなきゃいけなかったんでしかたなくアルゴリズムからコードに落としてみた。

とりあえずgithubに上げといた。

一応バグはないと思う。
問題はPHP4の環境でまだ動かしてないということ。
PHP5の環境ではとりあえず動いてた。
PHP4でダメなシンタックスがあるかもしれんけど、それはこれから。

パフォーマンス考えてたらデータ全部メモリに一度のっけちゃうのがいいのかもしれないけど64Byte単位で処理するようにした。
それでも内部の演算に乗算、除算はやらずにシフト演算で対応した。

C言語とかやってた時期はバイナリ操作やりまくってたけど、PHP触りだしてから全然やらなくなったから、文字列がバイナリデータだってことに気が回らず文字列をバイナリ化しようと悩んでしまった。

javascriptでIPアドレスを取得する

なんか、「javascript ipアドレス 取得」のキーワードでこのブログに訪問してくれている人がいるので、一応書いておこうかと。

JavascriptでIPアドレスは取得はできません。

一部のサイトではActiveXが動作しないと取れないと書いていたりします。
それってJavascriptでIPアドレス取れてないってことですね。
Javascriptのバージョンが上がれば将来的には取れるようになるかもしれませんが、現状ではJavascriptでIPアドレスは取得はできません。

大事なことなので2回言いました。

サーバーにリクエストがきた時点でIPアドレスは取れます。
Javascriptでは取れないのでサーバーサイドでIPアドレスを取得して、レスポンスでIPアドレスをクライアントに渡してあげて下さい。

サーバー側でIPアドレスを取る方法はググればいくらでも出てくると思います。

WebPayのPHPライブラリをV2に移行してみた。

WebPayが定期課金に対応して、PHPのライブラリも定期課金対応されたが
ライブラリのメジャーバージョンがアップしてた。

APIのバージョンは据え置きでライブラリのバージョンがあがったのみだけど
ライブラリのV1との互換性がなくなった。

とりあえずバージョン見て処理切り替えるようにコード変更しようと思ったわけだけど
ドキュメント見てもバージョンの取り方は書いてないし、ソース見てもWebPayクラスにバージョン情報がなかった…

V1のコードと見比べてメンバ変数に殆どが”s”がなくなってるのと
幾つか追加されたメンバ変数があるだけでその先のメソッド名の変更はないっぽい(全部は追いかけてないけど)

とりあえず、WebPayクラスのインスタンス生成は互換性あるんで
メンバ変数をproperty_exists()で判定できた。


$wabpay = new Webpay('secret-key');
$version = property_exists($webpay, 'charges') ? 1 : 2;

$charge = ($version === 1) ? $webpay->charges->create($data) : $webpay->charge->create($data);

だいたいこんな感じ

property_exists()が__get()をオーバーライドしてたからいけるか不安だったけど…

node.jsでプロセス分割

ちょっと1プロセスで使用できるメモリサイズの限界を超えてしまったので、
マルチプロセスで使用するメモリサイズを分割しようと思っていろいろとドキュメント読んだりしたけどイマイチよくわからなかった。

最初ははじめてのNode.js:マルチプロセスアプリケーションを作成するを見たんだけども、書いてる内容はリクエストの負荷分散の内容だったので殆ど参考にならず。

処理を分割したいだけでリクエストを割り振りたいわけじゃなかったので、
参考サイトのようにnet.createServer()を使う必要がなかった。
とりあえずchild_processモジュールをロードしてfork()することは分かった。

node本家のドキュメントを見て、いろいろとごにょごにょしてみたもののさっぱりうまくいかなかった。

親プロセスでリクエストに対して呼び出す子プロセスを切り替えたかったので
子プロセスにリクエストとレスポンスのオブジェクトをsend経由で渡したら動かないし…

そして、エラーをよくよく見たら、messageはオブジェクトでもいけるけど
なぜか一旦json形式のテキストデータに変換されるため、
functionを持つオブジェクトをmessageで受け渡しできない。

パフォーマンス優先で行きたかったので、子プロセスでレスポンスを返せるのが一番だったのだが…
仕方ないので、子プロセス側から親プロセスに実行結果を戻すようにして何とか完成。
プロセス間のデータはそれほど大きくないからオーバーヘッドもそれほど気にならない感じ。

そうはいっても大量のアクセスが来た場合にどうなるかはまだ不明だしなぁ。
とりあえずはこれでうまく行ってくれればと願うばかり。

Laravelで特定のURL以下にフィルターを適応する

最近Laravelを使い始めていろいろと苦悩しています。

ドキュメントを読んでもさっぱりです。
言いたいことが伝わってきません。
まぁドキュメントについてはLaravelに限ったことではありませんけど…

で、本題です。

Laravelで特定のURLにはAuthとかもろもろ前処理をしたいときに

Route::filter('myFilter', function() {
// なんかのフィルタ処理
});

でフィルタを定義して、

Route::get('path', array('before' => 'myFilter'), function() {
  return 'before filter!';
});

で、URLにフィルタを紐付けるわけです。

まぁこれをいろいろなURLでフィルタを使うときにこれを全部書くとかめんどくさすぎる。
一応まとめてやるには公式ドキュメントにはこんなサンプルコードがあるわけですが

Route::filter('myFilter', function()
{
  //
});

Route::when('user/*', 'myFilter');

これだと、https://hoge.com/userにはフィルタがかからない。
あくまでhttps://hoge.com/user/以下に対してだけになる。
https://hoge.com/userにもフィルタをかけたい場合は

Route::when('user', 'myFilter');
Route::when('user/*', 'myFilter');

と、書けばいいんだけど、これはこれでなんか納得行かない
で、ものは試しにと

Route::when('user*', 'myFilter');

ってやったら、どっちにも対応した。
ただし、https://hoge.com/usersってのがあったらこれにもフィルタが掛かってしまう。

グルーピングを使ったほうが楽なんだろうか?
他にスマートな方法があったら教えて。
まぁこのブログには連絡先は書いてないわけだけど