PHP で OAuth Consumer Request (2-legged OAuth)

前に「OAuth Consumer Request の処理フローと実装」で紹介した 2-legged OAuth 処理のPHP版です。

通常の OAuth では、ユーザの確認画面を間に挟んでトークンのやり取りを行いますが、OAuth Consumer Request は既に信頼関係にあるという前提でトークン発行、承認の手順を省いたものです。コンシューマとサービスプロバイダ二者間での信任フロー(2-legged OAuth)になります。詳しい仕様については下記を参照してください。

» OAuth Consumer Request 1.0 Draft 1

まずは、実際の処理手順を説明していきましょう。コンシューマは次のパラメータをサービスプロバイダに送信することになります。 Consumer Key と Consumer Secret については、サービスプロバイダから提供されているものを使います。

oauth_consumer_keyコンシューマキー
oauth_signature_methodHMAC-SHA1 or RSA-SHA1
oauth_signatureシグニチャ
oauth_timestampUNIXタイムスタンプ
oauth_nonceランダムな文字列
oauth_version1.0 (オプション)

ここで、 oauth_signature は以下のようにして生成されます。まず、ベース文字列を用意します。

  1. GET
  2. http://api.gu3.jp/v1/test/auth
  3. oauth_consumer_key=yamashita.dyndns.org&oauth_nonce=c83b1847200
    bd25d918c3fb077aca16f&oauth_signature_method=HMAC-SHA1&
    oauth_timestamp=1219931263&oauth_version=1.0

次にこれらをURIエスケープした後に & で連結して、ベース文字列を生成します。

GET&http%3A%2F%2Fapi.gu3.jp%2Fv1%2Ftest%2Fauth&oauth_consumer_key
%3Dyamashita.dyndns.org%26oauth_nonce%3Dc83b1847200bd25d918c3fb0
77aca16f%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp
%3D1219931263%26oauth_version%3D1.0

そして、このベース文字列を HMAC-SHA1 によってダイジェスト値を生成し、BASE64 でエンコードすることによってシグニチャを生成します(サービスプロバイダによっては RSA-SHA1 の場合もあります)。この際、利用する共有キーは cosumer_secret と 空のToken Secret を & で連結したものになります。例えば、 consumer_secret が kd94hf93k423kf44 なら kd94hf93k423kf44& になります。こうして、シグニチャは以下のようになります。

M32qYtcaUD8b1Kb/AponRG5hrwI=

こうして生成されたパラメータをAPIリクエスト時の Authorization ヘッダに追加して、サービスプロバイダに送信します。

Authorization: OAuth realm="http://api.gu3.jp/",
               oauth_consumer_key="yamashita.dyndns.org",
               oauth_signature_method="HMAC-SHA1",
               oauth_signature="M32qYtcaUD8b1Kb%2FAponRG5hrwI%3D",
               oauth_timestamp="1219931263",
               oauth_nonce="c83b1847200bd25d918c3fb077aca16f",
               oauth_version="1.0"

実際のPHPスクリプトは次のようになります。なお、実行には Google Code にて公開されているPHP用ライブラリ(OAuth.php)が必要です。

<?php
require_once 'OAuth.php';
define('CONSUMER_KEY', 'yamashita.dyndns.org');
define('CONSUMER_SECRET', 'kd94hf93k423kf44');

function OAuthConsumerRequest($method, $url, $data=NULL) {
    $consumer = new OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
    $signature_method_hmac_sha1 = new OAuthSignatureMethod_HMAC_SHA1();

    // access protected resources
    $oauth_request = OAuthRequest::from_consumer_and_token($consumer,
                                                           NULL,
                                                           $method,
                                                           $url);
    $oauth_request->sign_request($signature_method_hmac_sha1,
                                 $consumer, '');

    $headers = $oauth_request->to_header();

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array($headers));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    $result = curl_exec($ch);
    if ($result === FALSE) {
        return curl_error($ch);
    }
    curl_close($ch);
    return $result;
}

$ret = OAuthconsumerRequest('GET', 'http://api.gu3.jp/v1/test/auth');
print($ret);

PHPからMecabを利用する拡張モジュール

