2008年04月03日
Atom 1.0 リファレンス
RFC4287の原文と日本語翻訳+構造図で、インタラクティブに参照するAtom(Syndication Format)の仕様。
- デフォでは図のように、左側に構造図を、右側にRFC仕様を表示します。左上の「仕様の全文を表示」リンクをクリックすると、仕様の全文をダラダラと表示します。
- 構造図モードでは、クリックした箇所に応じた仕様のセクションを右側に表示します。右上の「戻る」と「進む」はブラウザのボタンと同じイメージ。
- 構造図中で名前の後ろに「?」と「*」がある要素や属性はオプションです(記号がないものは必須)。「?」はその場所に1個だけ、「*」は複数登場できます。ただしこれは原則で、オプションであっても条件次第で必須となるとか、あれこれ例外があるので要注意。例えばatom:authorはオプションですが、ドキュメントのどこかに少なくとも1個はないとダメです。あるいは例えば、atom:contentのないatom:entryには<link rel="alternate" href="~">が必須です。詳細は仕様を熟読してください(主なルールは仕様のセクション4.1.1と4.1.2にまとめられています)。
- 構造図中で「atomCommonAttributes」となっているブロックは、その中の属性がAtomの共通属性(仕様のセクション2)であることを表しています。決して<atomCommonAttributes xml:lang="ja"/>とか書けという意味ではありません(笑)。同様に「atomなんとかConstruct」となっているブロックは、共通の構造体(仕様のセクション3)です。
- RFC仕様の記述に合わせて、Atomの要素はすべて「atom」という接頭辞を付けて表記してますが、通常Atomの要素はデフォルトの名前空間に属することになる筈で、その場合接頭辞はもちろん不要です。
以下は余談。
最初はRSS 0.9x/2.0とRSS 1.0とAtomとの簡単な比較表を作ろうと思ってたのでした(そして、RSS 1.0やAtomの仕様は、杜撰な鷹揚なRSS 0.9x/2.0のそれと比べて厳格なので、各フォーマットを共通のデータソースから生成しようとする場合には、データソースの準備は厳格な側に合わせてやらないとワヤになりまっせ、という講釈を垂れようとしていた)。
で、しかしRFC4287を眺めてたら、Relax NG(のコンパクト構文)スキーマによるストラクチャー表現を、ブロック図に置き換えて操作できるようにしたら面白いかもと思い立ち(この時点で比較表を作ろうという当初の目的は潰える)。しかし要素を並べただけではアレなので説明を加えるにしても、RFC原文のコピペだけでは不親切かなということで、ついでに日本語訳も用意してみた次第。
既存のRFC4287の日本語翻訳
- http://blog.good-day.net/~iwai/wiki/wiki.cgi?page=Atom+Format+%CB%AE%CC%F5
- http://momdo.s35.xrea.com/spec/rfc4287j.html
- http://www.futomi.com/lecture/japanese/rfc4287.html
- http://www.7key.jp/rfc/4287/rfc4287.html
Category: ウェブ制作
Posted 2008年04月03日 00:49
2008年04月02日
iMenuのGoogle検索がいきなりおかしなことになってる件
Googleモバイルで「プロフィール」や「プロフ」を検索すれば、1位は前略プロフだろうと思うのは素人。
http://www.google.co.jp/imode/search?ie=Shift_JIS&mrestrict=chtml&site=mobile&q=%83v%83%8D%83t%83B%81%5B%83%8B確かに、PCで普通に検索してみれば、少なくとも本日ただ今現在の1位は前略プロフで、そのPCで、Googleモバイルで「プロフィール」を検索する上のアドレスを開けば、本日ただ今現在の結果は以下のような感じで、やはり前略プロフが1位。
- 前略プロフィール
『前略プロフィール』は、誰でも手軽に携帯電話・パソコンの両方に対応した、自己 ...
pr.cgiboy.com/ - FC2プロフ - あなた専用のプロフィールを作ってみよう!!
あなた専用のプロフィールが簡単に作れちゃう!!プロフィールを作ってみよう!!
pr.fc2.com/ - Amazon.co.jp: プロフィール: デューク・ピアソン,ジーン・テイラー ...
Amazon.co.jp: プロフィール: デューク・ピアソン,ジーン・テイラー, ...
www.amazon.co.jp/プロフィール-デューク・ピアソン/d... - 佐野夏芽プロフィール
タレントプロフィール ・ フォトダイアリー ・ タレント募集 ・ メールマガジン登録 ...
www.metalbox.co.jp/work/sano/pcolum... - みんなのプロフィール
みんなのプロフィール 名前をクリックするとプロフィールを閲覧できます。 ...
www.yukinosake.com/cgi-bin/profile/...
しかし、少なくとも本日ただ今現在、「PREF」という名称のcookieを削除してから上記のモバイル版のアドレスを開いてみると、以下のようにまったく違う結果が表示される。1位は関西のデリヘル。ちなみにこのcookieがない状態で100位(10ページ)まで検索しても、前略プロフは出てこない(以下にもあるような、前略を騙るサイトは出てくる)。
- 大阪・兵庫・京都・奈良・和歌山巨乳ロリ・ギャル系専門デリバリーヘルス ...
プロフィール南大阪 ・ プロフィール京都 ・ プロフィール兵庫 ・ プロフィール奈良 ・ プロフィール和歌山 ...
www.pro-file.jp/m/ - 携帯(ケータイ)無料プロフ作成フリーサイト「My・ぷろふぃーる」
完全無料でマイプロフィール交換画面を作成できる携帯電話専用プロフ提供フリー ...
vl-o-l.jp/ - プロフィール
プロフィール. 名前:すぬーぴー. 種別:ビーグル犬の. ぬいぐるみ. 年齢:不明 ...
penguinmaru.fc2web.com/i/profile.html - 前略プロフィール by aimew
プロフガイドは数あるプロフィールサイトを厳選してご紹介!もちろんプロフを通じて新しい ...
aimew.jp/zennryaku/ - 前略プロフィール by aimew
JC、JKに人気のあるプロフィールサイト♪. 前略出会い系 ...
aimew.jp/zennryakud/ - 携帯無料プロフ作成 チェキ!プロフィール
チェキ!プロフィールでは簡単☆無料でプロフィールサイトを作成できます!
chpr.jp/ - プッチギャル
女の子コメント:いちゃx2楽しい時間を過ごしましょうねぇ(*^^)v ...
www.kobe-pucchigal.com/m/gal/k-view... - 京都デリヘル/プッチギャル
キャッチコピー:☆京都に渋谷系GAL誕生☆ドエロEカップに大興奮! ...
www.kyoto-pucchigal.com/m/gal/k-vie...
さて、cookieの有無で検索結果が変わるということは、cookieを喰わないドコモの端末ではどうなるかというと、もちろん上と同じ、1位がデリヘルという結果になる。
で、ドコモは4月1日からiMenuのトップ画面にGoogleと連携した検索機能を追加し、Googleの検索エンジンにより、携帯電話向け一般サイト、PCサイトの検索結果も表示されるようになったのだけど、そのiMenuの検索フォームから「プロフィール」を検索してみた結果が以下。
- 携帯(ケータイ)無料プロフ作成フリーサイト「My・ぷろふぃーる」
完全無料でマイプロフィール交換画面を作成できる携帯電話専用プロフ提供フリー ...
vl-o-l.jp/ - プロフィール
プロフィール. 名前:すぬーぴー. 種別:ビーグル犬の. ぬいぐるみ. 年齢:不明 ...
penguinmaru.fc2web.com/i/profile.html - 前略プロフィール by aimew
JC、JKに人気のあるプロフィールサイト♪. 前略出会い系 ...
aimew.jp/zennryakud/ - 京都デリヘル/プッチギャル
キャッチコピー:☆京都に渋谷系GAL誕生☆ドエロEカップに大興奮! ...
www.kyoto-pucchigal.com/m/gal/k-vie...
一瞥して明らかなように、これは上の、通常のGoogleモバイルでの結果のサブセット。1位のデリヘルが消えているのは、おそらくドコモなりのフィルターで、「有害」と判定されているサイトが除去されてるためではないかと思われ。
しかし京都のデリヘルは見事このフィルターをくぐり抜け4位に躍進!(4位だとiMenu検索の1ページ目に表示されるので、それ以下とは雲泥の差)なんという脅威のSEO!(違)
………とまあ、そんなこんなで。これはたまたま出くわした極端な例ですが、別にこの例に限らず、ドコモ端末でGoogleモバイルを利用すると、検索結果がなんだかおかしなことになってる模様です、というお話ですた。
Category: ウェブ制作
Posted 2008年04月02日 23:41
2007年06月01日
opm.blitzed.org is pointing at a blackholed nameserver
MovableTypeの管理画面にあるSixApartからの告知に、【重要】コメント投稿に時間がかかる現象についてと出ていて、なにかと思ったら、opm.blitzed.orgが停止したので、バンドルされているSpamLookupプラグインの、DNSBLサーバの設定がデフォルトのままだとヤバイですよ、というハナシで。
いや、ちょっと待てと。OPMが停止したのは一年も前なわけで。それを今頃になって告知かと。OPM statusによると、今年の5月にopm.blitzed.org is pointing at a blackholed nameserver
ということになったそうで、そのため告知にあるような事態が生じるようになって問題が顕在化したらしい。
で、なんでブラックホールリストのサーバがブラックホール行きになったかというと、in order to reduce query load on our servers
だそうで。なんで未だにそんな状態かというと、多くのMTユーザが(もちろんMTだけじゃないだろうけど)OPMの停止を知らずに、デフォルトで設定されているサーバをそのまま使い続けていたであろうからで。なんでそんなことになってるかというと、誰かに言われない限り、普通はDNSBLサーバが停まってるなんてことには気付かないよな、と(ましてデフォルトで設定されてるものだし)。
多くのDNSBLサービスはボランティアな運営なわけで、いつなくなっても不思議ではなく。そもそもDNSBLは、ボットネットの拡大によって以前ほど効果的ではなくなっており、ORDB.orgのようにこれを理由に閉鎖してしまった例もあり。あるいはzen.spamhaus.orgのように、新たなサーバが用意され以前のもののリプレイスが推奨される場合もあり。斯様な状況でDNSBLを利用する場合は、利用するサーバの状況を定期的に確認して設定を見直す必要があるわけですが、それをすべてのユーザにやれというのも無茶なハナシで。しかしMTには折角管理画面に告知コーナーがあるのだから、早期に告知がされていればユーザもSixApartも、そしてBlitzed.orgも無用のトラブルを抱えずに済んだのになあ、と。
………と、OPMの死亡告知を死亡から半年後に出したヤツが、自分のことは棚にあげて自戒の念を込めて申し上げてみるテストでございました。合掌。
以下はMTのハナシではないけれど、DNSBLネタが少々。
Category: ウェブ制作
Posted 2007年06月01日 23:59
Firefox 2/IE7用、OpenSearch検索プラグイン(検索プロバイダ)作成ツール

