A.Saitouのページ

カウンタ

コンピュータと陸上競技生活についてまとめる個人のページです.


コンピュータ:2008年のログ
玄箱(Debian etch)でqmailメモ2008/12/27

 玄箱(Debian etch)でqmailを使ったメール鯖を立てたときのはまったところメモです.

 まず,バイナリパッケージでダウンロードできないので,apt-getでソースを入手してコンパイルします.

# apt-get install qmail-src ucspi-tcp-src
# build-ucspi-tcp
# build-qmail 
#

 これは様々なサイトに書かれている通りです.このあと,qmail関連を普通に設定するだけなのですが,思わぬところではまりました.

 起動スクリプト/etc/init.d/qmailで次のようにしないとsmtpポートとpopポートでListenしてくれませんでした.SMTPの起動ですが,-x /etc/tcp.smtp.cdbのあとにIPとPortを指定します.Portの指定で,smtpというニーモニックではなく,25を指定しないとsmtpでListenしません.また,POPの起動で,--exec /usr/bin/tcpserverの次の行,こちらもPortをpop3ではなく,110を指定しないとListenしません.

/etc/init.d/qmail
--
# prevent denial-of-service attacks, with ulimit
ulimit -v 16384
 sh -c "start-stop-daemon --start --quiet --user qmaild \
    --pidfile /var/run/tcpserver_smtpd.pid --make-pidfile \
    --exec /usr/bin/tcpserver -- -R -H \
    -u `id -u qmaild` -g `id -g nobody` -x /etc/tcp.smtp.cdb 0 25 \
    $rblsmtpd /usr/sbin/qmail-smtpd 2>&1 \
    | $logger &"
#中略#
# Uncomment the following lines to automatically start the pop3 server
sh -c "start-stop-daemon --start --quiet --user root \
    --pidfile /var/run/tcpserver_pop3d.pid --make-pidfile \
    --exec /usr/bin/tcpserver -- -R -H \
    0 110 /usr/sbin/qmail-popup `hostname`.`dnsdomainname` \
    /usr/bin/checkpassword /usr/sbin/qmail-pop3d Maildir &"
--

 通常,/etc/servicesで指定してあれば,smtpやpop3というニーモニックのPort指定で問題ないはずです.どうも,ソースからコンパイルしたtcpserverが怪しそうです./etc/servicesを読んでない感じがします.

 このあと,vpopmailを入れて,バーチャルドメイン対応にしようとしたのですが,パッチなど運用とメンテナンスが激しく面倒なので,postfixでいくことにしました.apt-getで最新版を入れるのになれちゃうと,不精になっていけませんね.

PHPで日本語ファイル名でファイルをダウンロードする2008/12/23

 日本語ファイル名でファイルをダウンロードするPHPアプリを作ったときのメモです.

 まず,日本語文字コードをブラウザやOSに合わせないと文字化けします.どのブラウザとOSでも問題のでないやり方は見つけられませんでした.ユーザエージェント毎に処理して解決しました.

 Macintosh + Safariの場合,奥村先生のホームページによると環境変数PATH_INFOを使い,UTF-8でやるといいらしいですが,試していません.普通にやると,EUC, SJIS, UTF-8とそのURLエンコードで全6パターン試しましたが文字化けしました.

 ファイルをダウンロードさせるPHPスクリプトは以下のような内容で書いてます.

header( "Content-Type: " . $downfile["type"] );
header( "Content-Length: " . filesize($downfile["path"]) );
header( "Content-Transfer-Encoding: binary" );
header( "Content-Disposition: attachment; filename=\"".$downfile["name"]."\"" );
readfile($downfile["path"]);

 $downfile["name"]に指定するファイル名の文字コードが今回の話題です.

UPSバッテリ交換2008/12/23

 2001年に購入したUPS-オムロンBX25XT-を玄箱のバックアップに使っています.先週,バッテリ交換のアラームが止まらなくなったので,交換バッテリBP25XTをamazonで税込6,825円で購入しました.7年も経つのにネット販売で購入できるのは助かります.

 昨日,物が届いたので,早速交換しました.作業は,ビスを1個外して,コネクタを抜き挿しするだけでした.簡単です.

 マニュアルには電池寿命2~3年とあったのですが,7年も使ってしまいました.停電していないときは,商用電源入力がそのままスルー出力されるタイプのUPSなので,温度環境が良かったのかもしれません.さて,今度は何年もちますか.

