Recently in PHP Category

前回のエントリでmultipartのバウンダリ文字列を抜き取る処理を記述したけれど、
multipartを分解したいだけなら、Mail/mimeDecode.php の基本処理で事足りたようである...

<?php 
require_once('Mail/mimeDecode.php');

$_params['include_bodies'] = true;
$_params['decode_bodies'] = true;
$_params['decode_headers'] = true;
$_params['input'] = file_get_contents('php://stdin');
$_structure = Mail_mimeDecode::decode($_params);

foreach ($_structure->parts as $_part) {
    //$_part->body;
}

?>

この例では、foreachの中の

$_part->body;
で分解された個々のbodyを取得できる。
本来、multipartかどうかの処理や、その他の細かい処理が必要になるが、そこら辺はPHPプロ!の記事を参照されたい。

!!!!!multipartを分解するだけの処理を知りたい場合は、こちらを参照されたい。!!!!!

multipartのバウンダリ文字列がヘッダで渡ることを知らなくて、少しだけはまった。

本エントリでは、qmailが動いているサーバでメールを受信し、
/tmp/mail_sample.txtにバウンダリ文字列を出力するまでの過程を記述する。

qmailでは、$HOME/.qmailでメール本文を受けたときに起動するスクリプトを記述できる。
私の環境では、.qmailは次のようになっている。

$ cat ~/.qmail
| /usr/bin/php /tmp/sample_script.php

この例では、メールを受信したタイミングで/tmp/sample_script.php が起動する。

さて、/tmp/sample_script.php は次のようになっている。
(PEAR のMail_Mimeがインストールされていることを前提としている)

<?php
require_once('Mail/mimeDecode.php');

$_in = fopen("php://stdin", "r");
$_mail_text = '';
while($_line = fgets($_in)) {
    $_mail_text .= $_line;
}

$_decoder = & new Mail_mimeDecode( $_mail_text );
$_parts =$_decoder->getSendArray();
list( $_recipients, $_headers, $_body ) = $_parts;

$_ret = preg_match("/boundary=\"([0-9a-zA-Z_\-\+\=\.\:]+)\"/", $_headers['Content-Type'], $_matches);
if($_ret) {
    $_fp = fopen("/tmp/mail_sample.txt", "w");
    fwrite($_fp, $_matches[1]);
    fclose($_fp);
}
?>

ただ単純に、ヘッダからContent-Typeの列を取り出して、正規表現で抜き出すだけ。
本来なら、multipart/mixed かどうかも見るべきかと思うけれど、
multipart/mixed でない限りは"boundary"という文字列は存在しないはずなので、これでよしとしている。

なお、multipart/mixed の場合は、次のような感じの文字列を受け取れる。

multipart/mixed; boundary="-----=_NextPart_46196_50244_54292"

この場合、上記のスクリプトでは、

-----=_NextPart_46196_50244_54292

を取得できる。

PEARのLogパッケージを使用して、Firebugにログを出力する方法を次に示す。
元ネタは「cl.pocari.org - PEAR Log を使って Firebug にログを出力する」。

まず、Logパッケージをインストールする。

# pear install Log
WARNING: "pear/DB" is deprecated in favor of "pear/MDB2"
Did not download optional dependencies: pear/DB, pear/MDB2, use --alldeps to download automatically
pear/Log can optionally use package "pear/DB" (version >= 1.3)
pear/Log can optionally use package "pear/MDB2" (version >= 2.0.0RC1)
pear/Log can optionally use PHP extension "sqlite"
downloading Log-1.9.11.tgz ...
Starting to download Log-1.9.11.tgz (38,479 bytes)
..........done: 38,479 bytes
install ok: channel://pear.php.net/Log-1.9.11

あとはLogクラスのインスタンスを生成し、logメソッドを呼ぶだけ。
具体的なコードは次の通り。

<?php
require_once 'Log.php';

$log = &Log::singleton('firebug', '', 'PHP', array('buffering' => true), PEAR_LOG_DEBUG);