Firefox 2やInternet Explorer 7などの検索バーに検索サイトを追加するOpenSearch形式のプラグインを、極力簡単に作れるようにしてみました、というものです。要Cookie+JavaScript。実は随分前に作って、しかし腑に落ちないまま放置していたものを引っ張り出してきて、全面改装。
» OpenSearch検索プラグイン(検索プロバイダ)作成ツール
ものは試し。上のリンク先で、ページの右側の「ブックマークレット」欄にある、「検索プラグインの作成」というリンクを、マウスの右クリックとかでブックマーク(お気に入り)やツールバーに登録してみてくださいな。
で、例えばGoogleとかで、「TEST」を検索した結果のページでそのブックマークレットを選択してみてください。下図のような表示が出てきたら正解。以上の操作がメンドクセーひとはここをクリック(笑)。

「検索プラグインを追加」ボタンをクリックすると、確認ダイアログが表示され、プラグインを追加できるわけですが、お気に召さない項目があれば適宜編集していただければと存じます。各項目の説明は、その入力欄をクリックすると説明が出てくる筈。編集後には「確認・更新」ボタンをクリックしてください。
「名前」は、ウェブブラウザはこれでプラグインを管理してるので、既に登録済みのプラグインと同じ名前は付けられません。
「アイコン」は、Firefox 2の検索バーに表示されるものです(IE7では利用されません)。アイコンはウェブサイトのFaviconを自動検出しますが、Faviconがないサイトや、自分好みのアイコンを使いたい場合は、画像をアップロードすることもできます。画像がJPEGやGIF、PNGなら、自動的に画像の中央部を切り出してアイコンサイズに縮小するので、あらかじめアイコンサイズの画像を用意しておく必要もありません。
なお、ここで検索プラグインを作成できるのは、GETメソッドの検索フォームのみです。つまり、検索結果のページのアドレスに、(検索キーワードである)「TEST」という文字が含まれないものは作成できません(POSTメソッドによる検索プラグインは、OpenSearchの拡張仕様のひとつとして用意されているParameter要素を使って作成できますが、IE7はこれに対応していないためPOSTメソッドのプラグインは利用できません)。
いまでは多くのウェブサイトがオフィシャルな検索プラグインを提供していますが、提供されてない(提供しそうにもない)サイトや、ありそうでなさそうなサイトや、あるいは提供されてるけど名前やアイコンが気に入らない類は、自分で(勝手に)作っちゃえばいんじゃないかと。以下は、現時点でオフィシャルが存在しないものをテキトーに見繕ってみた例。
» 「Firefox 2/IE7用、OpenSearch検索プラグイン(検索プロバイダ)作成ツール」の続きを読む
Category: ウェブ制作
Posted 2007年06月01日 19:22
2007年05月26日
HTMLをXML化してDOMやXPathで操作するWebスクレイピング用PHPクラス
SimpleXML+HTMLParser or Tidy+HTTP_Request+Cache_Liteの組み合わせで、リモートサイトから取得したHTMLソースを整形して、SimpleXMLオブジェクトに変換するライブラリでございます。サーバサイドはもとよりクライアントサイドのAjaxでも、DOMやXPathなどを用いたオブジェクト操作によるScrapingが可能になります。要SimpleXMLなのでPHP5専用(もっとも、SimpleXMLをDOM XMLに置き換えればPHP4でも同じようなことはできますが)。
ええっと手っ取り早く、以下にアクセスしてフォームに適当なURLを入力してみてください。
下図のようにURLがダラダラとリストされれば正解。