ユーザ認証(ベーシック認証とダイジェスト認証)するときの.htaccessの設定メモ2008/12/15

 apacheでユーザ認証するには,ベーシック認証とダイジェスト認証の2つを選択できます.ベーシック認証の場合は次のようになります.

■特定ユーザのみ許可する場合
(例として,ユーザname_userだけを許可する.)
.htaccess
---
AuthUserFile    /home/hogehoge/.htpass
AuthGroupFile   /dev/null
AuthName        "PrivateArea"
AuthType        Basic
Require user    name_user
---

■登録ユーザすべて許可する場合
.htaccess
---
AuthUserFile    /home/hogehoge/.htpass
AuthGroupFile   /dev/null
AuthName        "PrivateArea"
AuthType        Basic
Require valid-user
---

■パスワードファイル
○.htpassは,htpasswd コマンドを使って生成する.

 同じホストで,複数のユーザ認証エリアを設定する場合,AuthNameをユニークにした方がいいです.ブラウザ側でIDとパスワードを記憶する機能がありますが,AuthNameを元に切り分けるので,重複していると認証エラーでいちいち入力を求められてしまいます.

 ダイジェスト認証は,IDとパスワードをダイジェストでやり取りする方法で,ベーシック認証のようにIDとパスワードが平文で流れないため,セキュリティ上好ましい方式です.ただし準備として,apacheの設定に手を入れる必要があります.ここでは,Debian Etch(無印)玄箱のapache2.2の場合を説明します.

 まず,auth_digestモジュールを有効にします.

# a2enmod auth_digest
#

 そして,次の一行を/etc/apache2/httpd.confや/etc/apache2/apache2.confに登録します.設定後,apacheを再起動します.

BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On

 IE6でダイジェスト認証を使う場合,この設定が入っていないと,ダイジェスト認証を使った場合,GETメソッドを使っているcgi等で不具合がでます.なお,IE7では,バグが直ったのか,この設定なしで動作しました.また,Firefoxも設定なしで問題なく動作しました.IE6特有の症状みたいです.その他のブラウザは試していません.

 これでダイジェスト認証が使えます..htaccessの設定は次のようになります.

■特定ユーザのみ許可する場合
(例として,ユーザname_userだけを許可する.)
.htaccess
---
AuthUserFile    /home/hogehoge/.htpassdj
AuthGroupFile   /dev/null
AuthName        "PrivateArea"
AuthType        Digest
Require user    name_user
---

■登録ユーザすべて許可する場合
.htaccess
---
AuthUserFile    /home/hogehoge/.htpassdj
AuthGroupFile   /dev/null
AuthName        "PrivateArea"
AuthType        Digest
Require valid-user
---

■パスワードファイル
○.htpassdjは,htdigest コマンドを使って生成する.
○realmとAuthNameは同じにする.
HDD故障22008/12/09

 前回,異常が出ているドライブのデータを移動し,設定していたページファイルもCドライブへ戻しました.その後,カツンという異音もなくなったため,Dドライブ用HDDの故障で確定と判断しました.さらば,Maxtor DiamondMax.

 個人的な経験での話になりますが,HDDの故障原因は大きく2種類です.ディスクにヘッドがあたるなどの物理故障とディスクコントローラ故障です.前者の場合,水平または垂直かつ振動の少ない場所に設置されていて壊れたのであれば,寿命なのであきらめます.後者の場合,同じ型の-HDD裏側についている-基盤を交換すれば,復活する可能性大です.何年も経ったあとに壊れることが多いので,ほとんど入手できませんけど.(笑)

 コントローラ故障の対策ですが,HDD用ファンをつけるなど,がんがん冷やしてあげれば,かなりの確率で防げます.アイネックス社のHDC-501シリーズを愛用していますが,これを使って以来,コントローラ故障は経験していません.ファンレスマシンの場合は特にご注意を!

(無印)玄箱の負荷軽減(Debian etch) updatedb.confの設定変更2008/12/08

 朝方,一般的なLinuxデストリでは,/etc/cron.daily 内のスクリプトが実行されます.(無印)玄箱をDebian etch化したマシンでは,デフォルトに手を加えていないはずなので,午前6時25分です.最近,このプロセスに関するHDD音が長くなってきました.

 中身をみると,findというスクリプトがあって,その中で-ファイル検索-locateコマンド用のupdatedbコマンドが呼ばれています.この処理が原因でずーっとHDDが動作しっぱなしになっていました.ちょうど,/home 以下に数万個のファイルを保存していたので,検索処理に時間かかるのは当然です.毎日この処理を実行されてはたまらないので,次のように設定変更しました./home 以下を検索しなくなります.