PHPからMecabを使いたかったので、Page2さんで公開されているPHP拡張モジュールを試してみた。試したのは、PHP5とMecab 0.95という組み合わせ。

  1. ソースのダウンロード
    $ wget http://page2.xrea.jp/pub/php_mecab-0.2.0.tgz
    $ tar zxvf php_mecab-0.2.0.tgz
  2. コンパイルとインストール
    $ cd php_mecab-0.2.0
    $ /usr/bin/phpize
    $ ./configure --with-php-config=/usr/bin/php-config \
    --with-mecab=/usr/bin/mecab-config
    $ make
    $ sudo make install
  3. 動作確認
    <?php
    dl('mecab.so');
    
    $t = new MeCab_Tagger();
    $str = 'すもももももももものうち';
    
    echo $t->parse($str);

    実行結果1

    す      接頭辞,名詞接頭辞,*,*,す,す,*
    もも    名詞,普通名詞,*,*,もも,もも,代表表記:股
    も      助詞,副助詞,*,*,も,も,*
    もも    名詞,普通名詞,*,*,もも,もも,代表表記:股
    も      助詞,副助詞,*,*,も,も,*
    もも    名詞,普通名詞,*,*,もも,もも,代表表記:股
    の      助詞,接続助詞,*,*,の,の,*
    うち    名詞,副詞的名詞,*,*,うち,うち,*
    EOS

    問題なく動作しているようだけど、「すもも」が一つの名詞として認識されてなくて、「す」+「もも」という変な組み合わせになっている。次に辞書をJumanからipadicに変更してみる。

    <?php
    dl('mecab.so');
    $options = array('-d', '/var/lib/mecab/dic/ipadic');
    
    $t = new MeCab_Tagger($options);
    $str = 'すもももももももものうち';
    
    print $t->parse($str);

    実行結果2

    すもも  名詞,一般,*,*,*,*,すもも,スモモ,スモモ
    も      助詞,係助詞,*,*,*,*,も,モ,モ
    もも    名詞,一般,*,*,*,*,もも,モモ,モモ
    も      助詞,係助詞,*,*,*,*,も,モ,モ
    もも    名詞,一般,*,*,*,*,もも,モモ,モモ
    の      助詞,連体化,*,*,*,*,の,ノ,ノ
    うち    名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
    EOS

    今度はちゃんと認識してくれた。素晴らしい!

PRhagger@第20回PHP勉強会

KLab株式会社@六本木ヒルズで行われているPHP勉強会に来ています。

内容は、PHP Extensionの作り方と Rhaco で作られたアプリケーションの紹介が2つ。Rhacoというのは、DjangoのGeneric Viewやテンプレート継承の仕組みを取り入れたPHP向けのフレームワークです。で、このRhacoを使って作ったPHP版Plaggerが話題になり、勉強会の申し込み開始から数時間で定員がいっぱいになってしまったとのことでした。そういえば、いつものPHP勉強会とは違って、Perl界隈の人が多いような…


PHP Extensionを作ろう

  • PHP4とPHP5
  • 会社のサーバ落ちたので聞けなかった(残念)

Prhagger

  • haltさんの自己紹介

    幼稚園の時にスーパーマリオをワープなしでクリア
  • 某サイトの話とか

  • Subscriptionプラグイン FeedIn,bloglines,CustomFeddMixi

  • Filter FilterLou

  • Publish

  • Rhacoフレームワーク 名前はアオガエルから

  • 次回はエロPRha

    Publish_Photozouでエロ動画10000ファイル保存w
    iTunesで見たり
    YouTubeは帯域制限がかかっているので1日中動かしている
  • Perl版があるのにそのモチベーションはどこから?

    PerlよりPHPが得意だから
    Plaggerは敷居が高い
    アップロードしただけで動くようにしたい
    やりたいからやっている

WorkStyle

  • GTDツール

  • PHP版の他にJava版もある, Python版も作成予定

  • rhacoの特徴

    Easy setup
    Library independent
    URL mapping
    O/R Mapping
    Generic View
    Admin

ここのところのPHP勉強会は、話題がてんこ盛りで面白いですね。懇親会でDo you PHP?の人といっぱい話ができたのも収穫でした。次回の勉強会も出たいです。

PHP勉強会に参加してDjangoで掲示板を作りました

第17回PHP勉強会に参加してきました。会場となったECナビさんのオフィスは、とても綺麗でステキでした。

内容は時間内に各自で掲示板を作ろうというもので、皆さん、EthnaとかSymfonyとかお気に入りのフレームワークで作っていました。僕はというと、後ろのほうで隠れてDjangoで作りました。PHP勉強会なのにごめんなさい、ごめんなさい。

メインロジックはあっという間にできてしまって、HTMLとかスタイルシートが一番時間がかかった気がします(といってもadmin画面のパクリだけど)。実際にコードを書いたのは50行くらいです。本当にシンプルで面白くもなんともないのですが、せっかく作ったので公開することにします。これからDjangoを始めようという方向け。


勉強会の後の懇親会にも参加させてもらいましたが、PHPな方々と交流できて楽しかったです。

LLRing直前オフに行ってきた

