超俺clap!

  1. ChaoOreClap.php
  2. thanks.html
  3. test.html(送信フォーム例)
  4. error.html(エラー例)
  5. プチリファレンス

phpのshow_source的な関数を使っていますので
見づらかったり文字化けしていたりしますがそのあたりは脳内補完をお願いいたします。

ChaoOreClap.php

<?php
/* info
-----------------------------------------------
Chao!!-Ore-Clap! for general
超俺clap! ver.1.02
FileName: clap.php
Build:    2005.12.13(original) - 2005.12.17
Author:   hachiman_cian (八満とシアン)
Address:  駄文同盟.com (http://www.dabun-doumei.com/)
----------------------------------------------- */

/* 基礎処理部分
----------------------------------------------- */
if(phpversion() > "4.1.0"){
    
extract($_POST);
}
#スパムが来る場合のみ(この機能は現在無効にしています)
#if(preg_match("/@yahoo.co.jp$/",$name)){    //スパム弾き
#    $spam = "This may be SPAM";
#}

/* 基礎設定部分
----------------------------------------------- */
//-----------以下の項目を設定してください
$from        "(MAIL ADDRESS)";    //送信元        自分のメールアドレスにしてください
$to            "(MAIL ADDRESS)";    //送信先(メッセージ画ある場合    :: 携帯電話のアドレスにするとハッピー
$pcto        "(MAIL ADDRESS)";    //送信先(メッセージがない場合)    :: パソコンのアドレスにするとハッピー
$clapFile    "data.cgi";        //メッセージを書き出すファイル(cgi拡張子ですがプログラムではありません/パーミッションは666)
$pageError    "error.html";        //ダメなコに見せるページ
$pageOrei    "thanks.html";    //clap送信後ページ

$modeSimple    "";                //noにするとメッセージなしのclap!をエラー扱いにします
$modeCSV    "dataCSV.cgi";    //csvっぽい形式でログを生成します。書き出すファイル名を設定してください

$thanksMessage = array(
    
'ステキなclapありがとうございました!',
    
'そんなあなたのclapが大好きです!',
    
'ぱちぱちありがとうございましたぁ!',
);    
//お礼のメッセージ
//        ↑メッセージと画像は対応して表示させることが出来ます。
//        1つめのメッセージには"0.png"、2つめのメッセージには"1.png"という具合です。
//        10を超えた場合でも"10.png"...と無限に続きます。
//        メッセージは何でも構いません。ただし'(シングルクォーテーション)は入れてはいけません。

//-----------以下、フィーリングで改造可能です
if(!$name){$name "匿名希望";}
$name        stripslashes($name);