/etc/updatedb.conf
---
# paths which are pruned from updatedb database
# 変更前
# PRUNEPATHS="/tmp /usr/tmp /var/tmp /afs /amd /alex /var/spool /sfs /media"
# 変更後
PRUNEPATHS="/tmp /usr/tmp /var/tmp /afs /amd /alex /var/spool /sfs /media /home"
---

 これで,朝,HDD音で目覚めることはなくなるでしょう.(笑)

ソースコードをHTMLで表示させるときのツール(PHPで作ってみる)22008/12/08

 先に作ったのは少し使い勝手が悪かったので,出力仕様を再考してみます.

 ソースコードをHTML文書へコピペするとき,もっとも楽な方法は,<pre></pre>タグでソースコードを囲んでしまうことです.ただし,<pre></pre>タグ内でHTML特殊文字を使う場合,例えば<を&lt;に変換する必要があります.そこで,この変換部分だけを処理するプログラムにしてしまおうと思います.この方法だと,改行を<br />に置き換えたり,インデントをスペースで置き換えなくても済みます.また,変換した後に削除・追加・編集するのが簡単になります.

 上記を踏まえ,出力仕様を次のようにします.

 変更した結果を【こちら】に反映しました.ソースの変更点は以下の部分です.$_POST["text_input"]をいきなり処理するのは危ないので,POSTデータがある場合だけ処理するようにします.

$str_text_output = "";
if ( isset($_POST["text_input"]) && strlen($_POST["text_input"]) > 0 )
{
	// 文字コード変換
	$str_text_output = mb_convert_encoding( $_POST["text_input"], "EUC-JP", "UTF-8" );

	// PHPデフォルトでクォートされるのでアンクォート
	$str_text_output = stripcslashes( $str_text_output );

	// html特殊文字を変換
	$str_text_output = htmlspecialchars( $str_text_output );

	// <pre></pre>タグで囲む 2008/12/08
	$str_text_output = "<pre>\n".$str_text_output."\n</pre>";

	// コピペ用に更にhtml特殊文字を変換
	$str_text_output = htmlspecialchars( $str_text_output );
}
ソースコードをHTMLで表示させるときのツール(PHPで作ってみる)

 PHPでソースコードなどを表示させるとき,関数 htmlspecialchars を使えば,簡単にhtml特殊文字を変換できます.毎度変換ソフトを立ち上げるのもあれなんで,この関数を使って変換ツールを作ってみようと思います.

 インタフェースは,入力用textareaフォーム,出力用textareaフォームおよびsubmitボタンだけで十分しょう.submitされた入力用textareaの内容を1)文字コード変換,2)アンクォート,3)html特殊文字変換,4)改行コード変換,最後に再度5)html特殊文字変換します.html特殊文字変換が一回だと,ソースコードがそのまま表示されてしまうので,コピペして使えません.ソースを表示すればよいのですが,あまりにも面倒なので,コピペできるように2度変換します.最後に文字列をhtml文へ組み込んで表示します.文字コードは,内部文字コードをEUC,出力文字コードをUTF-8にします.

 上記仕様で【こちら】に作ってみました.ちなみに,ソースは下のようになりました.

<?php
//
// htmlconv.php
//
// (C) Copyright A.Saitou 2008
//
// 2008/12/08 Ver.1.0 初版
//

// 文字コード変換
$str_text_output = mb_convert_encoding( $_POST["text_input"], "EUC-JP", "UTF-8" );

// PHPデフォルトでクォートされるのでアンクォート
$str_text_output = stripcslashes( $str_text_output );

// html特殊文字を変換
$str_text_output = htmlspecialchars( $str_text_output );

// 改行コード変換
$str_text_output = nl2br( $str_text_output );

// コピペ用に更にhtml特殊文字を変換
$str_text_output = htmlspecialchars( $str_text_output );


// ページ本文文字列設定 ///////////////////////////////////////////////////////
$str_html =<<<EOL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>htmlconv</title>
</head>
<body>

<h1>htmlconv</h1>

<hr />

<form method="POST" action="htmlconv.php" target="_top">

