[IM]MediaAccessクラスと新たな拡張点

INTER-Mediatorはデータベースの内容を取り出し、Webページに展開し、場合によっては書き直したデータをデータベースに書き戻します。この一連のDBを中心としたデータの流れがあるのですが、Webアプリケーションではこれだけではすべてはまかなえません。HTMLでページを作るときは写真などの画像を別のファイルで供給します。このHTML外に実データが存在するようなものを「メディア」と呼ぶことにします。

メディアにはいろいろな種類があります。主要なものはIMGタグ要素で表示する画像、OBJECTタグなどで表示するFlashのコンテンツやビデオなど、そしてリンク先で得られるものとなるでしょうか。また、それぞれ、サーバ上にスタティックにあるものや、データベースのオブジェクト型フィールドに存在する場合もあります。WebページからこれらにアクセスするためのものがMediaAccessクラスです。概ね、次のような用途に使用方法は分類できます。

  • サーバ上にある画像ファイルを参照する
  • FileMakerのオブジェクトフィールドを参照する
  • データ生成を指定したクラスにさせる、生成結果を返す

ここで、単なる画像は普通にHTMLを書けばいいじゃないかと思うかもしれませんが、MediaAccessクラスを使う理由は、認証やアクセス権の設定との連携が可能になっているところです。

サーバ上にある画像ファイルを参照する

スタティックな画像で、認証が絡まない場合は、普通にIMGタグを記述します。また、画像ファイル名やパスがデータベースにある場合でも、必ずしもMediaAccessクラスは必要ないかもしれません。たとえば、あるテーブルのfilepathフィールドにファイル名が記録されているのなら、このようなIMGタグで表示できるでしょう。#srcにより、この要素のSRC属性にフィールドのデータが追加されます。

