« 2007年02月 | トップページ | 2007年04月 »

・[2007年03月25日]PEAR::Mail_Mimeを使ってHTMLメールを送ってみよう
・[2007年03月24日]PEAR::Mailを使ってメールを送信してみよう
・[2007年03月19日]PEARを使ってディレクトリの中身を全削除する
・[2007年03月15日]Movable TypeでSitemaps(サイトマッププロトコル)を作ってみよう
・[2007年03月14日]MySQLの暗号化をやってみよう
・[2007年03月11日]住所を都道府県・市区郡・それ以下に分けてみよう
・[2007年03月10日]PHPでBasic認証のパスワードを作ってみよう
・[2007年03月09日]JavaScriptでGETを取得する
・[2007年03月04日]マイブーム
・[2007年03月04日]Yahoo! UIのイベントリスナー(addListener)を使ってみよう

2007年03月25日

PEAR::Mail_Mimeを使ってHTMLメールを送ってみよう

前回「PEAR::Mailを使ってメールを送信してみよう」でメールの送信について紹介しました。これだけでも結構助かるのですが、便利になると更に欲が出るもので「ファイルを添付したメールを送信できないか?」「HTMLメールを簡単に作れないか?」などを考えます。そんなときにPEAR::MailをサポートしてくれるPEAR::Mail_Mimeという便利な拡張機能があります。
PEAR::Mail_Mimeは添付メールやHTMLメールを簡単に実現できます。
今日はPEAR::Mail_Mimeを紹介します。

インストールについて知りたい方は、過去の記事をご参照ください。
レンタルサーバーでPEARを使う方法
WindowsでPEARを自動インストールしてみよう

今回はPEAR::Mailの拡張機能になりますのでPEAR::Mailの使い方を知ってることが前提です。
もし使い方を知らない方は前回のエントリー「PEAR::Mailを使ってメールを送信してみよう」をご参照ください。

まずは添付メールの紹介です。
テキストメールで「sample.php」「sample.jpg」「sample.xls」の3つのファイルを添付する場合、以下のように記述します。尚、赤色の部分は前回のエントリーからの追加・編集した部分です。

require_once("Mail.php");
require_once("Mail/mime.php");

$header['From'] = "ピヨヒコ<piyopiyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Subject'] = "メールのタイトル";

$html_param['head_charset'] = "ISO-2022-JP";
$html_param['text_encoding'] = "ISO-2022-JP";
$html_param['text_charset'] = "SJIS";

$mime = new Mail_mime();
$mime->setTxtBody("メール本文");
$mime->addAttachment("./sample.jpg", "image/jpeg");
$mime->addAttachment("./sample.php", "text/plain");
$mime->addAttachment("./sample.xls");

$body = $mime->get($html_param);
$header = $mime->headers($header);

$mail = Mail::factory("smtp");
$ret = $mail->send("to@s-memo.net", $header, $body);
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


まずはPEAR::MailとPEAR::Mail_Mimeをインクルードします。
PEAR::Mail_Mime自身はメールの送信は一切行いません。あくまでPEAR::Mailをサポートする為のクラスですので、PEAR::Mailも必ずインクルードします。
require_once("Mail.php");
require_once("Mail/mime.php");

次に文字コードを連想配列にセットします。head_charsetはメールヘッダの文字コード、text_encodingはメールの文字コード(テキストメール専用)、text_charsetは変換前の文字コードです。
文字化けが発生した場合、この部分を間違えている可能性が高いです。mb_convert_encodingなどで文字コードを変更する前に以下の連想配列を変えてみることをお勧めします。
$html_param['head_charset'] = "ISO-2022-JP";
$html_param['text_encoding'] = "ISO-2022-JP";
$html_param['text_charset'] = "SJIS";

次にPEAR::Mail_mimeを宣言して、メール本文をセットします。テキストメールを送信する場合、setTxtBodyメソッドを使用します。
$mime = new Mail_mime();
$mime->setTxtBody("メール本文");

いよいよ添付処理です。添付はAttachmentメソッドを使用します。
第1引数にファイルパス又はデータを直接書きます。第2引数にContent-Typeを指定します。
Content-Typeが不明な場合は、省略しても大丈夫でした。でも、出来る限り指定してあげたほうがよさそうです。
$mime->addAttachment("./sample.jpg", "image/jpeg");
$mime->addAttachment("./sample.php", "text/plain");
$mime->addAttachment("./sample.xls");

getメソッドでメール用に変換したデータを$body変数に格納しています。
ヘッダ情報もheadersメソッドで変換したデータを$header変数に格納しています。
$body = $mime->get($html_param);
$header = $mime->headers($header);

$body変数はそのままメール本文で使用して、$header変数もそのままメールヘッダとしてPEAR::Mailにセットしてメールを送信します。
$mail = Mail::factory("smtp");
$ret = $mail->send("to@s-memo.net", $header, $body);

これでスクリプトを起動させると添付メールが届くと思います。

次はHTMLメールを作って見ます。HTMLメールには
・画像ファイルはサーバーに設置して、パスをhttpから記述する方法
・画像ファイルを添付してパスを相対パスで記述する方法
の2種類あります。
PEAR::Mail_Mimeを使うと両方とも実現できます。まずは、HTTPから記述する方法を紹介します。
「http://www.s-memo.net/img/sample.jpg」に画像があると過程します。