<p>入力コード<br /><textarea name="text_input" cols=80 rows=10></textarea></p>

<p>出力コード<br /><textarea name="text_output" cols=80 rows=10>{$str_text_output}</textarea></p>

<p><input type="submit" value="変換" /></p>

</form>

<hr />

</body>
</html>

EOL;

// 出力 ///////////////////////////////////////////////////////////////////////
header( "Content-Type: text/html; charset=UTF-8" );
print mb_convert_encoding( $str_html, "UTF-8", "EUC-JP" );

?>

HDD故障2008/12/06

 朝起きたら,付けっぱなしのパソコン-Windows2000-がフリーズしてました.システムイベントには次のメッセージが書き込まれていました.

 Harddisk1なので,2番目のディスク,Dドライブに使っているHDDがお亡くなりのようです.しかし,コマンド「CHKDSK /R」でも不良セクタはでませんでした.よくあるソフトウェアレベルでは上がってこないエラーでしょうか.とりあえずDドライブ上の全データを移動して様子見です.

PHPでアクセスカウンタを作ってみる(2)2008/12/03

 前回作ったカウンタにカウントアップしないIPアドレスの指定機能とリファラチェックを入れました.まず,それぞれの配列を定義します.

// 非カウントアップIP
$config["IP_INVALID"] = array( "127.0.0.1", "192.168.1." );

// カウントアップリファラ
$config["REF_VALID"] = array( "http://hogehoge/" );

 次に,スーパーグローバル変数からリモートアドレスとリファラを取得します.

$g_srcip = $_SERVER["REMOTE_ADDR"]; //接続元IP
$g_referer = $_SERVER["HTTP_REFERER"]; //リファラ

 最後に,それぞれチェックして,その結果でカウントアップするか否か,判断します.

// ソースIPチェック
$srcipchk = true;
foreach( $config["IP_INVALID"] as $val )
{
    if ( strpos( $g_srcip, $val ) !== false )
    {
        $srcipchk = false;
    }
}

// リファラチェック
$refchk = true;
foreach( $config["REF_VALID"] as $val )
{
    $chk = strpos( $g_referer, $val );
    if ( $chk === false || $chk != 0 )
    {
        $refchk = false;
    }
}

 その他,テーブルのカラム追加など修正を加えて,次のようなソースコードになりました.まだカウンタをリセットするとか,加えたい機能はありますが,それはまた後日に.

<?php
//
// mycnt.php
//
// 2008/11/30 Ver 1.1 ソースIPチェック,リファラチェック追加
// 2008/11/30 Ver 1.0 初版
//
// (C) Copyright 2008 A.Saitou
//
// 環境:PHP5.0+PDO+SQLite3
//

// 環境設定 ///////////////////////////////////////////////////////////////////

// ベースディレクトリ
$config["DIR_DATA"] = "./";

// DBファイル
$config["FILE_DB"] = $config["DIR_DATA"]."mycnt.db";

// テーブル名
$config["DB_TABLE"] = "tbl_cnt";

// 背景色
$config["COLOR_BACK"] = 0xffffff;

// 文字列色
$config["COLOR_TEXT"] = 0x0000ff;

// 桁数
$config["TEXT_NUM"] = 8;

// 非カウントアップIP
$config["IP_INVALID"] = array( "127.0.0.1", "192.168.1." );

// カウントアップリファラ
$config["REF_VALID"] = array( "http://hogehoge/" );

// 広域変数 ///////////////////////////////////////////////////////////////////
$g_count = ''; //カウンタ文字
$g_utime = time(); //現在時刻
$g_srcip = $_SERVER["REMOTE_ADDR"]; //接続元IP
$g_referer = $_SERVER["HTTP_REFERER"]; //リファラ

// DB処理 /////////////////////////////////////////////////////////////////////

