rtoss - Blame information for rev 45

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 roytam 1 <?php
2 /*
3  * tropy.php - PHP version of tropy.cgi
4  *
5  * # tropy.cgi - Version 20051105.
6  * #
7  * # Copyright (C) 2005 by Hiroshi Yuki.
8  * # <hyuki@hyuki.com>
9  * # http://www.hyuki.com/tropy/
10  * #
11  * # This program is free software; you can redistribute it and/or
12  * # modify it under the same terms as Perl itself.
13  */
14  
15 /* Config section */
16  
44 roytam 17 $thisurl_absolute = 'http://'.$_SERVER['HTTP_HOST'].preg_replace('/'.preg_replace('/.*\/+/','',$_SERVER['PHP_SELF']).'$/','',$_SERVER['PHP_SELF']); //Auto Setting
2 roytam 18 $site_name = 'Tropy';
19 $dir_html = 'html'; # Directory for Cached HTML files.
20 $dir_files = 'files'; # Directory for user-written text files and the index file.
21 $file_index = "$dir_files/index.txt";
22 $tropy_self = 'tropy.php';
23 /******************/
24 $sendmail = 0;
25 $adminmail = "";
26 # $adminmail = 'somebody@example.com';
27 $maxidlen = 8;
44 roytam 28 $id_pattern = '[0-9]{'.$maxidlen.'}';
2 roytam 29 $maxlength = 1000;
30 $maxlines = 20;
31 $maxcols = 80;
32 $maxrows = $maxlines;
33 $maxtitle = $maxcols - 3;
34 $maxpages = 10000;
35 $session_digest = md5(microtime().uniqid('Tropy',true));
36 $random_seed = hexdec(substr($session_digest, 0, 8));
37 $create_id = substr(sprintf("%0${maxidlen}u", $random_seed), 0, $maxidlen);
44 roytam 38 $time_visible_msec = '3000';
39 $time_jumpto_sec = '3';
40 $content_type = 'Content-type: text/html; charset=utf-8\n\n';
2 roytam 41 $allow_rebuild = 1;
42 $allow_toc = 1;
43 $allow_html = 0;
44 $show_plink = 1;
45 $auto_link = 1;
46 $allow_edit = 1;
44 roytam 47 $return_url='../';
2 roytam 48 $form=array_merge($_GET,$_POST);
49 $allid=array();
50  
51 main();
52 exit(0);
53  
54 function main() {
55         global $main_command,$form,$id_pattern,$random_seed,$allow_toc,$allow_rebuild,$show_plink,$allid;
56  
57         # Random init.
58         srand($random_seed);
59         rand(); rand(); rand();
60         TIEHASH();
61  
62         foreach ($form as $key => $val) {
44 roytam 63                 if (preg_match('/^c$/',$key)) {
2 roytam 64                         $main_command = 'create';
65                         do_create();
66                         break;
44 roytam 67                 } elseif (preg_match('/^e('.$id_pattern.')$/',$key,$matches)) {
2 roytam 68                         $main_command = 'edit';
69                         do_edit($matches[1]);
70                         break;
44 roytam 71                 } elseif (preg_match('/^w('.$id_pattern.')$/',$key,$matches)) {
2 roytam 72                         $main_command = 'write';
73                         do_write($matches[1]);
74                         break;
44 roytam 75                 } elseif (preg_match('/^toc$/',$key)) {
2 roytam 76                         if ($allow_toc) {
77                                 $main_command = 'toc';
78                                 $show_plink=0;
79                                 show_toc();
80                         }
81                         break;
44 roytam 82                 } elseif (preg_match('/^rebuild$/',$key)) {
2 roytam 83                         if ($allow_rebuild) {
84                                 foreach ($allid as $id => $val) {
44 roytam 85                                         if (preg_match('/^'.$id_pattern.'$/',$id)) {
2 roytam 86                                                 unlink_html($id);
87                                                 build_html($id);
88                                         }
89                                 }
90                         }
91                 }
92         }
93         if (! $main_command) {
94                 $main_command = 'random';
95                 do_random();
96         }
97 }
98  
99 function do_edit($id) {
100         global $main_command,$allid,$show_plink;
101         if ($main_command == 'create' || isset($allid[$id])) {
102                 $show_plink=0;
44 roytam 103                 $title = isset($allid[$id]) ? get_subject($id) : 'New Page';
2 roytam 104                 print_header($id, $title);
105                 print_editform($id, @implode('',FETCH($id)));
106                 echo get_footer();
107         } else {
44 roytam 108                 print_error('edit non id');
2 roytam 109         }
110 }
111  
112 function print_editform($id,$msg) {
113         global $maxrows,$maxcols,$tropy_self;
114         $mymsg = htmlspecialchars($msg);
115         echo <<<EOD
116   <form action="$tropy_self" method="post">
117         <input type="hidden" name="w$id" value="1">
118         <textarea cols="$maxcols" rows="$maxrows" name="mymsg">$mymsg</textarea><br><input type="submit" value="Write">
119   </form>
120 EOD;
121 }
122  
123 function do_write($id) {
124         global $form,$maxlength,$maxlines,$maxpages,$allid;
125         $msg = $form['mymsg'];
44 roytam 126         $msg = preg_replace('/\n+$/',"\n",$msg);
2 roytam 127         $msglen = strlen($msg);
128         $cr = $msglen -  strlen(str_replace("\n","",$msg));
129  
130         if ($maxpages < count($allid)) {
131                 DELETE_random_page();
132         }
133  
134         if ($msglen > $maxlength) {
135                 print_header($id, "length > $maxlength");
136                 print_editform($id, $msg);
137                 echo get_footer();
138         } elseif ($cr >= $maxlines) {
139                 print_header($id, "lines > $maxlines");
140                 print_editform($id, $msg);
141                 echo get_footer();
142         } else {
143                 if ($form['mymsg']) {
45 roytam 144  
145                         // =date -> real date
146                         $msg = preg_replace('/=date/i',date('r'),$msg);
147  
2 roytam 148                         STORE($id,$msg);
149                         send_mail($id, get_subject($id), 'edit', $msg);
150                         unlink_html($id);
151                         build_html($id);
152                         print_jumpto($id);
153                 } else {
154                         send_mail($id, get_subject($id), 'delete', FETCH($id));
155                         DELETE($id);
156                         unlink_html($id);
157                         do_random();
158                 }
159         }
160 }
161  
162 function delete_random_page() {
163         $id = get_random_id();
164         DELETE($id);
165         unlink_html($id);
166 }
167  
168 function print_jumpto($id) {
169         global $content_type,$time_jumpto_sec,$thisurl_absolute,$dir_html,$site_name;
44 roytam 170         $meta = "<meta http-equiv='refresh' content='$time_jumpto_sec; url=${thisurl_absolute}${dir_html}/${id}.html'>\n";
171         $navi = '<div id="navi"></div>';
2 roytam 172         header($content_type);
44 roytam 173         header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
2 roytam 174         echo get_header("$site_name...", "", 'black', 'white', $navi, $meta);
175         echo get_footer();
176 }
177  
178 function print_error($msg) {
179         $msg = htmlspecialchars($msg);
180         print_header(null, '?');
181         echo "<h1>$msg</h1>";
182         echo get_footer();
183         exit(0);
184 }
185  
186 function print_header($id,$title) {
187         global $content_type,$form,$site_name,$allow_edit;
188         list($color, $bgcolor) = get_style($id);
189         $navi = get_navi($id, $allow_edit);
190         header($content_type);
191         echo get_header("$title - $site_name", $title, $color, $bgcolor, $navi, "");
192 }
193  
194 function get_navi($id, $editable) {
195         global $tropy_self,$allow_toc,$show_plink,$return_url,$dir_html;
196         $mod = 17;
197         $random_url = "$tropy_self";
198         if ($id % $mod > 0) {
199                 for ($x=1;$x<$mod * 3;$x++) {
200                         $nextid = get_random_id();
201                         if (($id + 1) % $mod == $nextid % $mod) {
202                                 # Found.
203                                 $random_url = "$dir_html/$nextid.html";
204                                 break;
205                         }
206                 }
207         }
208         $return = $return_url ? "<a href='$return_url' title='Return to Home'>Return</a>" : '';
209         $toc = $allow_toc ? "<a href='$tropy_self?toc' title='Table of Contents'>TOC</a>" : '';
210         $edit = $editable ? "<a href='$tropy_self?e$id' title='Edit this tropy'>Edit</a>" : '';
211         $create = "<a href='$tropy_self?c' title='Create new tropy'>Create</a>";
212         $random = "<a href='$random_url' title='Jump to random tropy'>Random</a>";
213         $plink = $show_plink ? "<a href='$dir_html/$id.html' title='Permalink of this tropy'>Permalink</a>" : '';
214         return "<p id='navi'>$return $toc $edit $create $random $plink</p>";
215 }
216  
217 function do_random() {
218         global $id_pattern,$main_command,$id_pattern;
219         $random_id = get_random_id();
44 roytam 220         if (preg_match('/^'.$id_pattern.'$/',$random_id)) {
2 roytam 221                 build_html($random_id);
222                 print_jumpto($random_id);
223         } else {
224                 $main_command = 'create';
225                 do_create();
226         }
227 }
228  
229 function get_random_id() {
230         global $allid;
231         $id = array_keys($allid);
232         $rid = array_rand($id);
233         return isset($id[$rid])?$id[$rid]:null;
234 }
235  
236 function unlink_html($id) {
237         global $dir_html;
238         @unlink("$dir_html/$id.html");
239 }
240  
241 function build_html($id) {
242         global $dir_html,$allow_html,$site_name,$allow_edit,$auto_link;
243         list($color, $bgcolor) = get_style($id);
244         $navi = get_navi($id, $allow_edit);
245  
246         # Check.
247         if (file_exists("$dir_html/$id.html")) {
248                 return;
249         }
250  
251         # Read.
252         $fil=FETCH($id);
253         $caption=array_shift($fil);
254         $caption=rtrim(htmlspecialchars($caption));
255         $content = implode('',$fil);
44 roytam 256  
2 roytam 257         if (!$allow_html) {
258                 $content = htmlspecialchars($content);
44 roytam 259  
260                 if (strpos(strtolower($content),'=nbsp\n') !== -1) {
261                         $content = preg_replace('/=nbsp\n/i','',$content);
262                         $content = str_replace(' ','&nbsp;',$content);
263                 }
45 roytam 264                 $content = preg_replace("/=pre\n?/i",'<pre>',$content);
265                 $content = preg_replace('/=\/pre\n?/i','</pre>',$content);
44 roytam 266  
267                 $content = preg_replace('/(\n\n+)/',"\n\n",$content);
45 roytam 268                 $content = str_replace("\n\n",'</p><p>',$content);
269                 $content = str_replace("\n",'<br />',$content);
2 roytam 270         }
44 roytam 271         if ($auto_link) $content = preg_replace('/(https?|ftp|news)(\:\/\/[[:alnum:]\+\$\;\?\.%,!#~*\/\:@&=_-]+)/i','<a href="$1$2" target="_blank">$1$2</a>',$content);
2 roytam 272  
273         # Write.
274         if (!$wfil=fopen("$dir_html/$id.html","wb")) {
275                 print_error("build to $id");
276         }
277         fwrite($wfil,get_header("$caption - $site_name", $caption, $color, $bgcolor, $navi, ""));
278         fwrite($wfil,"<p>$content</p>");
279         fwrite($wfil,get_footer());
280         fclose($wfil);
281 }
282  
283 function show_toc() {
284         global $dir_html,$site_name,$allow_edit,$auto_link,$allid;
285         $content='';
286  
287         # Read.
288         foreach ($allid as $id => $val) {
289                 $fil=FETCH($id);
290                 $caption=array_shift($fil);
291                 $caption=rtrim(htmlspecialchars($caption));
292                 $content.="<a href='$dir_html/$id.html'>$id - $caption</a><br />";
293         }
294  
44 roytam 295         echo get_header("TOC - $site_name", 'Table Of Contents', 'black', 'white', get_navi(null,0), '');
2 roytam 296         echo "<p>$content</p>";
297         echo get_footer();
298 }
299  
300 function get_header($title, $caption, $color, $bgcolor, $navi, $meta) {
301         global $time_visible_msec,$thisurl_absolute;
302         return <<<EOD
303 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
304    "http://www.w3.org/TR/html4/loose.dtd">
305 <html lang="ja">
306 <head>
307 <meta http-equiv="content-type" content="text/html; charset=utf-8">
308 <meta http-equiv="content-style-type" content="text/css">
309 $meta<base href="$thisurl_absolute">
310 <style type="text/css"><!--
311 body{font-family:Verdana,sans-serif;margin:2% 20% 10% 20%;color:$color;background-color:$bgcolor;}
312 input{font-family:Verdana,sans-serif;}
313 #navi{text-align:right;}
314 p{line-height:150%;}
315 a{color:gray;background-color:$bgcolor;text-decoration:none;}
316 a:hover{text-decoration:underline;color:white;background-color:gray;}
317 --></style>
318 <script type="text/javascript">
319 <!--
320 function onLoad(){
321   document.getElementById("navi").style.visibility="hidden";
322   setTimeout("onTimeout()", $time_visible_msec);
323 }
324 function onTimeout(){
325   document.getElementById("navi").style.visibility="visible";
326 }
327 // -->
328 </script>
329 <title>$title</title>
330 </head>
331 <body onLoad="onLoad()">
332 $navi<h1>$caption</h1>
333 EOD;
334 }
335  
336 function get_footer() {
337         return "</body></html>\n";
338 }
339  
340 function send_mail($pagename, $subject, $mode, $content) {
341         global $sendmail,$adminmail,$allid;
342         if(!$sendmail) return;
343         $pages = count($allid);
344         $header = <<<EOD
345 To: $adminmail
346 From: $adminmail
347 Subject: [Tropy/$mode] $subject
348 MIME-Version: 1.0
349 Content-type: text/plain; charset=UTF-8
350 Content-Transfer-Encoding: 8bit
351 EOD;
352  
353         $message = <<<EOD
354 --------
355 MODE = $mode
356 REMOTE_ADDR = $_SERVER[REMOTE_ADDR]
357 REMOTE_HOST = $_SERVER[REMOTE_HOST]
358 --------
359 ${thisurl_absolute}$pagename.html
360 --------
361 $content
362 --------
363 pages = $pages
364 --------
365 EOD;
366         mail($adminmail,"[Tropy/$mode] $subject",$message,$header);
367 }
368  
369 function get_style($id) {
370         global $main_command;
371         list($color, $bgcolor) = array('black', 'white');
372         if ($main_command != 'create') {
373                 $digest = md5($id);
374                 $range = 32;
375                 $r = 255 - (hexdec(substr($digest, 0, 2)) % $range);
376                 $g = 255 - (hexdec(substr($digest, 2, 2)) % $range);
377                 $b = 255 - (hexdec(substr($digest, 4, 2)) % $range);
378                 $color = 'black';
44 roytam 379                 $bgcolor = sprintf('#%02X%02X%02X', $r, $g, $b);
2 roytam 380         }
381         return array($color, $bgcolor);
382 }
383  
384 function do_create() {
385         global $create_id;
386         do_edit($create_id);
387 }
388  
389 function get_subject($id) {
390         global $maxtitle;
391         $item=FETCH($id);
44 roytam 392         if (preg_match('/^(.*)/',$item[0],$matches)) {
2 roytam 393                 $caption = $matches[1];
394                 if (strlen($caption) > $maxtitle) {
44 roytam 395                         $caption = preg_replace('/^(.{'.$maxtitle.'}).*/','$1...',$caption);
2 roytam 396                 }
397                 return htmlspecialchars($caption);
398         } else {
399                 return "";
400         }
401 }
402  
403 function TIEHASH() {
404         global $file_index,$allid;
405         _make_index();
406         $keys = array_map('rtrim',file($file_index));
407         foreach($keys as $v) if($v) $allid[$v]=1;
408 }
409  
410 function STORE($id, $value) {
411         global $file_index,$dir_files,$id_pattern,$allid;
44 roytam 412         if (!preg_match('/^('.$id_pattern.')$/',$id)) {
2 roytam 413                 die("store nonid");
414         }
415  
416         # Replace file.
417         $filename = "$dir_files/$id.txt";
418         if (!$fil= fopen("$filename","wb")) {
419                 die("store $id file");
420         }
421         fwrite($fil,str_replace("\r\n","\n",$value));
422         fclose($fil);
423  
424         # Append $id.
425         if (!isset($allid[$id])) {
426                 if (!$idx= fopen("$file_index","a")) {
44 roytam 427                         die('store index');
2 roytam 428                 }
429                 fwrite($idx,"$id\n");
430                 fclose($idx);
431                 $allid[$id] = 1;
432         }
433  
434         return $value;
435 }
436  
437 function FETCH($key) {
438         global $file_index,$dir_files;
439         $filename = "$dir_files/$key.txt";
440         return @file($filename);
441 }
442  
443 function DELETE($key) {
444         global $file_index,$dir_files,$allid;
445         $filename = "$dir_files/$key.txt";
446         unlink($filename);
447         unset($allid[$key]);
448  
449         # Write index.
450         $id = array_keys($allid);
44 roytam 451                 if (!$idx= fopen("$file_index",'wb')) {
2 roytam 452                 die("delete index");
453         }
454         fwrite($idx,implode("\n", $id)."\n");
455         fclose($idx);
456 }
457  
458 function _make_index() {
459         global $file_index,$dir_files,$id_pattern;
460         if (file_exists($file_index)) {
461                 return;
462         }
463         if (!$di=opendir($dir_files)) {
44 roytam 464                 print_error('build index dir');
2 roytam 465         }
466         $index=array();
467         $entry='';
468         while ($entry = readdir($di)) {
44 roytam 469                 if (preg_match('/^('.$id_pattern.')\.txt$/',$entry,$matches)) {
2 roytam 470                         $id = $matches[1];
471                         if (-s("$dir_files/$id.txt") > 0) {
472                                 $index[]=$id;
473                         }
474                 }
475         }
476         closedir($di);
477         if (!$idx=fopen("$file_index","wb")) {
44 roytam 478                 print_error('build index open');
2 roytam 479         }
480         fwrite($idx,implode("\n", $index)."\n");
481         fclose($idx);
482 }
483  
44 roytam 484 ?>