require_once("Mail.php");
require_once("Mail/mime.php");

$header['From'] = "ピヨヒコ<piyopiyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Subject'] = "メールのタイトル";

$html_param['head_charset'] = "ISO-2022-JP";
$html_param['html_encoding'] = "ISO-2022-JP";
$html_param['html_charset'] = "SJIS";

$html = <<<HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<title>HTMLメール送信テスト</title>
</head>
<body>
<font color="#0000FF">HTMLメールのテストです</font><br>
<img src="http://www.s-memo.net/img/sample.jpg">
</body>
</html>
HTML;

$mime = new Mail_mime();
$mime->setHTMLBody($html);

$body = $mime->get($html_param);
$header = $mime->headers($header);

$mail = Mail::factory("smtp");
$ret = $mail->send("to@s-memo.net", $header, $body);
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


text_encodingとtext_charsetはテキストメール用ですが、HTMLメールの場合はhtml_encodingとhtml_charsetを使用します。
・テキストメールの場合
$html_param['head_charset'] = "ISO-2022-JP";
$html_param['text_encoding'] = "ISO-2022-JP";
$html_param['text_charset'] = "SJIS";

・HTMLメールの場合
$html_param['head_charset'] = "ISO-2022-JP";
$html_param['html_encoding'] = "ISO-2022-JP";
$html_param['html_charset'] = "SJIS";

次に$html変数にHTMLを挿入して、setHTMLBodyメソッドにセットします。
$mime->setTxtBody($html);

後は先ほどを全く同じです。これでHTMLメールが送信できると思います。

最後に画像ファイルを添付してパスを相対パスで記述する方法を紹介します。

require_once("Mail.php");
require_once("Mail/mime.php");

$header['From'] = "ピヨヒコ<piyopiyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Subject'] = "メールのタイトル";

$html_param['head_charset'] = "ISO-2022-JP";
$html_param['html_encoding'] = "ISO-2022-JP";
$html_param['html_charset'] = "SJIS";

$html = <<<HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<title>HTMLメール送信テスト</title>
</head>
<body>
<font color="#0000FF">HTMLメールのテストです</font><br>
<img src="./sample.jpg">
</body>
</html>
HTML;

$mime = new Mail_mime();
$mime->setTxtBody($html);
$mime->addHTMLImage("./sample.jpg", "image/jpeg");

$body = $mime->get($html_param);
$header = $mime->headers($header);

$mail = Mail::factory("smtp");
$ret = $mail->send("to@s-memo.net", $header, $body);
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


imgタグのsrc属性を相対パスに変更します。
<img src="./sample.jpg">

画像をHTMLメールに埋め込みたい場合には、addHTMLImageメソッドを使います。
第1引数には画像パス、第2引数にはContent-Typeを指定します。
$mime->addHTMLImage("./sample.jpg", "image/jpeg");

これで画像付のHTMLメールが送信できます。
画像を添付で送りたい場合はaddAttachmentメソッドを使って、画像をHTMLメールに埋め込みたい場合はaddHTMLImageメソッドを使います。状況によって使い分けてください。

2回に分けてメールに関するPEARを紹介してきましたがいかがだったでしょうか。
私はPEAR::Mailに切り替えてからメール関係で文字化けに悩むことが大分減りました。
メール関係だけでもまだまだ別のライブラリがありますので、機会があれば紹介したいなと思います。

[関連記事]
PEAR::Mailを使ってメールを送信してみよう

| | コメント (0) | トラックバック (0)

2007年03月24日

PEAR::Mailを使ってメールを送信してみよう

PHPにはmb_send_mail()関数という日本語を含めたメールを送信する機能がありますがよく文字化けします。PHPの自動エンコーディング機能がうまくいかずに文字化けをするのですが、設定がシビアなので使ってません。例えば、同じサーバーを使っている場合は制作時に気をつければ問題ありませんが、サーバーを移行するようなことがあると新しいサーバーでメールが文字化けしたり結構大変だったりします。
結局send()関数を使うのですが、これで日本語のメールを送信する為には追加メールヘッダを記述する必要があります。mb_send_mail()関数よりはマシですが、これもこれで設定に左右されるので意外と大変。メール送信用の自作関数を作ったものの完璧ではありませんでした。
最終的に落ち着いたのは、PEARのMailです。記述がシンプルな上に自由に設定できて便利。
ということで今回はPEAR::Mailを紹介します。

インストールについて知りたい方は、過去の記事をご参照ください。
レンタルサーバーでPEARを使う方法
WindowsでPEARを自動インストールしてみよう

まずは、基本から以下のソースを見てください。

require_once("Mail.php");

$header['From'] = "piyo@s-memo.net";

$mail = Mail::factory("sendmail");
$ret = $mail->send("to@s-memo.net", $header, "メール本文");
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


これはタイトルも宛先も空白の必須項目のみを記述したサンプルです。
PEAR::Mailで、必要なのは「From(送信者)」「To(送信先)」「メール本文」の3つです。

1行目はいつも通りMail.phpをインクルードしています。

require_once("Mail.php");

3行目では「From(送信者)」を配列にセットしています。
$header['From'] = "piyo@s-memo.net";

5行目でMail::factory()メーラインスタンスを作成しています。
$mail = Mail::factory("sendmail");

7行目でメールを送信しています。第2引数に3行目で作ったFromをセットしている配列を指定しています。
$ret = $mail->send("to@s-memo.net", $header, "メール本文");

