50行PHPスクリプト1枚 だけ で動かす超シンプルチャット - 肉とビールとパンケーキ by @sotarok ってあったので、半年前作って*1忘れてたのをアップ。
ポイントってほどでもないが携帯対応。ただ、mod_rewriteを使うので.htaccessも必要。なんでこんな仕様にしたかは忘れた。
あと、仕様として
- TSV形式の設定ファイル重要
- TSV設定ファイルのファイル名を知らないとアクセスできない
- 逆にURLさえ知ってれば管理者権限(だから、仲間内うちでしかできない)
- あまりに単機能なので脆弱性とか無いはず(仕様を守ってる限り)*2
.htaccessは
http://www.junoe.jp/m/itoh/tasks/.htaccess
において、
RewriteCond %{REQUEST_URI} !^/(m/itoh/tasks/entrypoint.php|.*/static)/
RewriteRule ^(.*)$ /m/itoh/tasks/entrypoint.php/$1 [L]
って書く。
で、PHPファイル
http://www.junoe.jp/m/itoh/tasks/entrypoint.php
<?php header('Content-Type: text/html; charset=Shift_JIS'); $now = time() + 86400 * 1; $root_url = sprintf('http://%s%s', $_SERVER['SERVER_NAME'], dirname($_SERVER['SCRIPT_NAME'])); $event_url = $params = get_params(); if (is_post_method()){ save_data($params); } $data = load_data($params); ?> <html> <head> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="Content-Type" content="text/html" charset="Shift_JIS" /> <title>[Chotaro]<?php echo $data['label'][0]?></title> </head> <body> <a name="top"></a> <a href="#bottom" accesskey="8">[8]bottom</a><br> <a href="<?php printf('%s/help/%s', $root_url, $params['event_id'])?>">使い方</a><br> <form action="<?php printf('%s/%s/%s', $root_url, $params['event_id'], $params['user_id'])?>" method="post"> <center><?php printf('<a href="%s/%s">[%s]</a>', $root_url, $params['event_id'], $data['label'][0])?></center> <?php if($params['user_id']){ printf('<input type="submit" value="%sの予定変更"><br>', $params['user_id']); } /* print label */ echo str_repeat(' ', 5); foreach ($data['label'] as $lk=>$l){ if ($lk==0) continue; printf(' <a href="%s/%s/%s">%s</a>', $root_url, $params['event_id'], $l, substr($l,0,1))."\n"; } echo "<br>"; foreach ($data['data'] as $day=>$d){ if ($day < $now){ continue; } $w = date('w', $day); $format = $w==0 ? "<font color='#ff0000'>%s </font>" : ($w==6 ? "<font color='#0000ff'>%s </font>" : "%s ") ; $day_str = date('md', $day); printf($format, $day_str); foreach ($d as $rk=>$r){ if ($params['user_id'] == $data['label'][$rk+1]){ printf('<input type="checkbox" name="check[%s]" value="1"%s> ', $day_str, $r?' checked':''); } else { printf('%s ', $r ? 'o' : 'x'); } } echo "<br>\n"; } if($params['user_id']){ printf('<input type="submit" value="%sの予定変更"><br>', $params['user_id']); } ?> </form> <a href="#top" accesskey="2">[2]top</a><br> <a name="bottom"><?php echo date('Y/n/j H:i')?></a></body></html> <?php //////////////////////////////////////////////////////////// function get_params() { $params = array(); if (isset($_SERVER['PATH_INFO'])){ $pathinfo = explode('/', trim($_SERVER['PATH_INFO'], '/')); if (count($pathinfo)>=1){ $params['event_id'] = $pathinfo[0]; $params['user_id'] = isset($pathinfo[1]) ? $pathinfo[1] : ''; } } if (count($params)==2){ return $params; } exit('invalid path'); } function save_data($params) { $file = get_file($params); $data = load_data($params); if (!isset($_POST['check']) || !is_array($_POST['check'])){ $_POST['check'] = array(); } $user_key = array_search($params['user_id'], $data['label']); if ($user_key!==false && $user_key>0){ $user_key--; foreach ($data['data'] as $dday=>$dd){ $dday_str = date('md', $dday); if (isset($dd[$user_key])){ $data['data'][$dday][$user_key] = array_key_exists($dday_str , $_POST['check']) ? 1 : ''; } } /// write in file if ($fp = fopen($file, 'w')){ fputs($fp, implode("\t", $data['label'])."\n"); foreach ($data['data'] as $dday=> $dd){ fputs($fp, sprintf("%s\t%s\n", date('Y/n/j', $dday), implode("\t", $dd))); } fclose($fp); } else { exit('cannot write file.'); } } } function load_data($params) { $label = array(); $data = array(); $file = get_file($params); foreach (file($file) as $k=>$line){ $d = explode("\t", trim($line, "\r\n")); if ($k==0){ $label = $d; } else { if (count($d) == count($label)){ $date = strtotime(array_shift($d)); $data[$date] = $d; } } } $ret = array('label' => $label, 'data' => $data); return $ret; } function get_file($params) { $file = sprintf('%s/cache/%s.tsv', dirname(__FILE__), $params['event_id']); if (file_exists($file)){ return $file; } if ($params['event_id']=="help"){ require dirname(__FILE__)."/static/help.html"; exit; } exit('cannot exists file.'); } function is_post_method() { return strcasecmp($_SERVER['REQUEST_METHOD'], 'post')===0; } function h($s) { return htmlspecialchars($s, ENT_QUOTES); }
んで、TSVファイルには
サンプル飲み会 itoh minmin foo bar uki hoge
2009/6/1
2009/6/2
2009/6/3
2009/6/4
2009/6/5
2009/6/6
2009/6/7
2009/6/8
みたいに、一行目にイベント名と参加者一覧を書く。
ファイル権限を666にする。
TSVファイル名が重要
さっきのサンプルの場合はTSVファイル名がsampleevent.tsvなので
http://www.junoe.jp/m/itoh/tasks/sampleevent
にアクセスする。
結論
設置が面倒。環境依存でかいし。この辺をなくそうと思って思ってるうちに忘却してたんだ。