<img src=”figs/” class=”IM[context@filepath@#src]” />

ページの内容を認証しなければ参照できないようにしたとき、やはりページに埋め込んだ画像なども認証を経由したいと考えます。Webサーバレベルでの認証の場合は、ある意味、認証がない場合と概ね同じことで可能ですが、INTER-Mediatorの認証機能を使った場合、SRC要素がスタティックな画像を参照していれば、もしかしたら、認証しなくても画像だけは見えてしまうかもしれません。そんなことをしても大した情報流出にならないとも言えるのですが、ガードしたいものはガードするのが基本ですし、認証しているのに一部は誰でも見えるのは正しい運用ではありません。

そこで、IM_Entry関数の2つ目の引数(つまりオプション引数)に、’media-root-dir’というキーで、サーバ上にあるメディアファイルのフォルダへのルートからの絶対パスを指定しておきます。たとえば、

‘media-root-dir’ => ‘/var/www/images’,

となっていたとします。あるページファイルで使われている定義ファイルのパスがcontext.phpだったとします。すると、次の部分URLが、メディアを返します。ここで背後では、MediaAccessクラスが使われており、このクラスがメディアに対するプロキシになっているとも言えます。

context.php?media=ch1/shot345.png

たとえば、IMGタグのSRC属性に上記のURLを記述すれば、media-root-dirと合成して、「/var/www/images/ch1/shot345.png」というファイルをアクセスし、その内容を取り出して、適切なMIMEタイプのヘッダとともに出力をします。

前記のURLにある画像ファイル名「shot345.png」がフィールドpicfileにあるような場合には、ページファイルの要素には以下のような記述ができます。media=は決められたキーワードです。

<img src=”context.php?media=ch1/” class=”IM[table@picfile@#src]” />

このとき、定義ファイルで認証が必要な設定になっていると、SRC属性のURLからの取得時にMediaAccessクラス内部で、認証の確認を行います。ここで、一般の認証時に使っているクレデンシャルをそのまま使うことが実はできません。一般の認証では、1つのアクセスごとに異なるチャレンジデータを使うことで、認証の乗っ取りをしにくくしています。しかし、そのためにメディア処理ではその仕組みが使えません。なぜなら、メディアへのアクセスは並列的にブラウザから行うからです。

そこで、メディアアクセス時の認証のためだけのクレデンシャルを生成させるようにしています。たとえば、直前のimgタグ要素の場合、tableという名前のコンテキストからの取得となりますが、そのコンテキスト定義(IM_Entry関数の第1引数)の’authentication’キー内部の’media-handling’キーの値をtrueにします。すると、このコンテキストのデータを取得するときに、サーバ側からメディア用のクレデンシャルを出力します。

IMGタグ要素などから実際にメディア取得を定義ファイルに対して行うとき、media=があれば、MediaAccessクラスに処理をまかせます。そのとき、クレデンシャルがクッキーに記録されてサーバ側に到達し、それを発行したクレデンシャルと比較することで認証が通っているかどうかを判定します。つまり、コンテキストが得られるということは認証が通っているわけで、その信頼関係をもとに秘密の合い言葉をやりとりします。このクレデンシャルは繰り返し使われる可能性があります。クッキーに記録し、時間が来れば消去するようにはなっているものの、クレデンシャルを盗まれるのはそれだけでメディアアクセスを可能にしてしまうことになります。従って、HTTPS(SSL)でのサーバ運用は必須とも言えるでしょう。

普通のHTMLでMediaAccessを経由させる

Webページを作って画像を埋め込むと、<img src=”img/cover.jpg” /> などと記述します。これをMediaAccessクラスを使ってデータの取り出しを行いたいとしたら、ソースを全部変更しないといけないのかというとそうではありません。リダイレクトを使うことで、HTMLソースはそのままに、MediaAccessクラスを使うことができます。たとえば、.htaccessファイルを作り、たとえば次のような記述を作ります。

RedirectMatch img/(.+) http://host.name/myapp/context.php?media=$1

すると、<img src=”img/cover.jpg” /> は、<img src=”http://host.name/myapp/context.php?media=cover.jpg” /> と同じことになるわけです。

部分パスと絶対パス、それらを消したり追加したりといろいろ複雑にはなりますが、このスタティックなメディアを認証した上で表示できるようにしたのがMediaAccessの最初のインプリメントでした。

(この内容、続く)

[IM]ドラッグ&ドロップでファイルアップロード

ファイルのドラッグ&ドロップによるアップロードをINTER-Mediatorに実装しました。動作条件を整える方法はドキュメントを改めて書きますが、ページファイル上は、

class=”IM[testtable@vc1] IM_WIDGET[im_fileupload]”

のように、IM_WIDGETで、利用するコンポーネントを書くだけで、以下のムービーのようなドラッグ&ドロップによるファイルのアップロードができるようになっています。

dragdrop

[IM]PHP Ver.5.3 on OS Xで、APCを稼働させる方法

ファイルのアップロードをするときのプログレスバーを出す方法が「A Simple PHP Upload Progress Bar」というページに紹介されています。シンプルなのでやりやすそうと思われるのか、このサイトのスクリプトを単にコピーしただけのサイトなんかもあります(せめて出展くらい出すべきでしょう)。

当初、動かし方を紹介したサイトはないかと思って探したのが「Mac OS XのPHP 5.3にAPC(Alternative PHP Cache)をインストールする方法」というサイトでした。OS X Lion時代のものなのかこの通りでは動かなかったので、追加で必要な作業をまとめてみました。

プログレスバーを出す仕組みはちょっとややこしいのですが、ポイントの1つはPHPのAPC(Alternative PHP Cache)という機能を利用することです。残念ながら、PHP 5.3では生の状態ではこの機能は使えません。この機能を、OS X Moutain Lion + OS X Server Ver.2.2 + FileMaker Server 12という状況で使えるようにする方法を解説します。PHPは、Ver.5.3.13です。FileMaker Serverでない場合php.iniファイルの扱いが違ってくると思われます。

  1. Webサーバ稼働マシンに、Xcodeをインストールしてください。Xcode 4.6.2で以下の動作は確認しています。
  2. MacPortsをインストールします(インストール済みならもちろん何もしなくてもOKです)。まず、以下のコマンドでダウンロードします。以下のURLはアップデートにより変更されるかもしれません。
    curl -O https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.8-MountainLion.pkg
  3. 以下のコマンドでインストーラを使ってMacPortsをインストールします。
    sudo installer -target / -pkg MacPorts-2.1.3-10.8-MountainLion.pkg
  4. 以下のコマンドで、autoconfiをインストールします。
    sudo port install autoconf
  5. 以下のコマンドで、pcreをインストールします。
    sudo port install pcre
  6. 以下のコマンドで、ヘッダファイルの1つをコンパイラが認識するディレクトリにコピーします(参考)。
    sudo cp /opt/local/include/pcre.h /usr/include
  7. APCのソースをダウンロードします。URLはアップデートによって変更があるかもしれません。
    curl -O http://pecl.php.net/get/APC-3.1.13.tgz
  8. アーカイブを展開します。
    tar zfvx APC-3.1.13.tgz
  9. カレントディレクトリに移動します。
    cd APC-3.1.13
  10. 以下のコマンドを入れます。
    phpize
  11. 次のように表示されます。warningがありますが、問題ない模様です。
    Configuring for:
    PHP Api Version: 20090626
    Zend Module Api No: 20090626
    Zend Extension Api No: 220090626
    configure.in:3: warning: prefer named diversions
    configure.in:3: warning: prefer named diversions
  12. おなじみの以下のコマンドでコンパイルします。
    make
    sudo make install
  13. 最後のコマンドで以下のようなメッセージが表示されます。1行目のパスをphp.iniファイルに記述するので、コピーしておくといいでしょう。
    Installing shared extensions: /usr/lib/php/extensions/no-debug-non-zts-20090626/
    Installing header files: /usr/include/php/
  14. php.iniファイルを変更します。以下のパスは、Mountain Lion + FMS12の場合です。使用する状況に合わせて正しいphp.iniファイルを編集します。もし、ない場合は、/etc/php.iniあたりに作成します。使用しているphp.iniファイルのパスを調べるには、phpinfo関数の出力を利用しましょう。
    sudo nano ‘/Library/FileMaker Server/Web Publishing/publishing-engine/php/mountain lion/lib/php.ini’
  15. php.iniファイルに以下の3行を追加します。これらの設定をいままで全く行っていないのなら、そのまま追加でかまいません。すでに設定がないかどうかは検索して確認しましょう。
    extension_dir=/usr/lib/php/extensions/no-debug-non-zts-20090626/
    extension=apc.so
    apc.rfc1867=on
  16. 以下のコマンドを入力して、Apacheに設定変更を適用させます。
    sudo apachectl graceful
  17. phpinfo関数の出力を見て、APCのカテゴリがあることと、apc.rfc1867の値が「On」になっていることを確認します。

ポイントとしては、APCのコンパイルのために、autoconf、pcreが必要である点です。また、APCの設定は既定値ではrfc1867はOffですので、設定ファイルで記述してオンにしておく必要があります。

なぜ、この記事のカテゴリにINTER-Mediatorがあるかというと、この仕組みをINTER-Mediatorに組み込んだからです。

スクリーンショット 2013-06-16 16.44.40