8~10行目はメール送信に失敗した場合に、エラーメッセージを表示させます。
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}

メールを受信してみると分かるのですが、宛先も件名も空っぽになっています^^;
これだけだと使い道がないので、もう少し実用的なものを作ってみます。
先ほどのスクリプトに赤の部分を追加・修正してください。(メールアドレスは適当に変えてください)

require_once("Mail.php");

$header['From'] = "ピヨヒコ<piyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Cc'] = "Cc様<cc@s-memo.net>";
$header['Bcc'] = "Bcc様<bcc@s-memo.net>";
$header['Reply-To'] = "piyopiyo@s-memo.net";
$header['Subject'] = "メールのタイトル";

$address = array("to@s-memo.net", "cc@s-memo.net", "bcc@s-memo.net");

$mail = Mail::factory("sendmail");
$ret = $mail->send($address, $header, "メール本文");
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


$headerの連想配列を追加しました。この連想配列にメールアドレスをセットしても指定のアドレスにはメールは送信されません。この配列はメールを受信した時に表示されるテキストです。(上記の例だとメールを受信した時に送信者に「ピヨヒコ」、宛先に「To様」、Ccに「Cc様」と表示されます)
メールを送信先はsend()メソッドで指定します。最初の例のように直接記述することもできますが、複数のアドレスに送信する場合、配列又はカンマ区切りで指定します。
以下のように配列を作って、
$address = array("to@s-memo.net", "cc@s-memo.net", "bcc@s-memo.net");

send()メソッドから複数アドレスに送信します。
$mail->send($address, $header, "メール本文");

[ちょっと余談]
以下の「Reply-To」というのはメールの返信先です。
$header['Reply-To'] = "piyopiyo@s-memo.net";

Fromは「piyo@s-memo.net」ですが、メーラーから返信をすると宛先に「piyopiyo@s-memo.net」が指定されます。Fromと返信先を変えたい時に使いましょう。

最後にSMTPからメールを送信してみましょう。
SMTPを使用すれば外部のメールアドレスからメールを送信することができます。
先ほどのスクリプトを修正します。赤の部分を追加・修正してください。

require_once("Mail.php");

$param['host'] = "smtp.s-memo.net";
$param['port'] = 25;
$param['auth'] = TRUE;
$param['username'] = "piyohiko";
$param['password'] = "password";

$header['From'] = "ピヨヒコ<piyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Cc'] = "Cc様<cc@s-memo.net>";
$header['Bcc'] = "Bcc様<bcc@s-memo.net>";
$header['Reply-To'] = "piyopiyo@s-memo.net";
$header['Subject'] = "メールのタイトル";

$address = array("to@s-memo.net", "cc@s-memo.net", "bcc@s-memo.net");

$mail = Mail::factory("smtp", $param);
$ret = $mail->send($address, $header, "メール本文");
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


ホスト名やポート番号等を連想配列を追加しています。
$param['host'] = "smtp.s-memo.net";
$param['port'] = 25;
$param['auth'] = TRUE;
$param['username'] = "piyohiko";
$param['password'] = "password";

「auth」はSMTP認証を使用するかどうかを指定します。TRUEでSMTP認証を使用し、FALSEでSMTP認証を使用しません。
ユーザ名やパスワードはSMTP認証に使用するユーザ名とパスワードを挿入します。

次に制作した連想配列を以下にセットします。

$mail = Mail::factory("smtp", $param);

後はsend()メソッドでメールを送信すれば完了です。
SMTPは外部サーバーのメールを使用できますが、ポートを開いてもらう必要がありますのでご注意ください。
予想以上に長くなりましたが今日はここまで。
と思いましたが、せっかくなのでMailクラスのリファレンスも残しておきます。

Mailクラスのfactoryメソッドのリァレンスは以下の通り

factory($backend, [, $param]);
$backend:「mail」「smtp」「sendmail」のいずれか
$param:パラメータの連想配列(FromやToなど)以下を参照

factoryメソッドの第2引数のパラメータは以下の通り
[「sendmail」の場合]
$p['sendmail_path']:sendmailへのファイルパス /usr/bin/sendmail等
$p['sendmail_args']:sendmailに渡す追加パラメータ
[「smtp」の場合]
$p['host']:SMTPを利用するドメイン又はIP名(デフォルト:localhost)
$p['port']:接続ポート番号(デフォルト:25)
$p['auth']:SMTP認証を使用するかどうか(デフォルト:FALSE)
$p['username'}:SMTP認証のユーザ名
$p['password'}:SMTP認証のパスワード

Mailクラスのsendメソッドのリファレンスは以下の通り

send($address, $header, $msg);
$address:メールアドレス(複数送信は配列又はカンマ区切り)
$header:追加ヘッダの連想配列。詳細は以下を参照
$msg:メール本文

sendメソッドの第2引数のパラメータは以下の通り
$h['From']:送信者
$h['To']:送信先(To)
$h['Cc']:送信先(Cc)
$h['Bcc']:送信先(Bcc)
$h['Reply-To']:メールの返信先
$h['Subject']:メールタイトル

send()メソッドの第2引数に「To」や「Cc」を追加しても実際には送信されません。これはメール受信者の表示用の為の記述です。
実際に送信したい場合は、第1引数に同じアドレスを記述してください。