PHPとPythonな人達が合同でLLRing直前オフをやるというので、参加してきました。
Software Design編集部やインプレスの人もいて、かなり盛り上がったよ。
  • 柴田さんが 『みんなのPython』 にサインを書きまくっていた。自分も持って行けばよかった。
  • Djangoの露木さんにいろいろ聞く。Djangoの勉強会を開催しようということに(決定ですよね?)
  • uemuraさんと初めて話した。Macのことをもっと聞きたかった。
  • tokuhiromさんがいいこと言ってた。「Rails含め他のWebフレームワークは横並び、Djangoはひと味違う」
  • Ura5hanの人がスーツ姿で登場して、「今日はJavaのコスプレしてますが」と言っててウケた。

  • PythonよりPHPのほうが若い人が多い気がする。
  • PHPのフレームワークは、関東と関西で人気のものが違うらしい。
  • Zend Frameworkはまだまだらしい。
  • むむむさん、面白かった。

CFUSION_ENCRYPT関数をPHPで書いてみる

思いっきりチラシの裏。中身は文字列とキーの排他論理和をとって16進化してるだけ。

function cfusion_encrypt($text, $key) {
    $keylen = strlen($key);
    $j = 0;
    $newval = "";

    for ($i=0; $i<strlen($text); $i++) {
        if ($i >= $keylen) $j++;
        $wd = (ord(substr($key, $i - $keylen * $j, 1)) ^ ord(substr($text, $i, 1)));
        $newval = $newval . sprintf("%02X", $wd);
    }
    return $newval;
}

PEAR::HTML_TreeMenuとDB_NestedSet

今日は、HTML_TreeMenuDB_NestedSetではまってました。
どちらもPEARというPHP用のライブラリです。規模は違うけど、PerlのCPANみたいなものですね。
HTML_TreeMenuがツリー構造のメニューを配列から生成するもので、DB_NestedSetがその配列をデータベースに保存するためのものです。ノードの追加や移動などのメソッドが用意されてるんで簡単にツリー形式のメニューが作れます。ただ、ドキュメントが少なくてここに辿り着くまでにかなり苦労しました。

最初、PEAR::Treeを試したんですけど、HTML_TreeMenuとの連携という点ではDB_NestedSetのほうが簡単です。DB_NestedSetのメソッドとして実装されているので、HTML_TreeMenuは意識する必要がありません。
ただ、1.3以降のベータバージョンでないと、tree_toHTML()というメソッドが使えないので、出力を変数に格納することができません。CMS等で使う場合は、最新版にしましょう。
本当はここにサンプルを載せたいけど、風邪をひいたらしく体調悪いのでまた次回。

もう、XOOPsやめます

/.クローンとしてしばらく使ってきましたが、自分が求めてる機能とのずれを感じてきたのでxoopsやめます。
・纏まったドキュメントを管理したい
・モジュール(ポートレット?)を簡単に追加できる
・RSS提供サイトが増えてきたのでうまく組み込む
・ローカルなコミュニティを複数作りたい
見た目は、plone.orgみたいな感じでTrackBackに対応したやつを自分で作ろうかなぁ。
PHPで作ったポータルフレームワークを発展させるか、JAVAの勉強を兼ねてJetspeedでやるか。

Xoops 2.0.1とRSSヘッドライン

今日は風邪が悪化(変な肺炎かと心配するくらい)して咳が止まらないので、午後から仕事を放棄して帰ってきました。
病院に行ったはいいけど、保険証を置き忘れて家に電話がかかってくるなど散々でした。もう3日くらい禁煙してたり、情報処理の試験を欠席したりして治そうと努力してるのに一向に良くならない。こりゃ誰かに移すしか…

本題に入ると、ちょっと前にXoops 2.0.1にアップグレードしました。
アップグレード自体は上書きして、スクリプトを実行するだけととても簡単です。テーブルの更新も自動でやってくれます。よくできてます。
が、ヘッドラインモジュールが曲者でした。今は右側に/.とjapan.linux.comのヘッドラインが表示されてると思います。これが最初は正常に表示されるんだけど、2回目以降の更新がうまく動かないという不具合がありました。しかも、ページ全体を道連れにして何も表示されなくなってしまう。
さらに不運なことに、そのタイミングでGoogleのロボットがおいでになったために真っ白ページをインデクシングされてしまいました。

一応、次の対策で直ったと思うのだけれど、ちょっと自信なし…

modules/xoopsheadline/class/headline.php の123行目で常にtrueを戻すように変更しました。
 return false → return true

# 違うかなぁ。風邪引いて体調悪いので自信なし。

Xoops 2.0に移行しました

本日、Xoops 2.0RC3にアップグレードしました。 表面的にはあまり変わらないけど、管理側がとても使いやすくなっています。テンプレートを採用したことでViewのカスタマイズが簡単になりました。そして、モジュールの出力もプログラムをいじることなくカスタマイズできます。ソースを見ないとどんな変数が使えるか分からないので、お手軽とは言えないけど良いです。見習わなくちゃ。 気になったのは、キャッシュをして高速化を図っているみたいなんだけど、ファイルがあちこちに散らばっていて変更を反映させるのにどれを削除したらいいのか迷うところ。この辺は、アプリケーションレベルではなくてサーバレベルで一括して出来たらいいのに。