try
{
    $dbh = new PDO("sqlite:".$config["FILE_DB"], "", "");
    
    // テーブル存在チェック
    $sql = "SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='{$config['DB_TABLE']}'";
    $stmt = $dbh->
prepare( $sql );
    $stmt->execute();
    $res = $stmt->fetch(PDO::FETCH_ASSOC);
    
    // テーブルが存在しない場合はテーブル生成
    if ( intval($res["cnt"]) < 1 )
    {
        $sql = "CREATE TABLE {$config['DB_TABLE']} (
            id            INTEGER PRIMARY KEY AUTOINCREMENT,
            utime        INTEGER NOT NULL,
            srcip        VARCHAR(15),
            referer        VARCHAR(1024)
        )"
;
        $stmt = $dbh->prepare( $sql );
        $stmt->execute();
    }
    
    // ソースIPチェック
    $srcipchk = true;
    foreach( $config["IP_INVALID"] as $val )
    {
        if ( strpos( $g_srcip, $val ) !== false )
        {
            $srcipchk = false;
        }
    }
    
    // リファラチェック
    $refchk = true;
    foreach( $config["REF_VALID"] as $val )
    {
        $chk = strpos( $g_referer, $val );
        if ( $chk === false || $chk != 0 )
        {
            $refchk = false;
        }
    }
    
    // UNIX時刻挿入
    if ( $srcipchk && $refchk )
    {
        $sql = "INSERT INTO {$config['DB_TABLE']} ( utime, srcip, referer ) VALUES( {$g_utime}, '{$g_srcip}', '{$g_referer}' )";
        $stmt = $dbh->prepare( $sql );
        $stmt->execute();
    }
    
    // 最新プライマリキーの読出
    $sql = "SELECT max(id) as id FROM tbl_cnt";
    $stmt = $dbh->prepare( $sql );
    $stmt->execute();
    $res = $stmt->fetch(PDO::FETCH_ASSOC);
    $tmp = 0;
    if ( $res["id"] != NULL )
    {
        $tmp = intval($res["id"]);
    }
    if ( $tmp >= 0 )
    {
        //カウンタ設定
        $g_count = sprintf( "%0{$config['TEXT_NUM']}d", $tmp);
    }
    
} catch (PDOException $e){
    echo $e->getMessage();
    exit(1);
}

// カウンタ画像生成 ///////////////////////////////////////////////////////////

// ベース
$im_base = imagecreatetruecolor( $config['TEXT_NUM']*8, 16 );

// 背景塗りつぶし
imagefill( $im_base, 0, 0, $config["COLOR_BACK"] );

// カウンタ文字描画
imagestring( $im_base, 4, 0, 0, $g_count, $config["COLOR_TEXT"] );

// カウンタ画像出力 ///////////////////////////////////////////////////////////

// 形式ヘッダ
header("Content-type: image/png");

// 出力
imagepng( $im_base );

// イメージ破棄
imagedestroy( $im_base );

// 終了
exit(0);

?>

特定ホストやネットワークからの接続だけ許可する.htaccessの設定メモ2008/12/02

 たまに.htaccessを書こうとすると設定方法を忘れています.年でしょうか.自分でコピー&ペーストするために記録しておきます.

.htaccess
--
order deny,allow
deny from all

# 許可ホスト.サブネット単位やドメインでも指定可能.
allow from 192.168.0.100
allow from 192.168.1.
allow from 192.168.2.0/24
allow from .xxx.xxx.xxx
--
PHPでファイルアップロードするときのphp.ini設定メモ2008/12/02

 PHPでファイルアップロードするとき,デフォルトでは2MBにサイズが制限されます.設定変更するときは,php.iniでupload_max_filesize,post_max_sizeおよびmemory_limitを設定します.これら数値の関係はmemory_limit ≥ post_max_size ≥ upload_max_filesizeです.

ソースコードをHTMLで表示させるときのツール2008/11/30

 下の記事でPHPのソースコードを表示させるとき,SourceConverterを使わせていただきました.作者様に感謝です.