[関連記事]
PEAR::Mail_Mimeを使ってHTMLメールを送ってみよう

【雑談】
やっと昼型に戻りました!まあ、いつまでもつか分かりませんが、、、^^;

| | コメント (5) | トラックバック (0)

2007年03月19日

PEARを使ってディレクトリの中身を全削除する

先週の木・金曜日あたりからずっと貧血気味で調子が悪く、夜型の生活が影響しているのかと思っていたのですがそれだけではありませんでした。原因は野菜不足。。。
最近は自炊する時間もなく外食が多かったのですが、肉ばっかり食べてたもんだから体調を崩したようです^^;当たり前だけど野菜はちゃんと食べよう。
さて、そろそろ本題に移ります。
PHPには「rmdir」というディレクトリを削除する関数がありますが、「空ディレクトリ」のみしか削除できずディレクトリ内にファイルが存在した場合、削除することができません。
PHPの標準機能だけを使った場合、再帰処理を使って全てのファイルを「unlink」で削除した後に「rmdir」を実行する必要があります。
今回はPEAR::Systemを使ってディレクトリを完全削除する簡単な方法を紹介します。

今回の「PEAR::System」はPEARの標準機能です。
インストールについて知りたい方は、過去の記事をご参照ください。
レンタルサーバーでPEARを使う方法
WindowsでPEARを自動インストールしてみよう

では早速作ってみましょう。
以下の構成だと仮定します。

[home]
 └─[ sample]
 └─rm.php

rm.phpは削除用のPHPファイル、sampleディレクトリは削除するディレクトリです。

rm.phpに削除用のスクリプトを記述します。

require_once("System.php");
System::rm("-r sample");
これだけです^^;問題なく削除できた場合はTRUE、削除に失敗した場合はFALSEが返ってきます。
ディレクトリ内にファイルがあっても再帰処理で全部削除してくれます。

HTTPからrm.phpにアクセスすれば、sampleディレクトリ及びディレクトリ内の全てのファイルを削除してくれます。
当然ですが、権限のないファイル・ディレクトリは削除はできません。
もし、権限のないファイルと権限のあるファイルが混ざっていた場合、権限ありのみのファイルが削除されて戻り値はFALSEが返ってきます。
権限のないファイルを削除したい場合は、属性を「777」にすれば削除できます。

require_once("System.php");
if(System::rm("-r sample")) {
  echo "削除が成功しました";
} else {
  echo "削除に失敗しました";
}

ちなみに

System::rm("samle.txt");

と記述すると、指定のファイルを削除してくれます。

ローカル上でテストしてみたのですが、500MBの容量(ファイル数:約30,000)でも問題なく削除できました。処理には約10~15秒かかりましたが、、、
一時保存ディレクトリを作った場合、削除処理がうまくいかずに困ることがありましたが、これからは大丈夫そうです。

| | コメント (0) | トラックバック (0)

2007年03月15日

Movable TypeでSitemaps(サイトマッププロトコル)を作ってみよう

このブログは気が向いたときに書いているのですが、現時点で今月は過去最高のエントリー数になってます。このまま1週間に2,3回は書いていけたらいいなと思ってます。質が落ちてる気がしないでもないのですが、、、
何故、更新頻度が上がったかと言うとアクセスが増えて更新が楽しくなってきたことと、更にアクセス数を「もっと増やしたいなぁ」っと考えたときに更新頻度を上げるのがベストだと思ったからです^^;
とは言っても本腰でアクセス数を増やすならもっと情報をPEAR、Ajax等に絞ったほうが良さそうですが、「勉強したことをメモ程度に記録する」というこのサイトの本質から外れるのでしばらくはこのまま行きます。

さてそろそろ本題に入ります。以前に「GoogleのSitemaps(サイトマッププロトコル)」の制作方法を紹介しましたが、今回はMovable Typeのテンプレートに記述する方法を紹介します。これを使えば、サイトを更新するたびに自動でSitemapsを作ってくれます。

Movable Typeにログインをして、「テンプレート」→「インデックス」→「テンプレートの新規作成」をクリックします。
テンプレートの新規登録ページに移動しますので「テンプレート名」には「Google Sitemaps」など自由に名前をつけます。続いて「出力ファイル名」には「sitemap.xml」と入力します。
後は「再構築オプション」の「インデックス・テンプレートを再構築するときに、このテンプレートを自動的に再構築する」にチェックを入れます。

「テンプレートの内容」にサイトマッププロトコルを記述していきます。
まずはお決まり通りXMLの宣言とurlsetタグを記述します。

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">

</urlset>


urlsetタグの中にトップページやエントリーのURLを記述していきます。
トップページの記述は以下のように記述します。
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
  <url>
    <loc><$MTBlogURL encode_xml="1"$></loc>
    <changefreq>monthly</changefreq>
    <priority>1.0</priority>
  </url>

</urlset>

「$MTBlogURL」にはその名の通り、ブログのトップページURLが呼び出されます。

更にその下に各エントリーのURLと最終更新日を記述します。

<MTEntries lastn="9999">
<url>
  <loc><$MTEntryPermalink encode_xml="1"$></loc>
  <lastmod><$MTEntryModifiedDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></lastmod>
</url>
</MTEntries>