$log->log('デバッグレベル', PEAR_LOG_DEBUG);
$log->log('情報レベル', PEAR_LOG_INFO);$log->log('警告レベル', PEAR_LOG_WARNING);
$log->log('エラーレベル', PEAR_LOG_ERR);
$log->log('レベル??');
?>

これで、次のようにFirebugのエラーコンソールにメッセージが出力される。

php_firebug.png

Enjoy!

last.fm から自分の再生履歴を配列として取得するphpスクリプトのサンプルを以下に示す。


<?php

// --
// VERSION CHECK
// --
if( version_compare(phpversion(), '5.0', '<') ) {
    echo "本スクリプトはPHPのVersion5.0以降でのみ動作します\n";
    exit;
}

// --
// LOAD XML
// --
$_lastfmName = 'mahata';
$_targetUrl = "http://ws.audioscrobbler.com/1.0/user/{$_lastfmName}/recenttracks.xml";
$_xmlObj = simplexml_load_file($_targetUrl);

// --
// MAKE ARRAY
// --
$_playList = array();
foreach( $_xmlObj as $_xmlObj_ ) {
    $_tArray = array();
    $_tArray['artist']  = (string)$_xmlObj_->artist;
    $_tArray['name']    = (string)$_xmlObj_->name;
    $_tArray['album']   = (string)$_xmlObj_->album;
    $_tArray['date']    = date('Y/m/d H:i:s', (int)strtotime($_xmlObj_->date));

    $_playList[] = $_tArray;
}

// --
// DUMP ARRAY
// --
print_r( $_playList );

?>


ここで、$_lastfmNameに任意のIDを設定すればよい。
実行結果は次のようになる。


$ php playlist2array.php
Array
(
    [0] => Array
        (
            [artist] => Surface
            [name] => クセになりそうだ
            [album] => resurface
            [date] => 2007/10/03 14:42:00
        )

    [1] => Array
        (
            [artist] => Surface
            [name] => ハニカムハニ
            [album] => resurface
            [date] => 2007/10/03 14:37:00
        )

    [2] => Array
        (
            [artist] => Surface
            [name] => WAIT!
            [album] => resurface
            [date] => 2007/10/03 14:34:00
        )

    [3] => Array
        (
            [artist] => Surface
            [name] => Re:START
            [album] => Re:START
            [date] => 2007/10/03 14:30:00
        )

    [4] => Array
        (
            [artist] => Surface
            [name] => ちりつもたれつ
            [album] => resurface
            [date] => 2007/10/03 14:26:00
        )

    [5] => Array
        (
            [artist] => Surface
            [name] => ワクチン
            [album] =>
            [date] => 2007/10/03 14:20:00
        )

    [6] => Array
        (
            [artist] => Surface
            [name] => 夢の続きへ
            [album] =>
            [date] => 2007/10/03 14:15:00
        )

    [7] => Array
        (
            [artist] => LINDBERG
            [name] => Brand New Day
            [album] => XII
            [date] => 2007/10/03 14:09:00
        )

    [8] => Array
        (
            [artist] => LINDBERG
            [name] => アタシは磨けば光るダイアモンドなのに
            [album] => XII
            [date] => 2007/10/03 14:05:00
        )

    [9] => Array
        (
            [artist] => LINDBERG
            [name] => 自転車に初めて乗れた日
            [album] => XII
            [date] => 2007/10/03 13:59:00
        )

)

拡張子がphpのファイル(というか、phpコードが実行される環境)で、
かつphp.iniのshort_open_tagがOnになっていると、XHTMLのxml宣言でエラーが出る。
なぜかというと、インタプリタが<?xml から始まる文字列をphpコードとして解釈するからである。


通常、次のようなerror_logが出力される。


Parse error: parse error, unexpected T_STRING in *.php on line 1


php.ini のshort_open_tag をOffにするのが正しい解決方法だが、
php.ini を勝手に変更してはならないケースでは、次のような回避方法もある。


<?php echo '<?xml version="1.0" encoding="utf-8"?>'."\n" ?>


PHPの仕様に文句をこぼさずに生きていきたいものですね。

About this Archive

This page is a archive of recent entries in the PHP category.

parser is the previous category.

qmail is the next category.

Find recent content on the main index or look in the archives to find all content.