PHPでアクセスカウンタを作ってみる2008/11/30

 どうも満足できるアクセスカウンターが見つかりません.単純にカウントアップ画像を出すCGIは色々あるのですが,アクセス時の接続元IPや参照元などログとして取っておけるのが見つかりません.どこかのWEBサービスを使えば解決するのですが,自分のサイトの情報を他のサーバにおくのも何なので,今回,PHPとSQLiteで作ってみようと思いました.なぜにSQLiteかというと,専用ファイルで記録したときの排他が面倒なのと,将来的に拡張しやすいからです.また,MySQLなど本格的なDBMSでは,相当量のCPUとメモリが要求されます.無印玄箱の処理能力を考慮して,SQLiteがちょうどいいと考えました.

 まず,DBを使うので,拡張するときカラムを追加するとして,最小の仕様とします.テーブルは,プライマリキーのオートインクリメント整数とUNIX時刻のアクセス時刻の2カラムにします.接続元IPやリファラなども入れたいところですが,がまんです.

 次に,出力仕様を考えて見ます.素のHTMLソースへカウンタを埋め込む時,そのフォーマットを画像にするかテキストにするか,悩みどころです.画像であれば,imgタグで参照すれば良いだけです.テキストの方は,Javascript読込になりそうです.テキストの場合,Javascriptが動かないブラウザや機能自体を無効にされると動かなくなるので,画像で出した方がよさそうです.よって,今回は画像フォーマットにします.

 画像の出力方法は,数値画像を連結させる方法ではなく,PHPでGDライブラリを使って動的に生成してみようと思います.画像連結は,画像ファイルのライセンス云々が面倒なので,見送りです.

 PHP本体は,次のような流れにします.

  1. DBチェック.テーブルが存在しない場合はデーブル生成.
  2. テーブルへINSERT.プライマリキーは,オートインクリメントなので無視.アクセス時のUNIX時刻だけを挿入.
  3. 挿入したときのプライマリキーを読み出し.これをカウンタの数字設定.
  4. ベース画像生成.サイズ決定と塗りつぶし.
  5. カウンタ数字文字列描画.
  6. 出力.ヘッダ情報を送信してから,画像本体を送信.

 これでざっと,ソースを書いてみます.

<?php
//
// mycnt.php
//
// 2008/11/30 初版
//
// (C) Copyright 2008 A.Saitou
//
// 環境:PHP5.0+PDO+SQLite3
//

// 環境設定 ///////////////////////////////////////////////////////////////////

// ベースディレクトリ
$config["DIR_DATA"] = "./";

// DBファイル
$config["FILE_DB"] = $config["DIR_DATA"]."mycnt.db";

// テーブル名
$config["DB_TABLE"] = "tbl_cnt";

// 背景色
$config["COLOR_BACK"] = 0xffffff;

// 文字列色
$config["COLOR_TEXT"] = 0x0000ff;

// 桁数
$config["TEXT_NUM"] = 8;

// 広域変数 ///////////////////////////////////////////////////////////////////
$g_count = ''; //カウンタ文字
$g_utime = time(); //現在時刻

// DB処理 /////////////////////////////////////////////////////////////////////

try
{
    $dbh = new PDO("sqlite:".$config["FILE_DB"], "", "");
    
    // テーブル存在チェック
    $sql = "SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='{$config['DB_TABLE']}'";
    $stmt = $dbh->
prepare( $sql );
    $stmt->execute();
    $res = $stmt->fetch(PDO::FETCH_ASSOC);
    
    // テーブルが存在しない場合はテーブル生成
    if ( intval($res["cnt"]) < 1 )
    {
        $sql = "CREATE TABLE {$config['DB_TABLE']} (
            id            INTEGER PRIMARY KEY AUTOINCREMENT,
            utime        INTEGER NOT NULL
        )"
;
        $stmt = $dbh->prepare( $sql );
        $stmt->execute();
    }
    
    // UNIX時刻挿入
    $sql = "INSERT INTO {$config['DB_TABLE']} ( utime ) VALUES( {$g_utime} )";
    $stmt = $dbh->prepare( $sql );
    $stmt->execute();
    
    // 挿入したプライマリキーの読出
    $tmp = intval($dbh->lastInsertId());
    if ( $tmp > 0 )
    {
        //カウンタ設定
        $g_count = sprintf( "%0{$config['TEXT_NUM']}d", $tmp);
    }
    
} catch (PDOException $e){
    echo $e->getMessage();
    exit(1);
}

// カウンタ画像生成 ///////////////////////////////////////////////////////////

// ベース
$im_base = imagecreatetruecolor( $config['TEXT_NUM']*8, 16 );

// 背景塗りつぶし
imagefill( $im_base, 0, 0, $config["COLOR_BACK"] );

// カウンタ文字描画
imagestring( $im_base, 4, 0, 0, $g_count, $config["COLOR_TEXT"] );

// カウンタ画像出力 ///////////////////////////////////////////////////////////

// 形式ヘッダ
header("Content-type: image/png");

// 出力
imagepng( $im_base );

// イメージ破棄
imagedestroy( $im_base );

// 終了
exit(0);

?>

 実際表示してみると,【カウンタ】のように表示されます.環境設定のベースディレクトリは,外部から参照されない場所に設定した方が安全です.コピペして使う人は皆無に近いと思いますが,ご注意ください.

 今回は,このあたりで失礼します.また次回があればですけど.(笑)