「MTEntries」はエントリーを挿入する際に使用します。
「MTEntries lasten="9999"」は最初のエントリーから9999個のエントリーを順番に呼び出しなさいという指示になります。エントリーが9999個以下の場合は、全てのエントリーが呼び出された時点で終了します。尚、「lasten="9999"」を入れなかった場合、最新の一部のエントリーしか表示されませんのでご注意ください。
「$MTEntryPermalink」はURLを、「$MTEntryModifiedDate」は最終更新日を呼び出しています。

次にエントリーの下にカテゴリを入れます。

<MTCategories>
<url>
  <loc><$MTCategoryArchiveLink encode_xml="1"$></loc>
  <lastmod><$MTDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></lastmod>
</url>
</MTCategories>

「MTCategories」は各カテゴリを順次呼び出します。
「$MTCategoryArchiveLink」はURLを、「$MTDate」は構築日を呼び出しています。構築日よりも「カテゴリ内の最新エントリーデータの更新日」がセットできればベストだと思ったのですが、リファレンスを見ても都合の良いのがありませんでした^^;

カテゴリの下に月別(アーカイブ)のリンクを記述します。

<MTArchiveList archive_type="Monthly">
<url>
  <loc><$MTArchiveLink encode_xml="1"$></loc>
  <lastmod><$MTArchiveDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></lastmod>
</url>
</MTArchiveList>

「MTArchiveList」 type="Monthly"」で月別(アーカイブ)を順番に呼び出します。
「$MTArchiveLink」でURLを、「$MTArchiveDate」でその月の1日の日付が呼び出されます。「$MTArchiveDate」を「$MTArchiveDateEnd」に書き換えてもいいかもしれませんが、最新月のデータの更新日に未来の日付が入るので辞めたほうが無難かと思います。

最終的には以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
  <url>
    <loc><$MTBlogURL encode_xml="1"$></loc>
    <changefreq>monthly</changefreq>
    <priority>1.0</priority>
  </url>

  <MTEntries lastn="9999">
  <url>
    <loc><$MTEntryPermalink encode_xml="1"$></loc>
    <lastmod><$MTEntryModifiedDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></lastmod>
  </url>
  </MTEntries>

  <MTCategories>
  <url>
    <loc><$MTCategoryArchiveLink encode_xml="1"$></loc>
    <lastmod><$MTDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></lastmod>
  </url>
  </MTCategories>

  <MTArchiveList archive_type="Monthly">
  <url>
    <loc><$MTArchiveLink encode_xml="1"$></loc>
    <lastmod><$MTArchiveDate utc="1" format="%Y-%m-%dT%H:%M:%SZ"$></lastmod>
  </url>
  </MTArchiveList>
</urlset>

URLはバッティングしないので問題ないとは思いますが、上記のテンプレートを使うことで検索エンジンの順位が下がったりインデックスが削除されても本サイトでは責任を負えませんので予めご了承ください。

・関連記事
GoogleのSitemaps(サイトマッププロトコル)を作ろう

| | コメント (0) | トラックバック (0)

2007年03月14日

MySQLの暗号化をやってみよう

ここ2週間ぐらい昼と夜が逆転してます。今も夜勤(?)中です。
私の場合、なぜか昼より夜のほうが調子が良いのです。今に始まったことではなく一番古い記憶だと小学校5年生のときには夜型人間だと自覚していて、昔働いていた工場でも夜勤が楽しみで仕方なかった。なぜだろう?
そんな私に友人から一言「確実に体は蝕まれているので気をつけろ」と^^;
はい。気をつけます。。。
全く関係のない話から入りましたが、そろそろ本題に入ります。
今日はMySQLの暗号化を紹介します。

MySQLのPASSWORD関数は非推奨の為、出来る限り使用されないようにお願いします。
(2008.06.12 追加)


MySQLでパスワードを認証を行う場合、PASSWORD関数を使用します。
下記のように簡単なテーブルを作成してます。

CREATE TABLE users_table(
  account TEXT NOT NULL,
  pass_word TEXT NOT NULL
);

INSERTのときに「pass_word」フィールドを「PASSWORD」関数を使ってINSERTします。
INSERT INTO users_table (account, pass_word)
values("staff", PASSWORD('pass'));

認証は以下のように行います。
SELECT * FROM users_table
WHERE account='staff' AND pass_word=PASSWORD('pass');

PASSWORD関数は復元できないため、暗号化したパスワードを参照することはできません。
[PASSWORD関数の注意点]
MySQL4.0以前とMySQL4.1以降では仕様が変わっています。
MySQL4.0以前からMySQL4.1以降にアップグレードすると認証が使えなく可能性があります。
詳細はMySQLのリファレンスをご参照ください。

暗号化・復元の両方を行いたい場合はAES_ENCRYPT関数とAES_DECRYPT関数を使用します。
AES_ENCRYPT関数で暗号化をして、AES_DECRYPT関数で復元をします。
暗号化は以下のように行います。

INSERT INTO users_table (str)
values(AES_ENCRYPT('暗号化する文字列', 'password'));

復元は以下の通りです。
SELECT FROM AES_DECRYPT(str, 'password') FROM users_table

各関数の仕様は以下の通りです。
AES_ENCRYPT(str, key)
str:暗号化する文字列
key:暗号化用のパスワード
AES_DECRYPT(str, key)
str:復元するフィールド名
key:暗号化用のパスワード


| | コメント (2) | トラックバック (0)

2007年03月11日