ここでリストされるURLは、ご覧いただければおわかりの通り、入力したURLのウェブページ内にあるA要素のHREF属性値なわけですが、ポイントはこれを、responseXMLからDOMで取得していること。つまりXMLHttpRequestのリクエスト先は、well-formedなXMLを返してるということでございます。あと、HREF属性値はすべてフルパスに変換されてたりもします。
そのXMLHttpRequestのリクエスト先であるPHPアプリのソースは以下の通り。
<?php
if (!isset($_GET['url']) or empty($_GET['url'])) {
header("$_SERVER[SERVER_PROTOCOL] 400 Bad Request");
header('Content-Type: text/plain;charset=UTF-8');
exit('The URL is not specified.');
} else {
require_once 'HTMLScraping.class.php';
$s = new HTMLScraping;
try {
$xml = $s->getXmlObject($_GET['url']);
} catch (Exception $e) {
header("$_SERVER[SERVER_PROTOCOL] 400 Bad Request");
header('Content-Type: text/plain;charset=UTF-8');
exit($e->getMessage());
}
$s->convertPath($xml, array('a' => 'href'));
header('Content-Type: application/xml;charset=UTF-8');
exit($xml->asXML());
}
?>
HTMLScraping->getXmlObject()は、第1パラメータのURLで取得したHTMLソースから生成したSimpleXMLオブジェクトを返します(エラーの際には例外を投げますんで、上の例のようにtry~catchしてやってください)。
ちなみに、キャッシュ処理を行う場合、まずは以下のように、コンストラクタの第1パラメータにキャッシュファイルを保存するディレクトリを指定しておきます(このディレクトリはもちろん、PHPアプリに対するread/writeパーミッションが必要です)。
$s = new HTMLScraping('/tmp/');
で、getXmlObject()の第2パラメータに秒数を指定すると、URLのレスポンスが指定した秒数キャッシュされます。
$xml = $s->getXmlObject($_GET['url'], 3600);
その他のオプションパラメータやその他のメソッドの説明、及び配布アーカイブのダウンロードなどは、説明ページへどーぞ。
応用例:HTMLをScrapingしてRSSフィードを生成する
さてこれだけでは面白くないので、これの応用例としてHTMLからRSSフィードを生成するということをやってみました。と言ってもHTMLの内容は多様で一律に処理できるわけはないので、共通処理をまとめたabstractなクラスを用意し、この継承クラスでオーバーライドするメソッド内で、HTMLScraping->getXmlObject()で取得したSimpleXMLオブジェクトから必要なデータを抽出していただこうという寸法でございます。
注意:これはあくまで応用例として用意したもので、実用に供されることを意図したものではありません。
配布アーカイブ中のexamplesディレクトリにあるtest_feed.phpはこのサンプルアプリケーションで、同ディレクトリ内にあるtest_feed.htmlからリストアイテム要素を取り出し、フィードを構築して出力します(このアプリケーションはキャッシュ機能を使用しますので、実際に自分の環境で実行する場合は、コンストラクタのパラメータで指定しているキャッシュファイルの保存先ディレクトリ名を、実際に利用可能なものに変更してください)。
HTMLToFeed.class.phpは、test_feed.php内で継承しているabstractクラスHTMLToFeedを定義しています。HTMLToFeed->getFeed()は、DOMで構築したフィードを出力しますが、キャッシュ処理が有効な場合は、フィードの出力をキャッシュし、出力にLast-Modified/Etagヘッダを含めて、If-Modified-Since/If-None-Matchによる条件付きリクエストに応答します。
test_feed.phpでは、アクセス先のURLが単一(しかもコンテンツが変更されない)であるため、出力のみをキャッシュしていますが、複数のURLにアクセスしてその内容をマージするような場合、URLごとに、その更新頻度に応じてキャッシュの有効期間を設定し、それに加えて出力もキャッシュすることで、アプリケーションのパフォーマンスを向上させることができるかもしれません。
DisclaimrBETA
まあこれは、こんな感じでこんなことができますよというサンプルであって、これを広く使ってもらおうなんていう気は毛頭なく。仕様も自分の好みでやらかしてるので、あんまし汎用的ではないかもしれず。そもそもライブラリの組み合わせからして、別段この組み合わせに限ったわけでも、もちろんありません。
特に、Tidyが利用できればこんなことはもっとお手軽に(リソースの消費も少なく高速に)できちゃうわけで。しかし、HTMLParserの趣旨にも書いたように、現在の一般的なレンタルサーバのPHP環境ではこれは殆ど利用できない筈なので、そういう場合には利用価値があるやもしれませんが(このライブラリでは、Tidyが利用可能ならそちらを、そうでなければ(自動的に)その代替にHTMLParserを利用するようになってたりはします)、そんな感じのツクリなので、気に入らないところがあれば、しょせん既存のライブラリの組み合わせなので、わざわざオーバーライドするよりは自分好みの仕様で作り直しちゃうことをお勧め申し上げる次第でございます。
Category: ウェブ制作
Posted 2007年05月26日 00:25
2007年03月25日
ながらTube
Flash Media Playerで遊ぼう企画の第3弾くらい。再生するプレイリストを自動生成しようというネタ。Flashビデオが大量に転がってるところといえばあそこなわけで。そのAPIでプレイリストを作ればいんじゃん?という安直な企画デスネ。
で、出来たのが以下。
» ながらTube
上のリンク先のページの右側にプレイヤーが表示されると思いますが、そのままではいまいち面白くなさそうなビデオがリストされてるかと思います。
で、その左側にある入力フォームでキーワード検索ができるので、ここに好みのキーワード、例えば「浦和レッズ」とか入れてみてください。配色も変えられるので、「Background」を赤に変更してみましょう。「Foreground」と「Rollover」は白と黒の組み合わせがいい感じではないかと。最後に「Update」ボタンをクリックすると、プレイリストの内容とプレイヤーの見栄えが変わるという寸法です。
- ボリュームスライダーの左隣にあるフルスクリーンボタンをクリックすると、ビデオをPCの画面全体に拡大して再生します(ただし、バージョン9.0.28以降のAdobe Flash Playerがインストール済みであること)。
- プレイリストの各ビデオの右端にあるInfoボタンをクリックすると、YouTubeの、そのビデオのページに移動します。
- キーワード検索ではなく、自分の好きなビデオを再生したい場合には、まずはビデオをYouTubeのMy Favoritesに登録してください。そしてながらTubeで、入力フォームに自分のYouTube IDを入力して、その下のラジオボタンのうち「username (to play his/her favorites)」にチェックを付けてください。これで「Update」ボタンをクリックすると、My Favoritesに登録したビデオがリストされます。
これまで見てきた、ページの右側に出てくるヤツは、ウェブやブログに貼り付けることを想定した「バッジ」版なのですが、一方で下図のように、これをサブウィンドウで表示して、デスクトップで鑑賞する用途を想定した「バー」版もあります。
ながらTubeの、バーの説明にある「Nagara Tube Bar (Bookmarklet)」というリンクをクリックすると、バッジ版と同じ内容が、下図のようにサブウィンドウに表示されます(タブブラウザではポップアップウィンドウの設定を変更する必要があるかもしれません。IE7ではタブブラウズの設定中の、ポップアップの発生時の動作を確認してください)。このリンクはブックマークレットにもなるので、ブックマークやツールバーにこのリンクを登録しておくと、以降はそれを選択するだけで同じ設定のバーを表示できます。
さて。
とか書いときながら実際にブログとかに貼られまくられちゃったりするとそれなりの負荷になるわけで。いつものようにソースを晒してるので、ご利用は自鯖でどーぞ。ただし、自作の部分はいつも通りフリーソフトウェアですが、Flash Media Playerはそうではなく、特に商用利用の場合はライセンス料金が必要になる点ご注意ください。
Category: ウェブ制作
Posted 2007年03月25日 22:58
2007年03月09日
“Reason for Living” - Roddy Frame (a.k.a. Aztec Camera)
ここにはFlashオブジェクトが表示されます。ここにFlashオブジェクトではなくこのテキストが表示されたままの場合は、以下の原因が考えられます。
- RSSリーダーとかで表示している。
- ウェブブラウザがDOM対応のものではないか、JavaScriptが無効になっている。
- Flashプレイヤーがインストールされていない。
- おいらの手違い。
お送りしている曲は、アズテックカメラことロディ・フレームの1998年のスリーコードチューン、「Reason for Living」です。
で、これは字幕作成のテスト。
歌詞が字幕で表示されるのって好きなんですよ。歌われる言葉は音楽の一部なので、ともすれば聞き流してしまいがちなのですが、書かれた言葉を目にすることでそれをしっかりと捉えられる気がするのです。殊に僕らの言語が採用している表意文字では文字そのものが具体的なイメージを喚起するので、なおさらそう思えるのかもしれません。
A little something about the tune
- オリジナルの歌詞は本家ファンサイトや日本のファンサイトに掲載されています。
- 日本盤のCDリリースはお馴染みの「歌詞・対訳つき」なわけですが、KISSファンクラブの初代会長であるらしい青柳つとむという御仁の手になるこの対訳がヤバイ。Pureヤバイ。誤訳とか意味が通じないとかそういうレベルじゃない。もう全然別モノ。適当な聞き取り起こしをあてがわれたのだとしても、英語習いたての厨にやらせても、こんな訳にはなるわけない。もはや神の御業。
- 日本盤のシングルCDのオビに書かれたキャッチコピーは、「輝きは 目映いばかり 北の空」。俳句かよっ。
Technical things
- 字幕の編集はSubtitle Workshop。ハードサブ作成はVirtualDub+VobSub。
- こちらで使ったFlash Media Playerがバージョンアップして、SubRip形式(.srt)などの字幕ファイルを表示する機能が追加されたので(flashvarsの「captions」パラメータで字幕ファイルのURLを指定する)、最初はそれを利用しようと思ったのだけど、どうにも字幕の表示がズレまくる。ズレ具合が一定ではないのでタイムコードをずらして済ませられるわけでもなく、とは言えこれにタイムコードを合わせたものを作ろうとしても、Subtitle Workshopのような編集ツールが利用できるわけではないので手間がかかるし、プレイヤーが改修されたら使い物にならなくなる。そんなことで、しかたなくハードサブで済ませることにしたわけですよ。無念。
- ちなみにFlash Media Playerが受け付ける日本語入りの字幕ファイルの文字エンコーディングはUTF-8で、一方Subtitle Workshopで作成した字幕ファイルの文字エンコーディングはShift_JISなので、プレイヤーに読み込ませる際は、あらかじめ文字エンコーディングを変換しておく必要がある。
Category: ウェブ制作
Posted 2007年03月09日 20:10
2007年03月06日
野菜小屋の地図をGoogle Maps APIで作ってみるテスト
飛田給駅の利用者なら、表通りでも派手に宣伝しているので大丈夫でしょうが、そうでなければ知らないひともいるかもしれないので、野菜小屋の地図を用意してみますた。
という口実で、GoogleマップのDOM APIで遊んでみたテスト。以下はトーキョーとは無関係。
» 「野菜小屋の地図をGoogle Maps APIで作ってみるテスト」の続きを読む
Category: FC東京, ウェブ制作
Posted 2007年03月06日 22:49
2007年01月12日
携帯JavaアプリのFlickrビューアがお蔵入りになった件
信頼すべき情報筋によれば、“ポケットflickr”というコードネームで昨年末にコソコソ製作されていた、携帯電話向けJava実行環境用の、Flickrのビューア・アプリケーションがお蔵入りになった模様。
製作者はお蔵入りの理由について、「飽きたから」と語っているという。参考までに、製作者の血液型はB型とのこと。
ポケットflickrは、Flickrの写真を、Interestingnessや、タグ、フリーテキストなどで検索して、携帯電話で閲覧するビューア。表示した写真はJavaの保存領域に保存しておくことができ、待ち受けアプリなどとしても楽しめるなどの、よくありがちな機能が予定されていた。
なお、携帯電話のカメラで撮影した写真をアップロードする機能は、「メールでやればいいじゃん」ということで、そもそも検討されていない。
ポケットflickrは、クライアント用のJavaアプリケーションと、FlickrのAPIとの通信や、携帯電話向けの写真の加工、及びこれらのキャッシュ処理などを行うウェブサーバ用のアプリケーションで構成され、その最初のバージョンは、NTTドコモのFOMAシリーズ用iアプリとして2006年内にリリースされる予定であった。
なお、製作が再開される見込みについては、「ないない」とのこと。
このエントリーの画像には、idfontで公開されている「id-カナ007」フォントを使用しています。このフォントの著作権は、井上デザイン・井上優さんが所有しています。Category: ウェブ制作
Posted 2007年01月12日 23:04
2007年01月11日
heywatch.comどうでしょう
Hey! Watchは、各種の動画変換(再エンコード)を行う、マルセイユ発のウェブサービスでございます。
動画変換のウェブサービスなんてえものは既に多々あるわけですが、TechClunchの記事に、メインの機能はREST APIでディベロッパー向けに公開し、サービスに直接に構築できるよう配慮している
(ちなみにヘンな日本語は原文のママ、とゆうかTechClunchの日本語はしばしばヘン)と書かれてたので触ってみますた。
Hey! Watchは、現在は本サービスに移行していますが、つい先日までは「invitation only beta」でした。以下のハナシは原則、その頃のものです。始まったばかりのサービスなので内容はどんどん変更されていく筈で、現状は違ってる可能性がたぶんにあることにご留意ください。
基本的な使い方はいたってシンプル。
- 変換したいビデオを、ローカルからアップロードするか、URLで指定する。
指定できるURLは:- ビデオファイルのURL。
- ビデオファイルのURLが書かれたウェブページのURL(複数ある場合はあらためて選択する)。
- YouTubeやGoogleビデオなど、対応している動画配信サービスのウェブページのURL。
- ビデオがいったんHey! Watchに転送されるので、完了するのを待つ(転送状況は随時確認できる)。
- 転送が完了したら、変換したいフォーマットを選んでエンコードする。
ただし、Hey! Watch全体で、同時に行えるエンコード数には制限がある。これは「スロット」という単位で表現されており、「空きスロット」があれば直ちにエンコードが行われるけれど、そうでなければ待たされる(エンコードの状況も随時確認できる)。
アカウントには、無料の「Free」と有料の「Watcher」(なんでそういう名前なのかは不明)があり、Watcherアカウントは$4.99/月で、「まとめて払えばお得」なプランもあり。ちなみに支払い方法は、現時点ではPayPalのみ(イケてないところ、その1)。
ふたつのアカウントの違いが具体的に書かれたページはログインしないと見れないので、以下にサクっとまとめてみた。
| 制限 | Free(無料) | Watcher($4.99/月) |
|---|---|---|
| 1ヶ月間に可能なエンコード回数 | 10回 | 100回 |
| エンコードフォーマットのカスタマイズ | NG | OK |
| 転送した(オリジナルの)ビデオの保存期間 | 6時間 | 12時間 |
| エンコードしたビデオの保存期間 | 12時間 | 24時間 |
| 同時に可能な転送数 | 1 | 3 |
| 同時に可能なエンコード数 | 1 | 3 |
| ビデオあたりの再生時間の制限 | 10分 | 25分 |
| ビデオあたりのデータサイズの制限 | なし | なし |
| 転送量の制限 | なし | なし |
ちなみに、このページに限らず、ヘルプですらログインしないと見れません(イケてないところ、その2)。
APIどうでしょう
ウェブインタフェースは非常にクールで直感的だが、REST APIも同様に直感的なものだ。ただし、現在のAPIドキュメントは、必要最低限の内容しか用意されていないので、APIドキュメントの解読は直感的というわけにはいかない(笑)。そして、ご多分に漏れずこのドキュメントも、やはりログインしないと見れません。見たければユーザ登録するアルよ。
Hey! Watchのサービスはユーザ認証が前提なので、APIアクセスもユーザ認証が必須ですが、その認証方式は、To use our API, you must be authenticated via Basic Auth.
ということで、ベーシック認証でございます。HTTPSでもないので、パケットでIDとパスワードが丸見えなんだな、これが(イケてないところ、その3)。
基本的な仕様はごく普通の(素直な)REST API。
POSTでリソースを作成し、GETで情報取得、PUTで変更、DELETEで削除。
例えば、YouTubeのFLVを変換するなら、/discoverにページのURLをPOSTしてFLVのURLを検出させる。
POST /discover.xml HTTP/1.0 Authorization: Basic hoge Host: heywatch.com Content-Type: application/x-www-form-urlencoded Content-Length: 58 url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DBPsfbV9t8Vw
POSTのレスポンスではまだ検出が完了しているわけではないので、同じURLを適宜GETして検出の完了を確認する。
GET /discover.xml HTTP/1.0 Authorization: Basic hoge Host: heywatch.com
で、検出が完了したXMLレスポンスはこんなんで、RESULT要素の中身がFLVのURL。
どうでもいんだけど、CREATED-AT要素のタイムゾーンがお国柄を匂わせてたりします。
<?xml version="1.0" encoding="UTF-8"?>
<discovers>
<discover>
<id>12345678</id>
<status>ok</status>
<download>false</download>
<result>
http://www.youtube.com/get_video?video_id=BPsfbV9t8Vw&l=61&t=OEgsToPDskI5F9Jp4wgYUqAzjmkPJN7D
</result>
<url>
http://www.youtube.com/watch?v=BPsfbV9t8Vw
</url>
<title>
YouTube - YouTube Happy New Year
</title>
<created-at>
Mon Jan 01 00:00:00 +0100 2007
</created-at>
</discover>
</discovers>
で、検出が完了したらそのURLを、今度は/downloadにPOSTして、Hey! WatchにFLVを転送開始。同様に適宜GETして転送の完了を待ち、完了したら今度は/jobに、そのビデオのIDとエンコードフォーマットのIDをPOSTしてエンコード開始…。
まあ、そんな感じ。
レスポンスの形式は、XMLの他にJSONとYAML。この指定は、APIのリクエストURLに対応する拡張子を付けて行います。例えば、エンコード済みのビデオの一覧を取得する場合、XMLなら「GET /encoded_video.xml」、JSONなら「GET /encoded_video.js」という感じ。
なお、リクエストによっては特殊なレスポンスが用意されていて、例えば「GET /encoded_video.rss」とすると、エンコード済みのビデオの一覧のRSSフィード(Podcastコンパチ)が出てきたり、「GET /encoded_video/video_id.jpg」とすると、エンコード済みのビデオのサムネイル画像が出てきたりします。
リクエスト結果は、まずはHTTPステータスコードで判断するわけですが、ドキュメントにあるのは、200 OK、201 Created、204 No Content、400 Bad Request、404 Not Found、406 Not Acceptable。
どうでもいんだけど204は、means that the resource has been updated or deleted successfully
と書かれていて、おそらくPUT/DELETEの成功を示すのだろうけど、ステータスコードの本来の意味からするとヘン。
一方406は、the format you asked is not available
と書かれていて、この「format」はおそらくエンコードフォーマットのことなのだと思うけど、だとしたら、ステータスコードの本来の意味の履き違え。
携帯どうでしょう
Hey! Watchのエンコードフォーマットには「Mobile 3GP」や「Mobile 3GPP2」、「Mobile MP4」といった選択肢があり、また、Watcherアカウントであればフォーマットのカスタマイズも可能で、例えば「Mobile 3GP」のビデオコーデックはH.263なのだけど、これをMPEG4に変更したりできる。
これらのフォーマットに変換したビデオは、日本の携帯電話でも再生できる場合もある。ただし、Hey! Watchはおそらく、LinuxプラットフォームでFFmpegを使ってエンコーディングを行っており、FFmpegでのエンコード時の問題がそのまま残される(例えばドコモ端末でストリーミング再生できないとかいう類)。
これについてHey! Watchの中のひととメールでやり取りしてみますた(ちなみにレスポンスはめちゃめちゃ迅速でした)。
指定のデータサイズでビデオを分割できるようにして欲しいなあという要望は、やんわりと、しかし即座に却下。3GP_Converter(aka 携帯動画変換君)のQT3GPPFlattenの例を挙げて、Atomフィールドの書き換えとかやって欲しいなあという要望を出してみたら、こっちはうやむやのうちに却下(笑)。
唯一、指定のデータサイズになったらエンコード糸冬了という機能だけ検討してくれることになりますた。って、それってFFmpegに-fsパラメータ渡すだけじゃん。
Category: ウェブ制作
Posted 2007年01月11日 19:10
2006年12月26日
第一次ハラ東京最後の日
天皇杯のハナシを書いてて思い出した、第一次ハラ東京最後の試合となった、松山での天皇杯レッズ戦で撮影していたビデオを公開しておこうかと。
- 以下のビデオは、少なくとも5年ほど前のPCでは、おそらくろくすっぽ再生されやしないと思われ。
- ファイルがバカデカく、YouTubeがクソ遅いので、いったんFLVをダウンロードして見たほうがいいと思われ。
試合後の挨拶
ガスサポの行進
というフリして、動画をYouTubeにアップしてみたテスト。
以下はテストのメモ。もはやハラ東京とは無関係。
Category: FC東京, その他のスタジアム, ウェブ制作, 愛媛のお勉強
Posted 2006年12月26日 18:43
2006年12月15日
Galicia - Sí, es única
ここにはFlashオブジェクトが表示されます。ここにFlashオブジェクトではなくこのテキストが表示されたままの場合は、以下の原因が考えられます。
- RSSリーダーとかで表示している。
- ウェブブラウザがDOM対応のものではないか、JavaScriptが無効になっている。
- Flashプレイヤーがインストールされていない。
- おいらの手違い。
久しぶりにルアル・ナ・ルブレ Luar na Lubre のウェブサイトが更新され、なにかと思いきや、YouTubeにアップされてる自分たちのビデオへのリンク集というネタで。TVGで放映されたスタジオライブとか、旧作のビデオクリップとか、日本のルブレオタ(推定3人程度)にとっては垂涎の映像が拝めるわけですが、これらはもちろん“オフィシャルに”アップロードされたものなわけはなく。うちらの国なら、アーティスト本人より先にJASRACあたりが、「削除と謝罪と賠償とユーザーの氏名・住所の登録制を要求するニダ」と騒ぎ立てるんだろうなと思ったり。
さて、上のFlashな動画はTurgalicia(ガリシア観光局)が今年の夏に制作したテレビCM集です。
「Tu Gitana」が最初のふたつのもののBGMに採用されているため、ルアル・ナ・ルブレのウェブサイトでも紹介されていますが、いかんせん本家の動画(左のメニューね)を日本から眺めようとすると、ダウンロードにドえらい時間がかかる上に、一部HTMLがクズなのでまともに見れやしない。てなことで、ガリシアへのニッポン人観光客誘致の一助になればという願いをこめて…。
というフリをしてFlashビデオをあれこれいじってみたテスト。
以下はテストのメモ。もはやガリシアとは無関係。
» 「Galicia - Sí, es única」の続きを読む
Category: ウェブ制作, ガリシアのお勉強
Posted 2006年12月15日 21:54
2006年11月22日
ぜろちゃんねる(0ch BBS Script)掲示板のスパム対策
1ヶ月ほど前から、うちのぜろちゃんねる掲示板に英文スパムが来襲するようになり、当初はDNSブラックリスト(DNSBL/RBL)で対処してたのですが、プロのスパム屋は新しいプロキシを次々と用意してくるわけで、ブラックリストがすべてを網羅できるわけはなく。それでも数が少ないうちはコマメに消してたのだけど、日増しにその数が増えて、やってらんねえ状態になったので、こんなふうにしてみますた、というメモ。
やってることは、2ちゃんねる BBQなどの任意のDNSBLサービスに登録されてるホストからの投稿を弾くのと、日本語文字(Shift_JISの2バイト文字)が本文に含まれない投稿を弾くこと(いわゆるひとつのBanAscii)。後者はURLだけのカキコとかも弾いてしまうわけですが、まあしょうがない。
ぜろちゃんねるスクリプトの改造は正直かなりマンドクセー('A`)わけですが、これなら改造が1箇所で済むし簡単な処理なのだけど、結構効果的なのではなかろうか、と。
追記@2007/01/30
- 0ch BBS Scriptの2007/01/24版でも確認。
- こちらを参考に、本文にAタグやBBCodeが含まれる場合、及びメール欄に@が含まれる場合も弾く処理を追加。
# 0ch BBS Scriptの2005/11/13、2006/02/27、2007/01/24版で確認
# test/module/vara.plファイル内の
# IsRegulation(規制チェック)サブルーチン(2007/01/24版なら296行目あたり以降)内の
# 適当なところ(例えば「# 規制ユーザ・NGワードチェック」とある行の前)に
# 以下の「...」に囲まれている箇所を追加
# エラー番号は既存のものを流用なのでエラーメッセージも既存のもののままです
# それではワケワカランと思われる場合は、test/info/errmsg.cgiに新しい番号とメッセージを追加し
# 以下の「return」の後に続く番号をそれと取り替えるとモアベター
sub IsRegulation
{
...
# 本文にShift_JISの2バイト文字が含まれていなければ
# 600エラー(NGワード)
if ($this->{'FORM'}->Get('MESSAGE') !~ /[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC]/) {
return 600;
}
# 本文に<a~>または[url=や[url]が含まれていれば
# 600エラー(NGワード)
if ($this->{'FORM'}->Get('MESSAGE') =~ /(<a\b[^>]*?>|\[url(?:\s?=|\]))/i) {
return 600;
}
# メール欄に@が含まれていれば
# 600エラー(NGワード)
if ($this->{'FORM'}->Contain('mail','@')) {
return 600;
}
# IPアドレスが以下で指定するDNSBLのいずれかに登録されてれば
# 997エラー(PROXY規制)
# ブラックリスト鯖はお好みで
my @dnsbls = (
'niku.2ch.net',
'bsb.spamlookup.net',
'bbx.2ch.net'
);
$ENV{'REMOTE_ADDR'} =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
foreach my $dnsbl_host (@dnsbls) {
$dnsbl_host = "$4.$3.$2.$1.$dnsbl_host";
if (gethostbyname($dnsbl_host)) {
return 997;
}
}
...
}
で、昨日これを仕込んで以降24時間のうちに、以下のようなホストがスパムの投稿にやってきたわけですが、幸いすべて弾けた模様。エラーが103となってるものは「本文長すぎ」で、これは規制チェックより前に実施されるので、これに引っ掛かるヤツもいるのだけど、これで既に結構な数が弾けている。で、600エラーが本文に日本語文字が含まれなかったもの。ここまでですべて弾けてしまい、結局DNSBLのチェックにまではどいつも至ってなかったり。
| 来襲時刻 | エラー | ホスト名 | #1 | #2 | #3 | #4 | #5 | 国 |
|---|---|---|---|---|---|---|---|---|
| 11/21 20:29 | 103 | c-71-230-86-217.hsd1.pa.comcast.net | US | |||||
| 11/22 19:13 | 600 | bzq-84-110-225-57.red.bezeqint.net | IL | |||||
| 11/22 19:13 | 600 | bzq-84-110-236-82.red.bezeqint.net | IL | |||||
| 11/22 19:12 | 600 | bzq-84-110-231-119.red.bezeqint.net | IL | |||||
| 11/22 19:12 | 600 | bzq-84-110-233-25.red.bezeqint.net | IL | |||||
| 11/22 16:48 | 103 | 82.137.247.132 | yes | SY | ||||
| 11/22 15:00 | 103 | www.farmington.k12.mi.us | yes | US | ||||
| 11/22 13:22 | 103 | 84-123-102-217.onocable.ono.com | ES | |||||
| 11/22 12:11 | 600 | 200.29.137.217 | yes | yes | CL | |||
| 11/22 12:10 | 600 | 218.236.45.155 | yes | yes | yes | KR | ||
| 11/22 12:05 | 600 | S01060040ca37ccf6.cn.shawcable.net | yes | yes | CA | |||
| 11/22 12:05 | 600 | avquarantine.sec.kq.no | yes | yes | NO | |||
| 11/22 11:23 | 103 | proxy4-jan.integrity.com | yes | US | ||||
| 11/22 10:17 | 103 | 89-149-205-145.internetserviceteam.com | yes | DE | ||||
| 11/22 09:51 | 600 | 218.236.111.150 | yes | yes | yes | yes | KR | |
| 11/22 09:37 | 103 | 82.137.247.131 | yes | SY | ||||
| 11/22 07:50 | 103 | 94.190.189.72.cfl.res.rr.com | US | |||||
| 11/22 06:21 | 600 | ool-44c0fe41.dyn.optonline.net | US | |||||
| 11/22 06:02 | 103 | adsl-75-52-193-66.dsl.chcgil.sbcglobal.net | yes | US | ||||
| 11/22 04:11 | 600 | bzq-84-110-226-237.red.bezeqint.net | IL | |||||
| 11/22 02:27 | 103 | ulbcenter-04-b07.it-datacntr.louisville.edu | US | |||||
| 11/22 01:08 | 103 | riy01che02.ae.net.sa | yes | yes | yes | SA | ||
| 11/22 00:38 | 103 | 64.8.149.34 | US | |||||
| 11/21 23:56 | 600 | bzq-84-110-251-251.red.bezeqint.net | IL | |||||
| 11/21 23:56 | 600 | bzq-84-110-252-72.red.bezeqint.net | yes | IL | ||||
| 11/21 23:55 | 600 | bzq-84-110-241-44.red.bezeqint.net | IL | |||||
| 11/21 23:31 | 600 | 220.119.158.14 | yes | yes | yes | KR | ||
| 11/21 23:30 | 600 | 86.35.202.101 | yes | yes | RO | |||
| 11/21 23:29 | 600 | 211.207.215.84 | yes | yes | KR | |||
| 11/21 23:25 | 600 | 210.113.30.208 | yes | yes | yes | yes | yes | KR |
| 11/21 22:53 | 103 | 63-109-248-28.reverse.newskies.net | yes | yes | yes | US | ||
| 11/21 21:15 | 103 | 89-149-205-145.internetserviceteam.com | yes | DE |
上表の「#1~5」の欄は、各ホストについて以下の各DNSBLサービスでの登録の有無です。
- 2ちゃんねる BBQ - niku.2ch.net
- SpamLookup - bsb.spamlookup.net
- The Spamhouse Project - sbl-xbl.spamhaus.org
- SpamCop.net - bl.spamcop.net
- RBL.JP - all.rbl.jp
ご覧の通り、どのブラックリストにも登録されていないホストが結構あり、プロのスパム屋に狙われたら、やっぱしDNSBLでの規制だけでは不十分なんだよね、ということですな。
なお、2ちゃんねる BBQはDSBLでの登録状況も併せて応答するので、上表ではDSBLは端折ってます(なので、このふたつを併用するのは無意味です)。また、ちなみにどのホストも、2ちゃんねる BBX(bbx.2ch.net)には登録されていなかったので、こちらも上表では端折ってます。
参考になったり興味深く拝見したページ
- The Spamhouse Project: ROKSO(既知のスパム屋のリスト) - GIGAZINEの記事「世界中のスパムメールの80%がこの200人によって送信されている」の元ネタの元ネタ。
- The Spamhouse Project: Worst Countries - 本日現在のトップ10チャートでは、ニッポンがロシアを抑えて堂々3位!
- 自分自身のためのものづくりメモ: 掲示板spam対策
- 不正アクセスの発信地の国別統計をとろう!
- ぜろちゃんねる用BBQプラグイン
- opm.blitzed.org has shut down - DNSBLのひとつでしたが、鯖屋とトラブってお亡くなりになられたそうです。
» 「ぜろちゃんねる(0ch BBS Script)掲示板のスパム対策」の続きを読む
Category: ウェブ制作
Posted 2006年11月22日 23:38
2006年10月20日
Googleカレンダーを携帯で利用するPHPスクリプト
これは自作のGData API用クラスライブラリのデモとして制作した、携帯電話向けにGoogleカレンダーの表示と編集を行うウェブアプリケーションです。
しかしそもそも、携帯電話の画面にHTMLだけで、カレンダー/スケジューラのまともなインタフェースを作るのは結構無理難題なわけで。いちいち通信が必要なウェブアプリじゃあ、操作性も決してよろしくなく。携帯電話でGoogleカレンダーを利用する理想形は、やっぱ、Googleカレンダーとデータを同期するJavaアプリとかだと思うのですよ。実際iアプリなどには優れたカレンダー/スケジューラが既に多くあり、これらがこういう機能を備えれば、こんなウェブアプリはそりゃもう用無しだ罠。
PC/PDAで、このスクリプトのオンラインデモを確認できます。
このデモでは、アカウントの認証をこのアプリの本来の方式ではなく、AuthSubという方式で行います。この認証方式は、iモードやEZwebなどの携帯電話ブラウザからは利用できません。またGoogle Apps for Your Domainのアカウントも利用できません(当然ですが、このアプリの本来の方式では、いずれも利用できます)。
アーカイブのダウンロード
» gcal.zip 0.9.5 (eternally beta) issued 2007-06-06
機能制限
- 「繰り返し」の予定は表示のみで、追加や編集はできません。
- 「ゲスト」は表示のみで、追加や削除はできません。
- 参加設定の変更時に「メッセージ」や「同伴者」の編集はできません。既に設定されている「メッセージ」は「コメント」のひとつとして表示されます。「同伴者」は表示もされません。
- カレンダーの作成や追加など、「設定」ページで行う操作はできません。そういうわけで、公開カレンダーの検索もできません。
以下は現時点でGoogle側に不具合があるための制限です。(追記参照)
コメントを投稿するとエラーになります。閲覧権限が「予定の時間枠のみ」のカレンダーは表示されません。
動作要件とか
- PHP 4.3.9/5.0.1以降。OpenSSLとXML(expat)とmbstring必須。.htaccessでphp_flagが使えないと困るかも。
- カスタマイズを想定しているファイル(設定ファイルとHTMLテンプレート)の文字エンコーディングはUTF-8(BOM無しのUTF-8N)なので、対応のテキストエディタが必要です。
- ウェブアプリなのに複数ユーザでの利用はできない建前になってます。設置者おひとりでご利用ください。
これは、ウェブアプリで使用すべきとされているGoogleアカウントの認証方式(AuthSub)がiモードやEZwebなどの携帯電話ブラウザでは利用できないので、しょうがなく、使用すべきではないとされている方式(ClientLogin)を用いているためです(Googleアカウントの認証方式の解説はアカウント認証の概要をご覧ください)。 - 簡単に設置できるように、アーカイブにはPEARの各ファイルも突っ込まれてたりするかもしれませんが、別途にインストール済みなら、もちろん削除してください。なお、PC2Mをご利用の皆さまにおかれましては、それ用に改変したHTTP_Request(pearpack.zipにあるHTTP/Request.php)は、こいつには使えませんのでご注意ください。
設置手順
このアプリ自体の認証は、携帯電話の端末ID(製造番号とかサブスクライバIDとかシリアル番号とか)とパスコード(暗証番号)で行います。(端末IDが送信される状態で)ログインフォームに暗証番号を入力するだけという、ケータイフレンドリーな認証ですね。
そういうわけで、最初に設定ファイル(Config.inc.php)に、端末IDとパスコード、そしてGoogleアカウントのメールアドレスとパスワードを登録しておく必要があります。
- アーカイブ内の各ファイルをサーバの任意のディレクトリにアップロードし、「data」ディレクトリのパーミッションを707など、書き込み可能なものに変更します。
- 携帯ブラウザで_check_auth.phpにアクセスし、パスコードを入力して表示される内容をメールなどでPCに送ります。この内容を、Config.inc.phpファイルの「$auth_db」とある箇所に登録してください。「SERIAL」と表示される内容を$auth_dbの「serial」欄に、「PASS」と表示される内容を$auth_dbの「password」欄に、それぞれ登録します。
- 引き続き$auth_dbの、「google_username」欄にGoogleアカウントのユーザ名(@記号以降のドメイン名までを含むメールアドレス)を、「google_password」欄にそのパスワードを登録し、Config.inc.phpファイルをサーバにアップロードします。
- PCや携帯のブラウザでgcal.phpにアクセスして、期待通りに動作するか確認してみてください。この時点ではまだ、認証はパスコードのみで、端末IDでの認証は行っていないので、PCのブラウザでもアクセスできる筈です。
- 最後に、Config.inc.phpファイルの冒頭にある「define('GCAL_USE_DEVICE_ID_FOR_AUTHENTICATION', true);」とある行の、先頭のコメント記号(ふたつのスラッシュ記号)を削除し、これをサーバにアップロードしてください。これで、認証時に端末IDも照合されるようになり、端末IDを登録した携帯電話以外からはアクセスできなくなります。
gcal.phpのファイル名は任意のものに変更できます。設定などは不要です。
HTML表示を変更するにはTemplate.htmlを編集してください。各種の設定はConfig.inc.phpで行います。
ありがちなトラブル
- スクリプトにアクセスするとHTTP 500 Internal Server Errorになる。
- アーカイブ中の.htaccessファイルをサーバにアップロードしている場合は、この. htaccessの記載内容による設定変更が許可されていないことが原因かもしれません。.htaccessファイル中の「php_flag」で始まる行を削除して、再度試してみてください。ただこの場合、サーバのPHPの設定次第では、このスクリプトは期待通りには動作しないかもしれません。
- 日時が日本時間じゃない?
- PHP4ではスクリプトが明示的にタイムゾーンを設定することができないため(できたっけ?)、日時はスクリプトが動作しているサーバのタイムゾーンに沿ったものとして表示されます。例えば海外のレンタルサーバなどでPHP4の場合は、日時が現地のタイムゾーンで表示されるかもしれません(適切なタイムゾーンが設定されていないサーバも同様です)。逆に、Googleカレンダーのタイムゾーンが海外に設定されていても、国内のサーバでは、PHP4なら日本時間で表示されることでしょう。
PHP5では、設定ファイルで、定数GCAL_TIMEZONEの値に指定したタイムゾーンのIDに沿ったものになります。このIDは、例えば「Asia/Tokyo」や「America/Los_Angeles」など、タイムゾーンのリストにあるものです。
ライセンスとか
このプログラムの本体であるgcal.phpファイルはGNU GPL v2+でライセンスされますが、このプログラムは、そそくさと制作を済ませるために既存のオープンソースソフトウェアをあれこれ流用しており、かつ簡単に設置できるように、アーカイブにはこれらのファイルも含まれてるかもしれません。こうしたソフトウェアのライセンスは、そのファイルに記載のものとなり、gcal.phpとは別にライセンスされる点ご注意ください。
- HTMLTemplate.class.phpファイルは、鮎川寛さんが制作された、HTMLテンプレートを操作するクラスライブラリ、HTML template for PHPです。
- XMLParseIntoStruct.phpファイルは、orbitphreak at yahoo dot comさんによる、XMLパーサ関数のドキュメントのUser Contributed Notesへの投稿が基になった、XMLをハッシュ構造に展開するクラスライブラリです。
- Googleディレクトリ内の各ファイルは、自前のGData API用クラスライブラリのものです。
- ClientDetect.class.phpファイルと_check_auth.phpファイルは、自前のPCサイト->携帯変換スクリプトの一部です。前者は携帯端末の判別を行うクラスライブラリで、DevInfo_DoCoMo.inc.phpファイルとIPRange.inc.phpファイルはこのクラスで使用する定義ファイルです。
- HTTPディレクトリとNetディレクトリ内の各ファイル、及びPEAR.phpファイルは、Richard HeyesさんとAlexey BorzovさんによるPEARのHTTP_Request、及びその依存パッケージです。
» 「Googleカレンダーを携帯で利用するPHPスクリプト」の続きを読む
Category: ウェブ制作
Posted 2006年10月20日 00:00
2006年10月04日
Google Calendar APIの基礎
当初はGoogle自身がPHP用のライブラリを用意する予定だと表明していましたが、結局10月の終わりになって、Zend Google Data Client Libraryが登場しました。てなことで、PHP5をご利用の場合、以下のクラスライブラリは無用の長物と化しましたので、そこはすっ飛ばして、カレンダーAPIの解説としてご利用ください(ZendのものはPHP5用なので、PHP4をご利用の場合には、以下のクラスライブラリにも利用価値はあるかもしれません)。
なお、Googleカレンダーの携帯向けウェブアプリは元々このクラスライブラリのデモとして作ったものなので、このまま放置の予定。
PHP 4/5 class library for Google Data APIs
これは、GData APIとの通信を処理する、PHP4/5用のシンプルなクラスライブラリです(フィードの解析や作成を行う機能は提供されません)。詳細はREADMEをご覧ください。
- アーカイブの内容
-
- Google
- Account.php - アカウント認証API用クラス
- GData.php - GData APIの共通クラス
- Calendar.php - カレンダーデータAPI用クラス
- Blogger.php - BloggerデータAPI用クラス
- test.php - テストアプリその1
- gbase_demo_alt.php - テストアプリその2
- XMLParseIntoStruct.php - XMLを配列に処理する汎用のSAXパーサ(おまけ)
- README
- Google
テストアプリその1(test.php)は、以下で説明するふたつのアカウント認証API(ClientLoginとAuthSub)のそれぞれを使ってカレンダーフィードを取得する、シンプルなものです。
テストアプリその2(gbase_demo_alt.php)はGoogle Baseで料理レシピの投稿と編集を行うものです。これは、Google自身による、Google BaseデータAPIのPHP版デモを、このクラスライブラリを使って書き直したもので、これを動作させるにはAPIキーを取得して、このスクリプトの冒頭に登場する定数「GOOGLE_BASE_DEVELOPER_KEY」の値にそれを設定してください。
目次
GoogleカレンダーデータAPIへのアクセスは、公開予定の取得、及び「magicCookie」と呼ばれるURLを利用した非公開予定の取得については認証は不要ですが、予定の追加、変更、削除には認証を要します。
ここでは最初にアカウント認証について、次いでカレンダーデータAPIについてまとめています。
Google Account Authentication
Google Calendar Data API
アカウント認証の概要
認証を要するGoogleの各サービスAPIへのリクエストを行うアプリケーションは、ユーザIDとパスワードそのものではなく、アカウント認証APIによって発行される、トークン(token)と呼ばれるその代替データを送信します。トークンはその有効範囲内で繰り返し利用可能なので、アプリケーションはアクセスの都度トークンを取得する必要はありません。
アカウント認証APIにはClientLoginとAuthSubがあります。
- ClientLoginはPCのデスクトップアプリケーションなどでの利用を想定したものです。ユーザIDとパスワードはアプリケーションが直接取り扱います。トークンは、アプリケーションがユーザIDとパスワードを送信して発行されます。
- AuthSubはウェブアプリケーションでの利用を想定したものです。アプリケーションはユーザIDとパスワードは扱いません。トークンは、ユーザがGoogleアカウントのウェブサイトで、そのアプリケーションに対してアクセスを許可する操作を行い発行されます。
AuthSubでは、ウェブアプリケーションは、ユーザをGoogleアカウントのウェブサイトに誘導して、アプリケーションに対するアクセスの許可を依頼します。このときのURLには、「next」パラメータに、AuthSubからのレスポンスを処理するURLを指定しておきます。
以下の画像は、ユーザに表示されるログインフォームとアクセス要求の確認フォームの例です。アクセス要求の確認フォームでユーザが「アクセスを許可」をクリックすると、「next」パラメータで指定したURLに対してリダイレクトが行われます。
注意
- 現在のGoogleアカウントは、セッション管理をCookieで行っているため、例えばiモードなどの携帯電話用ウェブブラウザのように、Cookieが利用できない環境ではGoogleアカウントにログインできず、AuthSubも利用できません。
- Googleアカウントではない独自のアカウントを提供していたサービス、例えばBloggerなどについては、AuthSubは独自アカウントでは利用できません(独自アカウントをGoogleアカウントに移行すれば利用できます)。
なお、AuthSubのアクセスの確認フォームでは、アプリケーションがGoogleに登録されたものではない場合、以下のような警告文が表示されます。
このウェブサイトはGoogleに登録されていないため、承認リクエスト用の保護された接続を確立できません。
下記のリンク先を信頼できる場合にのみ、処理を続行してください。
登録済みのアプリケーションでは、この警告文は表示されません。また、登録済みのウェブアプリケーションはセキュアなトークンを利用可能ですが、これはここでは省略します。
ClientLogin
ClientLoginでは、https://www.google.com/accounts/ClientLoginに対して以下のようなリクエストを送信します。
POST /accounts/ClientLogin HTTP/1.1 Content-Type: application/x-www-form-urlencoded Email=Email&Passwd=Passwd&service=service&source=source
ポストデータの内容は以下の通りです。
| キー | 値 |
|---|---|
| ユーザID(ドメイン名を含むメールアドレス) | |
| Passwd | パスワード |
| service | 対象サービスのID(Googleカレンダーの場合は「cl」) |
| source | アプリケーションのID(任意の文字列で、「企業名-アプリケーション名-バージョン」形式が推奨されています) |
| logintoken | CAPTCHAチャレンジのトークン(CAPTCHAチャレンジ以外では省略) |
| logincaptcha | CAPTCHAチャレンジの回答(CAPTCHAチャレンジ以外では省略) |
リクエストが成功した場合のレスポンスはHTTP 200 OKで、そのボディは、以下のような「キー=値」形式のテキストです。このうち「Auth」キーの値がトークンです。他の値は現時点では使用されていません。
SID=DQAAAGgA...7Zg8CTN LSID=DQAAAGsA...lk8BBbG Auth=DQAAAGgA...dk3fA5N
なお、リクエストが不成功の場合、そのボディが、以下のような「キー=値」形式のテキストで、「Error」キーの値が「CaptchaRequired」である場合があります。これは、ClientLoginがロボットなどによる不正侵入の可能性を疑い、CAPTCHAチャレンジ(画像認証)を要求しているものです。
Error=CaptchaRequired CaptchaToken=DQAAAGgA...dkI1LK9 CaptchaUrl=Captcha?ctoken=DQAAAGgA...dkI1LK9
この場合、アプリケーションは、「CaptchaToken」キーに示された値と、「CaptchaUrl」キーに示されたURLで表示されるCAPTCHAチャレンジ画像の回答を、それぞれ「logintoken」と「logincaptcha」の値としてポストデータに追加し、ClientLoginへのリクエストを再度行うことになります。
クラスライブラリを使ったサンプルプログラム
以下の例は、この文章の冒頭で紹介しているPHPクラスライブラリを利用して、ClientLoginでトークンを取得し、それを表示するものです。
<?php
$email = 'example@gmail.com';
$password = 'password';
require_once 'Google/Calendar.php';
$service = new Google_Calendar;
session_start();
if (!isset($_SESSION['tokens'])) {
$_SESSION['tokens'] = array();
}
if (!isset($_SESSION['tokens']['calendar'])) {
if (!$service->requestClientLogin($email, $password)) {
exit("ClientLogin has failed.\n".$service->getResponseBody());
}
$_SESSION['tokens']['calendar'] = array(
$service->token,
$service->authType
);
}
var_dump($_SESSION['tokens']);
?>
ここでは、取得したトークンはいったんPHPのセッションデータに保存しています。トークンは繰り返し利用可能なので、アプリケーションがサービスAPIに複数回のリクエストを行う予定なら、トークンをPHPのセッションデータに保存しておくことで、リクエストの都度トークンを取得せずに、保存してあるものを利用することができます。この場合、実際にAPIにリクエストを行う際には、トークンを取得したアカウント認証APIがClientLoginかAuthSubかによって送信内容が異なるので、トークンには、それを取得したアカウント認証APIの種類(このクラスではauthTypeプロパティ)も紐付けておきます。
また、トークンは各サービスAPIごとに異なるので、アプリケーションが複数のサービスを利用する場合は、上の例でハッシュのキーにサービス名を用いているように、それがどのサービス用のものかを識別できるようにしておきます(AuthSubでは、AuthSubTokenInfoによってトークンの対象サービスを確認することが可能です)。
AuthSub
AuthSubではトークンは、Googleアカウントのウェブサイトで表示されるアクセス要求の確認フォームで、ユーザが「アクセスを許可」をクリックすることで発行されます。
ユーザはまず、https://www.google.com/accounts/AuthSubRequestに、以下のパラメータをクエリー文字列に指定したURLにアクセスします(ウェブアプリケーションはユーザにこのURLを示して、アクセスの許可を依頼します)。
| キー | 値 |
|---|---|
| next | アクセスが許可された場合に行われるリダイレクト先のURL(AuthSubのレスポンスを処理するウェブアプリケーションのURL) |
| scope | 対象サービスのURL(Googleカレンダーの場合は「http://www.google.com/calendar/feeds/」) |
| session | 使い捨てトークンをセッショントークンと交換するか否か |
アクセス要求の確認フォームで、ユーザが「アクセスを許可」をクリックすると、AuthSubは「next」パラメータで指定されたURLに、「token」パラメータを付加してリダイレクトします。
この「token」パラメータの値は使い捨てトークン(one-time|single use token)です。これは一回限り有効で、繰り返し利用することはできませんが、上表にある「session」パラメータの値が「1」の場合、この使い捨てトークンは、繰り返し利用可能なセッショントークン(multi-use session token)と交換することができます。
使い捨てトークンをセッショントークンと交換するには、https://www.google.com/accounts/AuthSubSessionTokenに対して以下のようなリクエストを送信します。Authorizationヘッダで指定するtokenは使い捨てトークンの値です。
GET /accounts/AuthSubSessionToken HTTP/1.1 Authorization: AuthSub token="token"
リクエストが成功した場合のレスポンスはHTTP 200 OKで、そのボディは、以下のような「キー=値」形式のテキストです。このうち「Token」キーの値がセッショントークンです。他の値については、現時点では使用されていません。
Token=DQAA...7DCTN Expiration=20061004T123456Z
なお、Googleに登録済みのウェブアプリケーションはセキュアなトークンを利用可能ですが、これはここでは省略します。
クラスライブラリを使ったサンプルプログラム
ユーザが、以下の例で示されるリンクをクリックして表示されるアクセス要求の確認フォームで、「アクセスの許可」をクリックすると、http://www.abcd.com/gcal/auth.php?token=tokenというURLにリダイレクトが行われます。このURLの「token」パラメータの値は、カレンダーデータAPIを対象とした、セッショントークンと交換可能な使い捨てトークンです。
<p>以下のリンクをクリックしてGoogleアカウントのウェブサイトに移動し
お客様のGoogleカレンダーにABCD.comがアクセスすることを許可してください。<br />
ABCD.comがお客様のパスワードおよび個人情報を入手することはありません。</p>
<p><a href="<?php
require_once 'Google/Calendar.php';
echo Google_Calendar::getAuthSubRequestUrl('http://www.abcd.com/gcal/auth.php')
?>">Googleアカウント アクセス要求</a></p>
そして以下の例では、使い捨てトークン(「token」パラメータの値)をセッショントークンと交換しています。なお、取得したトークンはClientLoginでの例と同様に、PHPのセッションデータに保存しています。
<?php
require_once 'Google/Calendar.php';
$service = new Google_Calendar;
session_start();
if (isset($_GET['token']) and strlen($_GET['token']) > 0) {
if (!$service->requestAuthSubSessionToken($_GET['token'])) {
exit("AuthSubSessionToken has failed.\n".$service->getResponseBody());
}
if (!isset($_SESSION['tokens'])) {
$_SESSION['tokens'] = array();
}
$_SESSION['tokens']['calendar'] = array(
$service->token,
$service->authType
);
var_dump($_SESSION['tokens']);
}
?>
トークンの確認と廃棄
AuthSubの有効なトークンの発行数は、1ユーザ/1アプリケーションあたり10ヶまでに制限されています。そのため、取得済みの有効なトークンを廃棄(revoke)する必要が生じる場合があります。
https://www.google.com/accounts/AuthSubTokenInfoに対して以下のようなリクエストを送信することで、そのトークンが有効かどうかを確認できます。
GET /accounts/AuthSubTokenInfo HTTP/1.1 Authorization: AuthSub token="token"
指定したトークンが有効な場合のレスポンスはHTTP 200 OKで、そのボディは、以下のような「キー=値」形式のテキストです。
Target=www.abcd.com Scope=http://www.google.com/calendar/feeds/ Secure=false
有効なトークンを廃棄するには、https://www.google.com/accounts/AuthSubRevokeTokenに対して以下のようなリクエストを送信します。
GET /accounts/AuthSubRevokeToken HTTP/1.1 Authorization: AuthSub token="token"
リクエストが成功した場合のレスポンスはHTTP 200 OKです。
なお、ユーザはGoogleアカウントウェブサイトの「アカウント情報」ページで、現在有効なAuthSubトークンの確認と廃棄が行えます。また、AuthSubのアクセス要求時に、既に制限数を超えるトークンが発行されている場合は、その旨のメッセージが表示されます。
以下の画像は、制限数を超えるトークンが発行済みの場合のメッセージと、トークンの確認と廃棄の画面です。確認と廃棄の画面で「アクセスを取り消す」をクリックしたトークンは廃棄され、無効になります。
クラスライブラリを使ったサンプルプログラム
以下の例では、まずトークンが有効かどうかの確認を行い、有効な場合はそのトークンを廃棄しています。
<?php
$token = 'GD32CMCL25aZ-v____8B';
require_once 'Google/Calendar.php';
$service = new Google_Account;
if (!$service->requestAuthSubTokenInfo($token)) {
echo("Token $token is not valid.");
} else {
if (!$service->requestAuthSubRevokeToken($token)) {
exit("AuthSubRevokeToken has failed.\n".$service->getResponseBody());
}
echo("Token $token has been revoked and is no longer valid.");
}
?>
カレンダーデータの取得
GoogleカレンダーデータAPIとアプリケーションは、Atom 1.0(またはRSS 2.0)に準じた、GDataと呼ばれるフィードデータをHTTP通信でやり取りします。
Googleカレンダーのフィードは、http://www.google.com/calendar/feeds/User_ID/Visibility/Projection[/Entry_ID|?Query_String]という形式のURLにアクセスすることで取得しますが、イベントの追加、変更、削除を行うアプリケーションでは一般的に、http://www.google.com/calendar/feeds/default/private/fullに対して以下のようなリクエストを送信して、読み書きのいずれにも利用可能な、非公開予定を含むフィードを取得します。
GET /calendar/feeds/default/private/full[/Entry_ID|?Query_String] HTTP/1.1 Authorization: [GoogleLogin auth=ClientLogin_token|AuthSub token="AuthSub_token"]
- Authorizationヘッダの値は、トークンを取得した認証APIがClientLoginかAuthSubかで異なります。
- VisibilityやProjectionの詳細はUsing the Google Calendar Data APIの“Calendar feed types”を参照してください。
URLに以下の検索パラメータをクエリー文字列に指定することで、条件付きでフィードを取得できます。
なお、日時は、Atom 1.0が採用しているRFC3339形式で指定します。
| キー | 値 |
|---|---|
| q | 文字列の検索式(Googleのウェブ検索などと同様、「"」、「|」、「-」などのオペレータが使用可能です) |
| max-results | 最大取得件数(省略時:25件) |
| start-index | 取得開始エントリーの索引番号(省略時:1) |
| orderby | エントリーの並び順(省略時:更新日時順|starttime:開始日時順) |
| start-min | 最も古いイベントの開始日時(省略時:1970-01-01) |
| start-max | 最も新しいイベントの終了日時(省略時:2031-01-01) |
| updated-min | 最も古いエントリーの更新日時 |
| updated-max | 最も新しいエントリーの更新日時 |
| author | エントリーのauthor/name要素またはauthor/email要素(完全一致) |
| alt | フィード種別(省略時:Atom 1.0|rss:RSS 2.0) |
これらの検索パラメータのうち、「start-min」、「start-max」、「orderby」はカレンダーデータAPI特有のもので、それ以外はGData共通のものです。なお、カレンダーデータAPIは、GData共通の検索パラメータのうち、「category」はサポートしていません。
クラスライブラリを使ったサンプルプログラム
以下の例では、ClientLoginでトークンを取得した後、現在以降に開始予定のイベントエントリーのうち「横河」または「佐川」という文字列を含むものを、イベントの開始日時順に最大10件、という条件でフィードを取得しています。
<?php
$email = 'example@gmail.com';
$password = 'password';
require_once 'Google/Calendar.php';
$service = new Google_Calendar;
if (!$service->requestClientLogin($email, $password)) {
exit("ClientLogin has failed.\n".$service->getResponseBody());
}
$queries = array(
'q' => '横河|佐川',
'max-results' => 10,
'orderby' => 'starttime',
'start-min' => date('Y-m-d\TH:i:s+09:00', time())
);
if (!$service->requestFeed($queries)) {
exit("Requesting a feed has failed.\n".$service->getResponseBody());
}
header('Content-Type:application/xml;charset=UTF-8');
echo $service->getResponseBody();
?>
イベントの追加
イベントを追加するには、http://www.google.com/calendar/feeds/default/private/fullに対して以下のようなリクエストを送信します。
POST /calendar/feeds/default/private/full HTTP/1.1 Authorization: [GoogleLogin auth="ClientLogin_token"|AuthSub token="AuthSub_token"] Content-Type: application/atom+xml GData
GDataは、例えば以下のような、Atom 1.0に準じたフィードデータです。
<entry
xmlns="http://www.w3.org/2005/Atom"
xmlns:gd="http://schemas.google.com/g/2005">
<category
scheme="http://schemas.google.com/g/2005#kind"
term="http://schemas.google.com/g/2005#event">
</category>
<title type="text">横河武蔵野FC vs. 佐川急便東京SC</title>
<content type="text">最後の東京ダービー</content>
<gd:where valueString="横河電機グラウンド">
</gd:where>
<gd:when
startTime="2006-10-07T15:00:00+09:00"
endTime="2006-10-07T17:00:00+09:00">
</gd:when>
</entry>
イベントが「終日」の場合は、gd:when要素のstartTime/endTime属性値に日付のみを指定します。「繰り返し」のイベントの場合は、gd:recurrence要素を指定します。GData要素の詳細は、Common Elements: “Kinds”を参照してください。
GDataの文字エンコーディングはUTF-8です。日時は、Atom 1.0が採用しているRFC3339形式で指定します。
リクエストが成功した場合のレスポンスはHTTP 201 Createdで、そのボディは、送信したGDataにid要素やupdated要素などが追加されたフィードデータです。
クラスライブラリを使ったサンプルプログラム
以下の例では、ClientLoginでトークンを取得した後、イベントを追加しています。
<?php
$email = 'example@gmail.com';
$password = 'password';
$entry = <<<GDATA
<entry
xmlns="http://www.w3.org/2005/Atom"
xmlns:gd="http://schemas.google.com/g/2005">
<category
scheme="http://schemas.google.com/g/2005#kind"
term="http://schemas.google.com/g/2005#event">
</category>
<title type="text">横河武蔵野FC vs. 佐川急便東京SC</title>
<content type="text">最後の東京ダービー</content>
<gd:where valueString="横河電機グラウンド">
</gd:where>
<gd:when
startTime="2006-10-07T15:00:00+09:00"
endTime="2006-10-07T17:00:00+09:00">
</gd:when>
</entry>
GDATA;
require_once 'Google/Calendar.php';
$service = new Google_Calendar;
if (!$service->requestClientLogin($email, $password)) {
exit("ClientLogin has failed.\n".$service->getResponseBody());
}
if (!$service->insert($entry)) {
exit("Inserting an entry has failed.\n".$service->getResponseBody());
}
header('Content-Type:application/xml;charset=UTF-8');
echo $service->getResponseBody();
?>
イベントの変更と削除
イベントの変更及び削除は、そのイベントエントリーのlink要素中、rel属性値が「edit」のものの、href属性値に示されているURLに対してリクエストを送信します。
変更の場合は、以下のようにPUTメソッド(または、X-Http-Method-Overrideヘッダに「PUT」を指定したPOSTメソッド)を用いて、変更したGDataを送信します。
PUT Edit_URL HTTP/1.1 Authorization: [GoogleLogin auth="ClientLogin_token"|AuthSub token="AuthSub_token"] Content-Type: application/atom+xml GData
削除の場合は、以下のようにDELETEメソッド(またはX-Http-Method-Overrideヘッダに「DELET」を指定したPOSTメソッド)を用います。
DELETE Edit_URL HTTP/1.1 Authorization: [GoogleLogin auth="ClientLogin_token"|AuthSub token="AuthSub_token"]
いずれも、リクエストが成功した場合のレスポンスはHTTP 200 OKで、変更の場合は、そのボディは、送信したGDataが加工されたフィードデータです。
クラスライブラリを使ったサンプルプログラム
以下の例では、ClientLoginでトークンを取得した後、イベントの開始/終了日時を変更しています。
<?php
$email = 'example@gmail.com';
$password = 'password';
$edit_url = 'http://www.google.com/calendar/feeds/default/private/full/abcd/1234';
$entry = <<<GDATA
<entry
xmlns="http://www.w3.org/2005/Atom"
xmlns:gd="http://schemas.google.com/g/2005">
<category
scheme="http://schemas.google.com/g/2005#kind"
term="http://schemas.google.com/g/2005#event">
</category>
<gd:when
startTime="2006-10-07T14:00:00+09:00"
endTime="2006-10-07T18:00:00+09:00">
</gd:when>
</entry>
GDATA;
require_once 'Google/Calendar.php';
$service = new Google_Calendar;
if (!$service->requestClientLogin($email, $password)) {
exit("ClientLogin has failed.\n".$service->getResponseBody());
}
if (!$service->update($entry, $edit_url)) {
exit("Updating an entry has failed.\n".$service->getResponseBody());
}
header('Content-Type:application/xml;charset=UTF-8');
echo $service->getResponseBody();
?>
Some Tips
- GDataフィードの形式が、規定のAtom 1.0の場合、日時表現形式はRFC3339ですが、PHP5では、strtotime関数はタイムゾーン指定を含むRFC3339形式の日時表現に対応しており、また、新たに追加された定数などによって、date関数などでの日時表現の生成も容易です。一方、PHP4のstrtotime関数は、タイムゾーン指定を含むRFC3339形式の日時表現には対応していないので、これをUnixタイムスタンプに置き換える必要がある場合は、独自の処理を用意することになります。
- GDataフィードを取得するURLのクエリー文字列に「alt=rss」を追加すると、フィード形式が、規定のAtom 1.0からRSS 2.0に変更されます。RSS 2.0は比較的以前からある形式のため、フィード解析に既成のパーサを利用する場合に、選択肢が広がるかもしれません。また、RSS 2.0の日時表現形式はRFC822ですが、PHP4でもこの形式については、strtotime関数はタイムゾーン指定を含む日時表現に対応しており、また、date関数での日時表現の生成も、フォーマット文字列に「r」を指定するだけで行えます。ただし、RSS 2.0はフィードの取得時のみに利用できます。イベントの追加や変更はAtom 1.0を利用します。
Category: ウェブ制作
Posted 2006年10月04日 22:53
2006年08月17日
HTMLを整形式のXML文書に修正するPHPクラス
ガーロ解任記念(無関係)。夏休みの宿題(嘘)。
HTMLなどにありがちなズサンなマークアップを、整形式のXMLドキュメントに補正するPHP用のクラスライブラリです。
一般的なXHTML変換処理にみられる、タグ書式の修正や不適切に用いられている解析対象記号の置換などに加えて、DTD的構成ルールを用いて、欠落している要素の補完や、要素の親子関係の補正をある程度行なうことができます。構成ルールは任意に指定可能で、これにより例えば、HTMLソースから不要な要素や属性を除去したり、別の要素に置換したりといったことも行えます。
各種のプログラミング言語において様々に提供されているマークアップの補正機能は、PHPでは、PECL拡張モジュール版のTidyなどを利用できますが、残念ながらこれらは、現在の一般的なレンタルサーバのPHP環境では必ずしも用意されているわけではありません。このスクリプトベースのクラスライブラリは、このようなバイナリ拡張モジュールが利用できない環境で、マークアップの補正を行う際の補助となることを意図したものです。
てゆうか、まあこいつのために作ったんだけど。
このクラスライブラリは、Free Software FoundationによるGNU Lesser General Public License(LGPL)のバージョン2.1あるいはそれ以降のバージョンの規約に従いライセンスされます。
応用例
» HTMLをXML化してDOMやXPathで操作するWebスクレイピング用PHPクラス
仕様とか制限事項
- このクラスライブラリを利用するにはPEARのXML_HTMLSax3、及びバージョン4.3.0以降のPHPが必要です。また、XML_HTMLSax3が扱える文字エンコーディングはUTF-8のみなので、mbstringなどの文字エンコーディング変換機能が必要かもしれません。
- 要素の補完や親子関係の補正には限界があり、必ずしも望ましい結果が得られるとは限りません。
- XML宣言やDOCTYPE宣言、名前空間などの補正は行いません。
- コメントやCDATAセクション以外のマークアップ記号はすべて解析対象です。即ち、XMPやPLAINTEXT、そして子要素がコメントまたはCDATAセクションではないSCRIPTなどがパース対象のドキュメントに含まれる可能性がある場合は、事前の処理が必要かもしれません。
- 任意の構成ルールを指定できますが、省略はできません。リリースパッケージには、XHTML 1.0 TransitionalのDTDに基づいて作成した構成ルールのサンプルが付属しますが、HTML以外のマークアップに対して利用する場合は構成ルールを独自に用意する必要があります。
- パフォーマンスを考慮した結果、パース結果は構造体ではなく文字列に構築されます。そのため、例えばドキュメントツリーを操作するようなインタフェースはありません(ドキュメントツリーを操作する必要がある場合は、出力をDOMオブジェクトに読み込むなどしてください)。
リリース
» 1.2.1 (stable) released 2007/05/17
※バージョン1.1からは、それ以前のバージョンと異なり、HTML_Sax3クラスのオブジェクトを別途に作成する必要がなくなりました。
| ファイル名 | 概要 |
|---|---|
| HTMLParser.class.php | クラスライブラリ本体。 |
| xhtml1-transitional_dtd.inc.php | XHTML 1.0 TransitionalのDTDを基に作成した、サンプルの構成ルールを表す連想配列を返す外部PHPファイル。 |
| sample.php | HTMLを読み込み、補正結果を表示するサンプルアプリケーション。 ファイル中の、ターゲットのURIを指定している箇所を編集して、お好みのウェブページを表示してみてください。また、冒頭にあるふたつの変数を、output_xmlをTRUEに、output_xmlnsをFALSEにすると、Mozilla FirefoxなどではXMLドキュメントツリーを確認できると思います。 |
概要
このクラスライブラリは、SAXベースのXMLパーサである、PEARのXML_HTMLSax3用のイベントハンドラを定義したものです(従ってその利用にはXML_HTMLSax3が必要です)。XML_HTMLSax3は、PHPのネイティブXMLパーサと異なり、不適切なマークアップに対しても処理を継続します。XML_HTMLSax3は、一般的なSAXパーサと同様に、パース対象のドキュメント中に開始タグや終了タグ、キャラクターデータなどの要素を検出する都度、各要素に対応するハンドラを呼び出します。このクラスライブラリの各ハンドラメソッドは、XML_HTMLSax3から引き渡された各要素を、指定の構成ルールに従って文字列に構築していきます。
サンプルプログラム
以下のダメダメHTMLをパースする簡単なサンプルプログラムを見ていきます。
以下のHTMLはShift_JISエンコーディングで、sample.htmlという名称のファイルで存在しているものとします。
<META NAME=DESCRIPTION CONTENT=Foo&Bar> <H1> <DIV ALIGN=CENTER>Foo&Bar</DIV> </H1> <HR NOSHADE> </BODY> <P>Foo<BR>Bar <TABLE FOO=BAR> <TD>Foo&Bar</TR></TR></TR></TR> </TABLE> <LI>Foo <LI>Bar <FOO> <HTML>
まず、このHTMLを読み込み、UTF-8エンコーディングに変換しておきます(XML_HTMLSax3が扱える文字エンコーディングはUTF-8のみです)。
$source = file_get_contents('./sample.html');
mb_convert_variables('UTF-8', 'Shift_JIS', $source);
このクラスのオブジェクトを作成し、アーカイブに付属している、サンプルの構成ルールを表す連想配列を返す外部PHPファイル(xhtml1-transitional_dtd.inc.php)を指定します。このサンプルの構成ルールはXHTML 1.0 TransitionalのDTDを基に作成したものです。setRuleFileメソッドは外部ファイルを指定しますが、これに替えて、setRuleメソッドで配列を指定することもできます。
require_once('./HTMLParser.class.php');
$parser = new HTMLParser;
$parser->setRuleFile('./xhtml1-transitional_dtd.inc.php');
このクラスのオプションを指定します。
- 要素の親子関係の補正を行う際には、構成ルールに定義される、各タグの「既定の親(default_parent)」が参照される場合があります。例えば、サンプルの構成ルールでは、「meta」の項には「'default_parent' => 'head'」という記述があり、上のsample.htmlで欠落しているHEAD要素は、この定義に従い補完されます。HTMLでは、多くのタグについてこの「既定の親」は「body」ですが、これらのタグについて構成ルールに逐次「既定の親」を記述するのは効率が悪いので、「既定の親」が未定義のタグの、既定の「既定の親」を指定するのがsetGenericParentメソッドです。
- setRootメソッドで指定する値はドキュメントのルート要素(HTMLの場合は「html」)の指定であり、パース対象のドキュメントに(上のsample.htmlのように)ルート要素が欠落している場合に補完されるものです。
パーサから開始タグのハンドラに最初に渡されるタグ名(上のsample.htmlでは「meta」)がsetRootメソッドで指定した名前と合致しない場合は、ここで指定した値に基づく要素が補完され、ハンドラから渡された要素は、その子要素として評価されます(なお、属性値は評価対象ではありません。名前さえ合致していれば、その属性値に関わらずハンドラから渡された要素がそのまま利用されます)。
以下の指定により、上のsample.htmlのパース結果にはまず「<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">」というタグが補完され、次いでMETAが、その子要素として評価されます(当然METAはHTMLの直接の子要素ではないの