/* 関数部分
----------------------------------------------- */
//-----------以下、関数部分のいくつかは『PHP Web Mailer MIME B  by ToR (http://php.s3.to)』を参考に
/* original by TOMO http://www.spencernetwork.org/ */
function sjis2jis($sjis){                //SJIS→JIS変換
    
$jis '';
    
$ascii true;
    
$b unpack("C*"$sjis);
    for(
$i 1$i <= count($b); $i++){
        if(
$b[$i] >= 0x80){
            if(
$ascii){
                
$ascii false;
                
$jis .= chr(0x1B).'$B';
            }
            
$b[$i] <<= 1;
            if(
$b[$i+1] < 0x9F){
                
$b[$i]   -= ($b[$i] < 0x13F) ? 0xE1 0x61;
                
$b[$i+1] -= ($b[$i+1] > 0x7E) ? 0x20 0x1F;
            }else{
                
$b[$i] -= ($b[$i] < 0x13F) ? 0xE0 0x60;
                
$b[$i+1] -= 0x7E;
            }
            
$b[$i] = $b[$i] & 0xff;
            
$jis .= pack("CC"$b[$i], $b[$i+1]);
            
$i++;
        }else{
            if(!
$ascii){
                
$ascii true;
                
$jis .= chr(0x1B).'(B';
            }
            
$jis .= pack("C"$b[$i]);
        }
    }
    if (!
$ascii$jis .= chr(0x1B).'(B';
    return 
$jis;
}

function 
HANtoZEN_SJIS($str_HAN){//半角→全角
    
$table_han2zen_sjis = array(0x8142,0x8175,0x8176,0x8141,0x8145,0x8392,
    
0x8340,0x8342,0x8344,0x8346,0x8348,0x8383,0x8385,0x8387,0x8362,0x815B,
    
0x8341,0x8343,0x8345,0x8347,0x8349,0x834A,0x834C,0x834E,0x8350,0x8352,
    
0x8354,0x8356,0x8358,0x835A,0x835C,0x835E,0x8360,0x8363,0x8365,0x8367,
    
0x8369,0x836A,0x836B,0x836C,0x836D,0x836E,0x8371,0x8374,0x8377,0x837A,
    
0x837D,0x837E,0x8380,0x8381,0x8382,0x8384,0x8386,0x8388,0x8389,0x838A,
    
0x838B,0x838C,0x838D,0x838F,0x8393,0x814A,0x814B);
    
$str_ZEN '';
    
$b unpack("C*"$str_HAN);
    for(
$i 1$i <= count($b); $i++){
        if(
0xA1 <= $b[$i] && $b[$i] <= 0xDF){
            
$b[$i] -= 0xA1;
            
$c1 = ($table_han2zen_sjis[$b[$i]] & 0xff00) >> 8;
            
$c2 $table_han2zen_sjis[$b[$i]] & 0x00ff;
            
$str_ZEN .= pack("CC"$c1$c2);
        }elseif(
$b[$i] >= 0x80){
            
$str_ZEN .= pack("CC"$b[$i], $b[$i+1]);
            
$i++;
        }else{
            
$str_ZEN .= pack("C"$b[$i]);
        }
    }
    return 
$str_ZEN;
}

function 
mime_enc($usr_str,$mime=0){            //MIMEエンコード
    
if(get_magic_quotes_gpc()) $usr_str stripslashes($usr_str);//\は取る
    
$usr_str HANtoZEN_SJIS($usr_str);
    
$enc sjis2jis($usr_str);            //JISに変換
    
if($mime$encode "=?iso-2022-jp?B?" base64_encode($enc) . "?=";    //Bヘッダ+エンコード
    
else $encode $enc;
    return 
$encode;
}

function 
clapHtml($name_html,$message_html,$option_html){
    global 
$clapFile,$pageOrei,$thanksMessage,$modeCSV;
    
$thanks_count count($thanksMessage) - 1;
    
$random rand(0,$thanks_count);
    
$thanksMessage $thanksMessage[$random];

    require_once 
"$pageOrei";

    switch(
date('w')){
        case 
0$youbi "日";break;
        case 
1$youbi "月";break;
        case 
2$youbi "火";break;
        case 
3$youbi "水";break;
        case 
4$youbi "木";break;
        case 
5$youbi "金";break;
        default: 
$youbi "土";
    }
    
$time date("Y年m月d日") . "(${youbi})" date("G時i分s秒");
    
$option_putout strip_tags($option_html);
    
$IP = @gethostbyaddr(getenv("REMOTE_ADDR"));

//-----------ファイルに書き出す内容
$putoutData =<<<_HTML_
日時 :: ${time}
感謝 :: 
${name_html}さん
本文 :: 
${message_html}
発信 :: 
${IP}
${option_putout}
-----------------------------\n
_HTML_;

    
$fp fopen("$clapFile","a");
    
flock($fpLOCK_EX);
    
fputs($fp$putoutData);
    
fclose($fp);

//-----------csv的ファイルに書き出す内容
    
if($modeCSV){
        
$putoutData str_replace("\n""\\n",($time "<>" $name_html "<>" $message_html "<>" $option_putout "<>" $IP));
        
$fp fopen("$modeCSV","a");
        
flock($fpLOCK_EX);
        
fputs($fp, ($putoutData "\n"));
        
fclose($fp);
    }

    exit;
}

function 
returnError($error){
    global 
$pageError;
    require_once 
"$pageError";
}


/* いろんな処理の部分(メイン)
----------------------------------------------- */
//-----------オプション項目
/* 
    name="opt[]"とすることでいくつでもオプションの項目が増やせます。
    例).form関連のどんなタグでもイケます
            好きな薔薇乙女 :: <input type="text" name="opt[好きな薔薇乙女]" />
            好きな桑谷夏子 :: <input type="checkbox" name="opt[好きな桑谷夏子multi]" value="翠星石" /><input type="checkbox" name="opt[好きな桑谷夏子multi]" value="カーシャ" />
            田中理恵といえば :: <select name="opt[]"><option value="水銀燈" selected="selected" /><option value="ルミナス" /></select>
        ※ほかにもチェックボックスなどなどアンケートにも転用可能(集計は自力で) ⇒別ファイル参照
        ※多次元配列の処理の仕方は違っているような気がしますがちゃんと動くのでヨシと。したいと。
*/
if(is_array($opt)){
    foreach(
$opt as $key => $val){
        if(
$val){        //不選択の項目は表示させない(『なし』表記にしたほうが良い?)
            
$i++;
            if(!
is_string($key) || !is_string($key)){    //多次元配列を処理-I (checkboxの場合は$keyなどが配列になっている)
                
$key strval($key);
                
$val strval($val);
            }
            if(
preg_match('/multi$/',$key)){    //多次元配列を処理-II (checkboxにつけるnameの語尾がmultiの場合は展開)
                
$val "";
                for(
$tajigen 0$tajigen count($opt[$key]); $tajigen++){
                    
$val .= $opt[$key][$tajigen] . " ";
                }
                
$key preg_replace('/multi$/','',$key);
            }
            
$optionLine "備考-${i}『${key}』 :: ${val}\n";
            if(
preg_match("/[\x80-\xA0]/",$val)){
                
$option .= mime_enc("$optionLine",0) . "\n";        //本文に日本語がある場合JIS変換
            
}else{
                
$option .= $optionLine "\n";
            }
            
$option_html .= $optionLine "\n";
        }
    }
}

//-----------clap!をどう処理するか(メッセージなし/clap!連打推奨の場合)
if(!$message){
    if(
$modeSimple){
        
$error "メッセージがありません";
    }else{
        
$message "応援しています(パチパチ)!";
        
$nomessage "メッセージなし";
    }
}
if(
$clap == "renda"){
    
$nomessage "連打推奨clap";
}

//-----------メイン
$boundary md5(uniqid(rand()));        //バウンダリー文字(何でも

$name_html $name;                        //保持
if(preg_match("/[\x80-\xA0]/",$name)){
    
$name mime_enc($name,1);            //日本語ならMIMEヘッド
}
$from = ($from) ? "$name<$from>" $name;

$body "";
$heady  "From: $from\n";                                        //From
$heady .= "X-Mailer: PHP/".phpversion()."\n";
$heady .= "MIME-version: 1.0\n";                                //MIMEヘッダ
$heady .= "Content-Type: text/plain; charset=\"iso-2022-jp\"\n";
$heady .= "Content-Transfer-Encoding: 7bit\n";
$heady .= "X-HOST: ".@gethostbyaddr(getenv("REMOTE_ADDR"));        //おまけ・・


$message str_replace("\r\n""\n"$message);                    //改行文字の統一
$message str_replace("\r""\n"$message);
$message ereg_replace("^(\n)+|(\n)+$"""$message);            //連続改行を消す
$message_html $message;                                        //保持

if(mb_strlen($message) > 100){
    
$subject mb_substr($message,0,100);
    
$subject .= "...";
}else{
    
$subject $message;
}
$subject mime_enc($subject,1);

//-----------メール本文
$message = <<<_EOD_
${name_html}さんより拍手です!
-----------------------
${message}
-----------------------
${option}
_EOD_;

if(
preg_match("/[\x80-\xA0]/",$message)){        //本文に日本語がある場合JIS変換
    
$body .= mime_enc($message,0);
}else{
    
$body .= $message;
}

$body .="---------------------------------------------\n";
$body .= gmdate("Y/m/d H:i:s",time()+9*3600)."\n";
$body .= @gethostbyaddr(getenv("REMOTE_ADDR")) . "\n";
$body .= getenv("HTTP_USER_AGENT")."\n";
$body .="---------------------------------------------\n";

//-----------変換など
$name_html        htmlspecialchars($name_html,ENT_QUOTES);        //htmlでの表示(お礼ページ)ではタグを無効化
$message_html    htmlspecialchars($message_html,ENT_QUOTES);    //htmlでの表示(お礼ページ)ではタグを無効化
$option_html    htmlspecialchars($option_html,ENT_QUOTES);    //htmlでの表示(お礼ページ)ではタグを無効化
$name_html        stripslashes($name_html);                        //htmlでの表示(お礼ページ)では/を無効化
$message_html    stripslashes($message_html);                    //htmlでの表示(お礼ページ)では/を無効化
$message_html    preg_replace('/((http|https):\/\/([-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+))/i' '<a href="\\1">\\1</a>'$message_html);
$option_html    stripslashes($option_html);                    //htmlでの表示(お礼ページ)では/を無効化
$option_html    ereg_replace("(\n)+","</li>\n<li>",$option_html);        //htmlの場合でもオプションのみ改行を許す

//-----------メールの最終処理判断
if($error){                                        //エラーへの対応
    
returnError($error);
}elseif(
$clap && !$spam && !$nomessage){
    if(
mail($to$subject$body$heady)){
        
clapHtml($name_html,$message_html,$option_html);
    }
}elseif(
$spam){                                    //スパム弾きの結果
    
header("Location:${pageError}");
}elseif(
$nomessage){                            //メッセージなしのclapは$pctoのアドレスへ
    
if(mail($pcto$subject$body$heady)){
        
clapHtml($name_html,$message_html,$option_html);
    }
}else{                                            
//googlebotなどの非clapeerへの表示
    
returnError("あなたがどなたが存じませんがclap!するときはフォームからどうぞ♪");
}
?>

thanks.html

<?php
/* info
-----------------------------------------------
Ore-Clap! お礼ページ for general
FileName: thanks.html
Build:    2005.12.13
Author:   hachiman_cian (八満とシアン)
-----------------------------------------------
解説
${random}……ランダムに決まる数字です。メッセージの数で範囲が決まります。
${thanksMessage}……ランダムに表示されるメッセージです。
${name_html}……clap!した人の名前です。『${name_html}おにいさま大好き』などと自由に応用可能。
${message_html}……メッセージ本文です。いじり甲斐はたぶんありません。
${option_html}……オプションです。同上。
----------------------------------------------- */
//下のecho<<<_HTML_より下をhtmlで自由に編集してください。
echo<<<_HTML_
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=Shift_JIS">
    <title>
${name_html}おにいさま、clap!痛み入ります</title>
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT">
</head>
<body>
<h1><img src="image/
${random}.png" alt="${thanksMessage}" title="${thanksMessage}"></h1>
<table class="table_body" border="0" cellspacing="4" cellpadding="4">
<caption>
${thanksMessage}</caption>
<tr>
    <th>clap!してくださった方</th>
    <td>
${name_html}さん</td>
</tr>
<tr>
    <th>clap!のメッセージ</th>
    <td>
${message_html}</td>
</tr>
_HTML_;
//これより下はオプションがある場合に表示される部分です。
//下のecho<<<_EOD_より下をhtmlで自由に編集してください。
if(${option_html}){
echo<<<_EOD_
<tr>
    <th>備考</th>
    <td>
        <ol>
            <li>
${option_html}</li>
        </ol>
    </td>
</tr>
_EOD_;
//ここまで
}
//これより下は通常表示部分です。
//下のecho<<<_HTML_より下をhtmlで自由に編集してください。
echo<<<_HTML_
</table>

<form>
    <input type="button" value="  1つ前のページへ戻る  " onclick="history.back()">
</form>


</body>
</html>
_HTML_;
//↑↓消すと大変なことになります。
?>

test.html(送信フォーム例)

<form action="http://www.dabun-doumei.com/clap/test/oreClap.php" method="post">
<fieldset>
<legend>通常clap!</legend>
<dl>
    <dt><input type="text" name="name" value="お名前をどうぞ" /></dt>
    <dd><textarea name="message" cols="40" rows="5"></textarea></dd>
    <dd><input type="hidden" name="clap" value="on" /></dd>
    <!-- ↑のかわりに<input type="hidden" name="clap" value="renda" />とすればメールは届きません -->
</dl>
</fieldset>
<fieldset>
<legend>ローゼンメイデンに関するアンケート</legend>
<ol>
<li>
    好きな薔薇乙女 :: 
        <label for="q1_1"><input type="checkbox" name="opt[好きな薔薇乙女multi][]" value="真紅" id="q1_1" />真紅</label>
        <label for="q1_2"><input type="checkbox" name="opt[好きな薔薇乙女multi][]" value="水銀燈" id="q1_2" />水銀燈</label>
        <label for="q1_3"><input type="checkbox" name="opt[好きな薔薇乙女multi][]" value="翠星石" id="q1_3" />翠星石</label>
        <label for="q1_4"><input type="checkbox" name="opt[好きな薔薇乙女multi][]" value="蒼星石" id="q1_4" />蒼星石</label>
</li>
<li>
    嫌いな薔薇乙女 :: 
        <label for="q2_1"><input type="radio" name="opt[嫌いな薔薇乙女]" value="雛苺" id="q2_1" />雛苺</label>
        <label for="q2_2"><input type="radio" name="opt[嫌いな薔薇乙女]" value="金糸雀" id="q2_2" />金糸雀</label>
        <label for="q2_3"><input type="radio" name="opt[嫌いな薔薇乙女]" value="薔薇水晶" id="q2_3" />薔薇水晶</label>
</li>
<li>
    翠星石と蒼星石は姉弟ですよね!? :: 
        <input type="text" name="opt[翠星石と蒼星石は姉弟ですよね!?]" />
</li>
<li>
    沢城みゆきといえば :: 
        <select name="opt[沢城みゆきといえば]">
            <option value="ミントたん" selected="selected">ミント・ブラマンシュ</option>
            <option value="真紅">真紅</option>
            <option value="チコ">チコ(トップをねらえ2)</option>
        </select>
</li>
</ol>
</fieldset>
<fieldset>
<legend>以上の内容で</legend>
    <input type="submit" value="送信してみる">
</fieldset>
</form>

error.html(エラー例)

<?php
/* info
-----------------------------------------------
Ore-Clap! エラーページ for general
FileName: thanks.html
Build:    2005.12.15
Author:   hachiman_cian (八満とシアン)
-----------------------------------------------
解説
${error}……エラーのメッセージです。
既に『メッセージがありません』というメッセージが設定されていますが、
これはoreClapAD.phpの199行目あたりで変更できます。
----------------------------------------------- */
//下のecho<<<_HTML_より下をhtmlで自由に編集してください。
echo<<<_HTML_
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=Shift_JIS">
    <title>超俺clap! ERROR:
${error}</title>
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT">
</head>
<body>

<h1>
${error}</h1>

<form>
    <input type="button" value="  1つ前のページへ戻る  " onclick="history.back()">
</form>


</body>
</html>
_HTML_;
//←↓消すと大変なことになります。
?>

プチリファレンス?

以下、12/18の管理人近況より超俺clap!に関した部分を抜粋しました。

超俺clap!ソース公開。 なお配布できるようなレベルではないので持ち出しは厳禁ということで。 くわえまして『ここはどうなってるの?』『設置したいけれどわからない』というご質問はご勘弁願います。 そのかわり“評価(してほしい)版”ということで『ここはああしたほうがいい』『あそこは間違ってるから直さないと』といったご意見はよろこんでお受けします(ワガママな!)。 ただすべてにお応えできる自信と時間があるかは……あわただしいこんな時期の公開ですみませんです。 [追記]やっぱり『ここはどうなってるの?』ギモンもお受けします(お答えできる範囲で+まとめてお返事というカタチですが)

とりあえず自己ツッコみを。 アンケート集計機能をつけるならほぼビフォーアフター並のリフォームを迫られそうです。 たぶんfunctionを1つ増やすくらいで対応できそうですが、ほかのfunctionの部分も変えなきゃならないということで腰が上がりません。 くわえましてメールでの文字化けを確認しています、がログのほうは文字化けの恐れがありませんので無視することにします。 またこの超俺clap!の原型は『PHP Web Mailer MIME B by ToR (http://php.s3.to)』であることをここに明記しておきます。メールへの文字変換をそっくり拝借しています。 あと多次元の連想配列の正しい処理の仕方をご存知の方は是非ツッコみを。たぶんもっとスマートな方法があるはずです。

最初はもっとシンプルだったんですけれど、 途中途中でいろいろと仕様の変更がありましたのでGetBackersでいうところの裏新宿のような様相を呈しています。 つぎきちんとした配布版をつくるならたぶんまたイチからだろうな……。

追加予定機能。といってもまだ配布するかどうかは本当に決めかねていますが……だって時間が(以下禁句←3日あたり前の近況を参照)。

  1. ログの書き込みを昇順/降順(+個別にIDをふる)に変えられる
  2. アンケート集計(項目ごとにファイルを生成するかデータベース書き込みか)
  3. rss配信(完全な自己満足+適当に言ってみました)
  4. cookieのオマケ(○○回目のclap〜←一番実現可能性が高いというか数行加えるだけ)
  5. お礼絵モードかお礼文章モード(小説サイトの方でも使えるように)
  6. ○通たまってはじめて送信する(ログの書き込み〜と同時に実現できそう)
  7. 一定量以上たまったらログを入れ替える(同上/肥大化防止)
  8. 即時公開モード(っていいますかこれじゃ掲示板じゃないですか)

アイディアだけ出したのであとは以上の機能を追加したヤツを僕に送りつけていただければたぶん最強です。 僕苦せずして完成、みたいな! ……とはいえこういうのの書式って人それぞれ違いますからうまくいかないでしょうけれども。 まぁそんなことで。興味のある方は自己責任でお持ち帰りになっていろいろ実験してみてください。なお実戦投入する場合は、そのいろいろ頑張ってください(問題はないとは思いますが……)。 著作権などに関しては意識してないのでそのあたりも自己判断でどうぞ。僕としては<a href="http://www.dabun-doumei.com/" title="あたらしめなメッセージフォームのカタチ">超俺clap! :: Chao!Ore-Clap!! ver.1.02</a>的な表記があれば超満足です。 ただ繰り返しますが配布版ではないので……あまりこのはずかしぃプログラムを世に出さないでください……(恒常的に置くのではなく、たとえば日記などで『設置してみました。どうぞ』といったカタチで使うのは全然構いません)。 あ、配布版を完成させられなかったときはこの公開版は完全に放棄しますので、超使いたいという方はそこを拾ってくだされば。

超俺clap! :: Chao!Ore-Clap!! ver.1.02