住所を都道府県・市区郡・それ以下に分けてみよう

1年程前に「CSVデータをデータベースに一括登録する」をやりました。
その時のお客さんの要望の中に「都道府県」「市区郡」それぞれで検索ができるようにしたいというのがあったのですが、元データが「○○県○○市○○1-2-3」と1つになっていました。
そのままデータベースの中に入れても「都道府県」「市区郡」別に検索することはできそうだったのですが、ほぼ間違いなく動作が重くなるのでデータを分けて登録することにしました。
で、その時に作った関数が以下の通り。
後ほど詳しく書きますがこの関数は完璧ではありません。
また、文字コードはSJISのみです。

/***
* 住所を都道府県 市区郡 以下住所の3つに分ける
* SJIS用
*/
function prefCityAddressSplit($value) {
  $ret = array();
  $search = "^([\x81\x3F-\xFF\xFF]{2,3}[\x93\x73|\x93\xB9|\x95\x7B|\x8C\xA7]{1})"; // 都道府県
  $search .= "([\x81\x3F-\xFF\xFF]+[\x8B\xE6|\x8E\x73|\x8C\x53]{1})"; // 市区郡
  $search .= "([\x81\x3F-\xFF\xFF|0-9a-zA-Z\-]*)"; // それ以下
  if(mb_ereg($search, $value, $string)) {
    $ret['pref'] = $string[1]; // 都道府県
    $ret['city'] = $string[2]; // 市区郡
    $ret['address'] = $string[3];
  }
  if(count($ret) < 3) return $value;
  return $ret;
}

「○○県○○市○○町1-2-3」をprefCityAddressSplit()の中に入れると配列で返してくれます。
住所以外のデータを入れると文字列がそのまま返ってきます。
$address = "○○県○○市○○町1-2-3";
prefCityAddressSplit($address);
array(3) {
  ["pref"]=>
  string(6) "○○県"
  ["city"]=>
  string(6) "○○市"
  ["address"]=>
  string(11) "○○町1-2-3"
}

データの内容が首都圏内だけのデータでしたのでその時は問題なかったのですが、改めて見てみるとバグ発見。。。
「宮崎県都城市○○○1-2-3」で上記の関数を使うと「宮崎県」ではなく「宮崎県都」「城市」「○○○1-2-3」となります^^;
せっかくなので、Blogに掲載することにしたのですが、この問題を発見し格闘すること数時間、まだ解決できません。
うーむ、正規表現は便利だけど難しいなぁ。

| | コメント (0) | トラックバック (0)

2007年03月10日

PHPでBasic認証のパスワードを作ってみよう

認証と言えば、Basic認証。
.htaccessと.htpasswdを設置するだけで認証をかけられる手軽さが最大のメリットです。
多分、この記事を見てる方も使ったことのない方はいないのではないでしょうか?
セキュリティは高くないものの「関係者以外に見られても構わないけどURL叩くだけで表示されるのはちょっと。。。」という場合に多く使用します。
今はレンタルサーバーで管理画面などから設置できることがほとんどですが、管理画面から設置できなかったり設置数に制限があったりすることもあります。
そこで自分で作って設置するのですが、Basic認証(.htaccess)を設置するには.htaccessにパスワードの設置場所をサーバのルートパスから位置を記述したり、パスワードを自分で作る必要があります。
今回はそんなときに役立つPHPの関数を紹介します。

[追記 2007/03/11]
Basic認証作成プログラムを作りました。htaccessを丸ごと作ったりパスワードだけを作ったりするBasic認証作成の支援プログラムです。ご自由にお使いください。
Basic認証作成プログラム

まずは本題のPHPでパスワードを作る方法です。
Basic認証のパスワードは以下のような記述になります。

staff:mlAVmSW3gMmpk

「:(コロン)」でアカウントとパスワードが分かれています。
この場合は「staff」がアカウントになります。
パスワードの作り方は非常に簡単でcrypt()関数を使うだけです。
以下のスクリプトを記述してブラウザでプレビューすれば暗号化してくれます。
echo crypt("password", 'mc');

crypt関数のリファレンスは以下の通り
string crypt ( string str, string [salt] )
crypt("暗号化する文字列", "任意の2文字");

saltを指定しなかった場合、デフォルトではMD5で暗号化を行います。Basic認証のパスワードはDES暗号なので第二引数には半角英数記号で2文字記述します。
echo crypt("password", '1a');

と記述しても
echo crypt("password", 'zr');

と記述してもどちらでも認証可能です。
で、生成した文字列をコピーして「アカウント:パスワード」と記述すればBasic認証のパスワードが簡単に作れます。

次はサーバパスの調査方法です。
以下のようにphpinfo()を設置してブラウザで表示します。
phpinfo()の中に「DOCUMENT_ROOT」という部分があるのですが、それがドキュメントルートのサーバパスになります。

phpinfo();

phpinfo()が使えなかったりphpinfo()の中にパスを確認できなかった場合、以下のスクリプトで確認する方法もあります。
echo $_SERVER['DOCUMENT_ROOT'];
echo __FILE__; // 現在のファイルのパス

ドキュメントルートが「/home/www」でパスワードのファイル名が「.htpasswd」で「site」ディレクトリに認証をかけたい場合、.htaccessには「/home/www/site/.htpasswd」と記述します。

最後に、Basic認証の設置方法を簡単に紹介します。
最初に「.htaccess」というファイルを作ります。Windowsの場合、「.(ドット)」から始まるファイルは作れませんので、「htaccess.txt」など別の名前を仮に付けておきます。
「.htaccess」をテキストエディタで開いて

AuthUserFile /home/www/site/.htpasswd
AuthGroupFile /dev/null
AuthName "STAFF PAGE"
AuthType Basic
require valid-user

赤テキスト部分以外は毎回固定です。
/home/www/site/.htpasswdの部分にはパスワードを設置するファイルパスを記述します。(サイトのドキュメントルートからのパスではなく、サーバのパスですのでご注意ください)
STAFF PAGEの部分には認証の際にダイアログに表示されるテキストを記述します。日本語でも大丈夫ですが、文字化けの可能性が高いので使わないほうがいいでしょう。
今回は「/home/www/site」ディレクトリの中の「.htpasswd」ファイルにパスワードが設置されていると仮定しています。
次に「.htpasswd」を作ります。「.htaccess」と同じようにWindowsでは「.(ドット)」から始まるファイルは作れませんので、「htpasswd.txt」など別の名前を仮に付けておきます。
staff:mlAVmSW3gMmpk

アカウントを複数作る場合は以下のように1行につき1アカウント作ります。
staff:mlAVmSW3gMmpk
s-memo:mcguYfwbSHFR2

これで準備完了です。後はFTPで認証を掛けたいディレクトリに「.htaccess」を/home/www/siteに「.htpasswd」を設置します。名前を変えて作っていた場合はファイル名を「htaccess.txt」を「.htaccess」に「htpasswd.txt」を「.htpasswd」に変更します。
「.htaccess」の名前は固定ですが(ただしApacheの設定で変更可能)、「.htpasswd」は「.password」など自由にファイル名前をつけられます。
FTPでアップロードする場合、両方とも「アスキー」モードでアップロードしてください。

と、気が付けばPHPのことよりBasic認証の設置方法のほうがスペース食っちゃった。。。
最近は何か基本的な技術紹介が多いのですが、メモ書きとして残しておこうかと考えました。
たまーにしか使用せず記述方法をよく忘れますので、、、(´Д`)

| | コメント (0) | トラックバック (0)

2007年03月09日

JavaScriptでGETを取得する

プログラムでURLの引数(GET)を取得する場合、PHPでは「$_GET」や「$_REQUEST」を使いますがJavaScriptではGETを取得する機能はありません。
PHPやPerlなどが使えるサーバであればいいのですが使えない場合、JavaScriptでGETを取得するにはどうしたらよいのでしょうか?
今日はJavaScriptでGETを取得する方法を紹介します。やり方は非常にシンプルでJavaScriptでは「location.search」というURLの「?」以下を取得できるプロパティがあり、それを分解するだけで簡単に使えます。
ただし、URLエンコードされたままなので半角英数以外は使えません。
と、自分で書いて思うのですがあまり使い道はなさそうだなぁ。。。
なぜ書いたかと言うと実際に仕事で使いましたので、次回からすぐに調べられるようにメモ書き程度に書くことにしました^^;

以下のスクリプトを追加して

function getRequest(){
  if(location.search.length > 1) {
    var get = new Object();
    var ret = location.search.substr(1).split("&");
    for(var i = 0; i < ret.length; i++) {
      var r = ret[i].split("=");
      get[r[0]] = r[1];
    }
    return get;
  } else {
    return false;
  }
}

最後に
var get = getRequest();

と記述すればOKです。
もし「http://xxxxxxx/xxx.html?id=3&code=test」というURLでアクセスした場合、
get['id']; // 「3」
get['code']; // 「test」

で、各GETを扱えます。先に述べたように日本語は使えません。
日本語を使う場合はURLデコードしなきゃいけないので、これはちょっと大変そうだなぁ^^;

| | コメント (2) | トラックバック (0)

2007年03月04日

マイブーム

1週間ほど前に本屋で技術の本を探していたら「Googleガジェット-プログラミング入門」という文字が目に入ってきました。
以前からGoogleガジェットやYahoo!ウィジェット等を気にはしていたもののほったらかし状態でした。
何気に手にしたら最後。ハマりました。そのまま衝動買い。
「ガジェット=ミニソフトウェア」とか思っていて、ソフトウェア開発は難しいものだと思い込んでいたのですが、本を見る限りHTMLとJavaScriptの知識があれば問題なさそうです。(実際はそんなに甘くはないのだろうけど^^;)
自分のパソコンを自由にカスタマイズできる辺りプログラマ魂に火がつきそうです。
「オリジナルのガジェット作るぞぉぉぉ!」と意気込んでおります。
さて、仕事がおろそかにならないように気をつけなければ、、、

Googleガジェット
Yahoo!ウィジェット

| | コメント (0) | トラックバック (0)

Yahoo! UIのイベントリスナー(addListener)を使ってみよう

つい先日Yahoo! UI Libraryが正式リリースされました。
バージョン0.2からバージョン1.0ではなく、いきなりバージョン2.2に。何故2.2なんだろう。
prototype.jsやjQueryだと機能が物足りない、、、と感じていたのですが正式リリースされたことと私の師匠の勧めもあり、YUIを使ってみました。で、使ってみたら、、、Yahoo! UI Libraryにはまりつつあります^^;ほとんどの機能はYahoo! UI Libraryでまかなえます。私はしばらくYahoo! UI Libraryを使ってみようと思います。まあ、浮気性なのでいつ別のフレームワークに移るか分かりませんが。
以前に、Yahoo! UIを使って非同期通信の紹介をさせて頂いたのですが今回はイベントリスナーを紹介します。
リスナーとは、予約機能みたいなものです。「マウスを動かした」「クリックした」「ウィンドウサイズを変更した」「キーボードのキーを押した」などの操作に対してHTMLの中にJavaScriptを埋め込むのが一般的かと思いますが、リスナーを使うとそれらの操作を事前に予約することができます。

Yahoo! UI Library
*「Download YUI」ボタンをクリックするとダウンロードできます。

今回は、「yahoo-min.js」「event-min.js」を使いますので、この2つのファイルを適当なディレクトリにコピーしてください。
インストールに関しては、「Yahoo! UIライブラリを使ってみよう」をご覧ください。

今回作成するサンプルは以下の構成になります。

[home]
 └─ index.html
 └─ [js]
     └─ yahoo.js
     └─ event-min.js

早速、イベントリスナーを使ってみます。
まずは外部のJavaScriptを参照しましょう。
<script type="text/javascript" src="./js/yahoo-min.js"></script>
<script type="text/javascript" src="./js/event-min.js" ></script>

次に以下の関数を作ります。
<script type="text/javascript">
function windowOpen() {
  alert("リスナーを使ってみよう");
}
</script>

「リスナーを使ってみよう」をいうテキストをダイアログ表示させるだけの簡単な関数です。
次に以下の1行を追加します。
<script type="text/javascript">
function windowOpen() {
  alert("リスナーを使ってみよう");
}
YAHOO.util.Event.addListener(window, "load", windowOpen);
</script>

「YAHOO.util.Event.addListener」の部分がイベントリスナーになります。これでイベントリスナー実装が終わりです。
ここまで作り終わったら、ブラウザで表示してみてください。
表示した瞬間に「リスナーを使ってみよう」をいうテキストがダイアログで表示されると思います。
通常であれば、
<body onLoad="windowOpen();">

のように<body>タグのonLoad属性にwindowOpen()と入れるのですが、リスナーを使うと<script>内に機能を入れることが出来ます。
「YAHOO.util.Event.addListener」の引数の説明は以下の通りです。
YAHOO.util.Event.addListener(id, event, action);
id:対象のID属性名
(windowでウィンドウ全体)
event:対象になるイベント
action:イベント発生時に呼び出す関数名

第2引数のeventには以下のような種類があります。
イベントの種類
load:ページにアクセスした
unload:ページを移動した(破棄した)
mouseover:対象物の上にマウスがある
mouseout:対象物の上にマウスがない
click:マウスをクリックした
mousedown:マウスのボタンを押し下げた
mouseup:マウスのボタンを上げた
change:formなどの内容が変わった
keydown:キーボードのキーを押し下げた
keyup:キーボードのキーを押し上げた

これだけだと何が良いのかよく分からないのでもう少しだけ実用的な
テキストの上にマウスを乗せると背景色が変わって、マウスが外れると背景色が元に戻るような機能を作ってみます。
<script>タグの中に以下のスクリプトを追加してください。

function rollOver() {
  this.style.backgroundColor = '#FFFF99';
}
function rollOut() {
  this.style.backgroundColor = '#FFFFFF';
}

さらに、以下のスクリプト(リスナー)も追加してください。
YAHOO.util.Event.addListener("listener", "mouseover", rollOver);
YAHOO.util.Event.addListener("listener", "mouseout", rollOut);

「listener」というID属性名に「mouseover」した場合、「rollOver」という関数を実行しなさい。とリスナー(予約)しています。
更に、「listener」というID属性名に「mouseout」した場合、「rollOut」という関数を実行しなさい。とリスナー(予約)しています。
最後に<body>タグ内に以下のHTMLを追加します。
<div id="listener">テキストのロールオーバ</div>

<div>タグ内に「listener」というID属性を追加しています。

これでロールオーバが完成しました。完成したらブラウザでプレビューしてみましょう。
「テキストのロールオーバ」というテキストにマウスを乗せると背景色が変わると思います。
ロールオーバも<body>タグ内ではなく、リスナーを使って<script>タグ内に機能を記述することで、ソースを見易くしました。
完成版のソースは以下を参照してください。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<title>Yahoo!リスナー</title>
<script type="text/javascript" src="./js/yahoo-min.js"></script>
<script type="text/javascript" src="./js/event-min.js" ></script>

<script type="text/javascript">
function rollOver() {
  this.style.backgroundColor = '#FFFF99';
}
function rollOut() {
  this.style.backgroundColor = '#FFFFFF';
}

YAHOO.util.Event.addListener("listener", "mouseover", rollOver);
YAHOO.util.Event.addListener("listener", "mouseout", rollOut);
</script>
</head>

<body>
<div id="listener">テキストのロールオーバ</div>
</body>
</html>

今回はイベントリスナー(addlistener)の紹介をさせて頂きました。
イベントリスナーを使うとHTMLソースが綺麗になります。しかし、下手に多様化すると解析が困難になるので別の作業者のことも考えてコーディングを行いましょう。

・関連記事
Yahoo! UIライブラリを使ってみよう

| | コメント (0) | トラックバック (0)