]> bicyclesonthemoon.info Git - ott/bsta/blob - viewer.1.pl
Adapted for new config tool.
[ott/bsta] / viewer.1.pl
1 ###RUN_PERL: #!/usr/bin/perl
2
3 # /bsta/v
4 # viewer is generated from viewer.1.pl.
5 #
6 # The viewer interface
7 #
8 # Copyright (C) 2016-2017, 2019-2020, 2023  Balthasar SzczepaƄski
9 #
10 # This program is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU Affero General Public License as
12 # published by the Free Software Foundation, either version 3 of the
13 # License, or (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU Affero General Public License for more details.
19 #
20 # You should have received a copy of the GNU Affero General Public License
21 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23 use strict;
24 #use warnings;
25 ###PERL_LIB: use lib /botm/lib/bsta
26 use bsta_lib qw(failpage gethttpheader getcgi entityencode readdatafile writedatafile printdatafileht urlencode bb2ht bb2bb linehtml);
27 use File::Copy;
28
29 ###PERL_CGI_PATH:           CGI_PATH           = /bsta/
30 ###PERL_CGI_ATTACH_PATH:    CGI_ATTACH_PATH    = /bsta/a
31 ###PERL_CGI_BBCODE_PATH:    CGI_BBCODE_PATH    = /bsta/b
32 ###PERL_CGI_CSS_PATH:       CGI_CSS_PATH       = /bsta/bsta.css
33 ###PERL_CGI_FRAME_PATH:     CGI_FRAME_PATH     = /bsta/f
34 ###PERL_CGI_GOTO_PATH:      CGI_GOTO_PATH      = /bsta/g
35 ###PERL_CGI_INFO_PATH:      CGI_INFO_PATH      = /bsta/i
36 ###PERL_CGI_LOGO_PATH:      CGI_LOGO_PATH      = /bsta/botmlogo.png
37 ###PERL_CGI_TIMER_PATH:     CGI_TIMER_PATH     = /bsta/timer.js
38 ###PERL_CGI_VIEWER_PATH:    CGI_VIEWER_PATH    = /bsta/v
39
40 ###PERL_DATA_PATH:          DATA_PATH          = /botm/data/bsta/
41 ###PERL_DATA_DEFAULT_PATH:  DATA_DEFAULT_PATH  = /botm/data/bsta/default
42 ###PERL_DATA_LIST_PATH:     DATA_LIST_PATH     = /botm/data/bsta/list
43 ###PERL_DATA_NOACCESS_PATH: DATA_NOACCESS_PATH = /botm/data/bsta/noaccess
44 ###PERL_DATA_SETTINGS_PATH: DATA_SETTINGS_PATH = /botm/data/bsta/settings
45 ###PERL_DATA_STATE_PATH:    DATA_STATE_PATH    = /botm/data/bsta/state
46 ###PERL_DATA_STORY_PATH:    DATA_STORY_PATH    = /botm/data/bsta/story
47
48 ###PERL_WWW_PATH:           WWW_PATH           = /botm/www/1190/bsta/
49 ###PERL_WWW_INDEX_PATH:     WWW_INDEX_PATH     = /botm/www/1190/bsta/index.htm
50
51 ###PERL_WEBSITE:            WEBSITE            = 1190.bicyclesonthemoon.info
52 ###PERL_WEBSITE_NAME:       WEBSITE_NAME       = Bicycles on the Moon
53 ###PERL_FAVICON_PATH:       FAVICON_PATH       = /img/favicon.png
54
55 my %http;
56 my %cgi;
57 my %framedata;
58 my %nextframedata;
59 my %default;
60 my %settings;
61 my %state;
62 my %newstate;
63 my %gotolist;
64
65 my $time = time();
66 srand ($time-$$);
67
68 my $method;
69 my $frame;
70 my $password;
71 my $passwordOK;
72 my $IP;
73 my $access;
74 my $seconds;
75 my $minutes;
76 my $hours;
77 my $statefile;
78 my $showcommand;
79 my $ongtime;
80 my $textmode;
81
82 delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
83 ###PERL_SET_PATH: $ENV{'PATH'} = /usr/local/bin:/usr/bin:/bin;
84
85 if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
86         $method=$1;
87 }
88 else{
89         exit failpage("Status: 405 Method Not Allowed\nAllow: GET, POST, HEAD\n","405 Method Not Allowed","The interface does not support the $ENV{'REQUEST_METHOD'} method.",$method);
90 }
91
92 %http = gethttpheader (\%ENV);
93 %cgi = getcgi($ENV{'QUERY_STRING'});
94
95 if ($method eq 'POST') {
96         if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
97                 my %cgipost=getcgi( <STDIN> );
98                 foreach my $ind (keys %cgipost) {
99                         $cgi{$ind}=$cgipost{$ind};
100                 }
101         }
102         # multipart not supported
103         else{
104                 exit failpage("Status: 415 Unsupported Media Type\n","415 Unsupported Media Type","Unsupported Content-type: $http{'content-type'}.");
105         }
106 }
107
108 if ($ENV{'HTTP_X_FORWARDED_FOR'} =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
109         $IP=$1;
110 }
111 elsif ($ENV{'REMOTE_ADDR'} =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
112         $IP=$1;
113 }
114 else {
115         $IP='0.0.0.0';
116 }
117
118 if ($cgi{'f'} =~ /^(.+)$/) {
119         $frame=int($1);
120 }
121 elsif ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) {
122         $frame=int($1);
123 }
124 else {
125         $frame = 0;
126 }
127
128 if ($cgi{'p'} =~ /^(.+)$/) {
129         $password=$1;
130 }
131 else {
132         $password='';
133 }
134 # print "Content-type: text/plain\n\n";
135
136 %settings=readdatafile(DATA_SETTINGS_PATH);
137 %default=readdatafile(DATA_DEFAULT_PATH);
138 %framedata=readdatafile(DATA_PATH.$frame);
139 if($password eq $settings{'password'}){
140         $passwordOK = 1;
141 }
142 else{
143         $passwordOK = 0;
144 }
145
146 if (open ($statefile,"+<",DATA_STATE_PATH)){
147         if (flock($statefile,2)) {
148                 
149                 %state=readdatafile($statefile);
150                 
151                 if($frame<0) {
152                         $frame = int($state{'last'}) + $frame +1;
153                         %framedata=readdatafile(DATA_PATH.$frame);
154                 }
155                 
156                 if(int($state{'state'})==1 && $frame == int($state{'last'}) && $method ne 'HEAD' && !$passwordOK){
157                         my %newstate=%state;
158                         if($state{'ip1'} ne $IP) {
159                                 if ($state{'ip1'} eq '') {
160                                         $newstate{'ip1'} = $IP;
161                                         writedatafile($statefile,%newstate);
162                                 }
163                                 elsif($state{'ip2'} ne $IP) {
164                                         if ($state{'ip2'} eq '') {
165                                                 $newstate{'ip2'} = $IP;
166                                                 writedatafile($statefile,%newstate);
167                                         }
168                                         else {
169                                                 $newstate{'state'}=2;
170                                                 $newstate{'ip3'} = $IP;
171                                                 writedatafile($statefile,%newstate);
172                                         }
173                                 }
174                         }
175                 }
176                 elsif(int($state{'state'})==0 && $frame == 1) {
177                         my %story;
178                         my $inpath;
179                         my $outpath;
180                         
181                         %story = readdatafile(DATA_STORY_PATH);
182                         %gotolist=readdatafile(DATA_LIST_PATH);
183                         if(int($story{'state'}) == 17 && int($story{'pass'}) == 1) {
184                                 #ACTIVATE!
185                                 
186                                 $framedata{'ongtime'} = $time;
187                                 writedatafile(DATA_PATH.$frame,%framedata);
188                                 $state{'state'} = 1;
189                                 $state{'last'} = 1;
190                                 $state {'ip1'} = '0.0.0.0';
191                                 $state {'ip2'} = '0.0.0.0';
192                                 $state {'ip3'} = '';
193                                 $state {'nextong'} = (int($time / 3600) + int($settings{'firstongtime'})) * 3600 ;
194                                 $state{'ongtime'} = int($settings{'firstongtime'});
195                                 
196                                 unless(defined($framedata{'ext'})){
197                                         $framedata{'ext'}=$default{'ext'};
198                                 }
199                                 
200                                 $inpath = DATA_PATH.sprintf($settings{'frame'},$frame,$framedata{'ext'});
201                                 $outpath = WWW_PATH.sprintf($settings{'frame'},$frame,$framedata{'ext'});
202                                 
203                                 $gotolist{'title-1'}=$framedata{'title'};
204                                 $gotolist{'ongtime-1'}=$framedata{'ongtime'};
205                                 
206                                 if(copy ($inpath, $outpath)) {
207                                         writeindex(WWW_INDEX_PATH);
208                                         writedatafile($statefile,%state);
209                                         writedatafile(DATA_LIST_PATH,%gotolist);
210                                 }
211                                 else {
212                                         $state{'state'} = 0;
213                                 }
214                         }
215                 }
216         }
217         else {
218                 $state{'state'} = 0;
219         }
220         close ($statefile);
221 }
222 else {
223         $state{'state'} = 0;
224 }
225
226 %nextframedata=readdatafile(DATA_PATH.($frame+1));
227 foreach my $ind (keys %default) {
228         unless(defined($framedata{$ind})){
229                 $framedata{$ind}=$default{$ind};
230         }
231         unless(defined($nextframedata{$ind})){
232                 $nextframedata{$ind}=$default{$ind};
233         }
234 }
235
236 $hours=int($state{'nextong'})-$time;
237 $ongtime=int($state{'ongtime'});
238 if($ongtime == 0) {
239         $ongtime=int($settings{'ongtime'})
240 }
241
242 $showcommand = ($hours < ($ongtime*3600/3));
243 if($hours>0){
244         $seconds = sprintf('%02d',$hours % 60);
245         $hours = int($hours/60);
246         $minutes = sprintf('%02d',$hours % 60);
247         $hours = sprintf('%02d',int($hours/60));
248 }
249 elsif(($hours>=-15) && (int($state{'state'}) == 2)){
250         $seconds='NG';
251         $minutes='00';
252         $hours='00';
253 }
254 else{
255         $seconds='EE';
256         $minutes='EE';
257         $hours='EE';
258 }
259
260
261 if ($passwordOK || (int($state{'state'}) >= 1 && $frame <= int($state{'last'}) && $frame >= 0)) {
262         $access=1;
263 }
264 else {
265         $access=0;
266         %framedata = readdatafile(DATA_NOACCESS_PATH);
267         foreach my $ind (keys %default) {
268                 unless(defined($framedata{$ind})){
269                         $framedata{$ind}=$default{$ind};
270                 }
271         }
272 }
273
274 $textmode = int($cgi{'b'});
275 if($textmode > 2) {
276         $textmode = 0;
277 }
278
279 # print "Content-type: text/plain\n\n";
280 # print 'frame='.$frame."\n";
281 # print 'password='.$password."\n";
282 # print 'passwordOK='.$passwordOK."\n";
283 # print 'access='.$access."\n";
284 # print "\n>>>ENV<<<\n\n";
285 # foreach my $ind (keys %ENV) {
286         # print $ind.'='.$ENV{$ind}."\n";
287 # }
288 # print "\n>>>HTTP<<<\n\n";
289 # foreach my $ind (keys %http) {
290         # print $ind.': '.$http{$ind}."\n";
291 # }
292 # print "\n>>>CGI<<<\n\n";
293 # foreach my $ind (keys %cgi) {
294         # print $ind.'='.$cgi{$ind}."\n";
295 # }
296 # print "\n>>>FRAMEDATA<<<\n\n";
297 # foreach my $ind (keys %framedata) {
298         # print $ind.': '.$framedata{$ind}."\n";
299 # }
300 # print "\n>>>NEXTFRAMEDATA<<<\n\n";
301 # foreach my $ind (keys %nextframedata) {
302         # print $ind.': '.$nextframedata{$ind}."\n";
303 # }
304 # print "\n>>>SETTINGS<<<\n\n";
305 # foreach my $ind (keys %settings) {
306         # print $ind.': '.$settings{$ind}."\n";
307 # }
308 # print "\n>>>STATE<<<\n\n";
309 # foreach my $ind (keys %state) {
310         # print $ind.': '.$state{$ind}."\n";
311 # }
312
313 print "Content-type: text/html\n";
314 if(!$access) {
315         print "Status: 403 Forbidden\n";
316 }
317 print "\n";
318 if($method eq 'HEAD') {
319         exit;
320 }
321
322 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
323 print '<html lang="en"><head>'."\n";
324 print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
325 print '<title>';
326 unless($framedata{'title'} eq '' || $framedata{'title'} eq $settings{'story'}) {
327         print entityencode($framedata{'title'}).' &bull; ';
328 }
329 print entityencode($settings{'story'}).' &bull; '.WEBSITE_NAME.'</title>'."\n";
330 print '<link rel="icon" type="image/png" href="'.FAVICON_PATH.'">'."\n";
331 print '<link rel="stylesheet" href="'.CGI_CSS_PATH.'">'."\n";
332 print '<link rel="index" href="'.CGI_GOTO_PATH.($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
333 print '<link rel="start" href="'.CGI_VIEWER_PATH.'/0'.($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
334 if($frame>0 && $access) {
335         print '<link rel="prev" href="'.CGI_VIEWER_PATH.'/'.($frame - 1).($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
336 }
337 if ($passwordOK || $frame<int($state{'last'})) {
338         print '<link rel="next" href="'.CGI_VIEWER_PATH.'/'.($frame + 1).($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
339         print '<link rel="prefetch" href="'.CGI_VIEWER_PATH.'/'.($frame + 1).($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
340 }
341 if($frame==int($state{'last'}) && int($state{'state'}) >= 1 && int($state{'state'}) < 3) {
342         print '<!-- <script src="'.CGI_TIMER_PATH.'"></script> -->'."\n";
343 }
344 print '</head><body>'."\n";
345 print '<a href="/"><img id="botmlogo" src="'.CGI_LOGO_PATH.'" alt="'.WEBSITE.'"></a>'."\n";
346 print '<div id="all">'."\n";
347
348 print '<div id="inst" class="ins">'."\n";
349
350 print '<div id="title">'."\n";
351 print '<H1 id="titletext">'.entityencode($framedata{'title'}).'</H1>'."\n";
352 print '</div>'."\n";
353
354 print '</div><div id="framespace">'."\n";
355 if(!$access) {
356         print '<img src="'.CGI_PATH.$framedata{'frame'}.'" id ="frame" alt="'.$frame.'" title="'.entityencode($framedata{'title'}).'">'."\n";
357 }
358 else {
359         print'<img src="';
360         if($frame<=int($state{'last'}) && int($state{'state'}) >= 1) {
361                 print CGI_PATH.sprintf($settings{'frame'},$frame,$framedata{'ext'});
362         }
363         else {
364                 print CGI_FRAME_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'');
365         }
366         print '" id="frame" alt="'.$frame.'" title="'.entityencode($framedata{'title'}).'">'."\n";
367 }
368 print '</div><div id="insb" class="ins">'."\n";
369
370 if($textmode==2){
371         print '<div id="chat">'."\n";
372         
373         if ($passwordOK || $frame<int($state{'last'}) || (int($state{'state'}) >= 2 && $showcommand)) {
374                 $framedata{'command'}=$nextframedata{'title'};
375         }
376         if ($access) {
377                 $framedata{'frame'}=sprintf($settings{'frame'},$frame,$framedata{'ext'});
378         }
379         
380         printdatafileht(%framedata);
381         print '</div>'."\n";
382 }
383 elsif($textmode==1){
384         print '<div id="chat">'."\n";
385         print '[quote][center][size=200]'.entityencode($framedata{'title'}).'[/size]<br>'."\n";
386         print '[url=http://'.WEBSITE.CGI_VIEWER_PATH.'/'.$frame.'][img]http://'.WEBSITE.CGI_PATH.($access?sprintf($settings{'frame'},$frame,$framedata{'ext'}):$framedata{'frame'}).'[/img][/url][/center]<br>'."\n";
387         print bb2bbf($framedata{'content'}).'[/quote]</div>'."\n";
388 }
389 elsif($framedata{'content'} ne ''){
390         print '<div id="undertext">'."\n";
391         print bb2htf($framedata{'content'})."\n";
392         print '</div>'."\n";
393 }
394
395 print '<div id="command">'."\n";
396 if($frame==int($state{'last'}) && int($state{'state'}) >= 1 && int($state{'state'}) < 3) {
397         print '[<span id="ongh" class="';
398         if(int($state{'state'}) >= 2 || $state{'ip1'} ne '') {
399                 print 'br';
400         }
401         else {
402                 print 'ni';
403         }
404         print '">'.$hours.'</span>:<span id="ongm" class="';
405         if(int($state{'state'}) >= 2 || $state{'ip2'} ne '') {
406                 print 'br';
407         }
408         else {
409                 print 'ni';
410         }
411         print '">'.$minutes.'</span>:<span id="ongs" class="';
412         if(int($state{'state'}) >= 2 || $state{'ip3'} ne '') {
413                 print 'br';
414         }
415         else {
416                 print 'ni';
417         }
418         print '">'.$seconds.'</span>]<br>';
419 }
420 print '&gt;';
421 if (!$access){
422         print '<a href="'.CGI_VIEWER_PATH.'/-1">'.entityencode($framedata{'command'}).'</a><br>'."\n";
423 }
424 else {
425         if ($passwordOK || $frame<int($state{'last'}) || (int($state{'state'}) >= 2 && $showcommand)) {
426                 if ($passwordOK || $frame<int($state{'last'})) {
427                         print '<a href="'.CGI_VIEWER_PATH.'/'.($frame + 1).($passwordOK?('?p='.urlencode($password)):'').'">';
428                 }
429                 if($nextframedata{'title'} ne '') {
430                         print entityencode($nextframedata{'title'});
431                 }
432                 elsif ($passwordOK || $frame<int($state{'last'})) {
433                         print'<span class="inp">_</span>';
434                 }
435                 if ($passwordOK || $frame<int($state{'last'})) {
436                         print '</a>';
437                 }
438                 else {
439                         print'<span class="inp">_</span>';
440                 }
441         }
442         else {
443                 print'<span class="inp">_</span>';
444         }
445         print '<br>'."\n";
446 }
447 print '</div>'."\n";
448
449 print '<div id="underlinks">'."\n";
450 print '<a href="'.CGI_PATH.'">Once again</a>';
451 if($frame>0 && $access) {
452         print ' | <a href="'.CGI_VIEWER_PATH.'/'.($frame-1).($passwordOK?('?p='.urlencode($password)):'').'">Before</a>';
453 }
454 if($frame != int($state{'last'})) {
455         print ' | <a href="'.CGI_VIEWER_PATH.'/'.int($state{'last'}).($passwordOK?('?p='.urlencode($password)):'').'">Now</a>';
456 }
457 print ' | <a href="'.CGI_GOTO_PATH.($passwordOK?('?p='.urlencode($password)):'').'">GOTO</a>'."\n";
458 print '<span style="float: right;">'."\n";
459
460 if ($textmode!=0) {
461         print '<a href="'.CGI_VIEWER_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'').'">Without</a> | ';
462 }
463
464 print '<a href="'.(($textmode==2)?(CGI_INFO_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'')):(CGI_VIEWER_PATH.'/'.$frame.'?b=2'.($passwordOK?('&amp;p='.urlencode($password)):''))).'">Info</a>';
465 print ' | <a href="'.(($textmode==1)?(CGI_BBCODE_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'')):(CGI_VIEWER_PATH.'/'.$frame.'?b=1'.($passwordOK?('&amp;p='.urlencode($password)):''))).'">BB</a>';
466 print "\n</span>\n";
467
468 print '</div>'."\n";
469
470 print '</div>'."\n";
471
472 print '</div>'."\n";
473 print '<a href="/" class="cz">'.WEBSITE.'</a>'."\n";
474
475 print '</body></html>'."\n";
476
477 sub writeindex {
478         (my $indexpath) = @_;
479         my $indexfile;
480         my %framedata;
481         my %nextframedata;
482         my %default;
483         
484         if(ref($indexpath)) {
485                 $indexfile=$indexpath;
486                 unless (seek($indexfile, 0, 0)) {
487                         return 0;
488                 }
489         }
490         else {
491                 unless (open ($indexfile, ">", $indexpath)) {
492                         return 0;
493                 }
494         }
495         
496         %framedata = readdatafile(DATA_PATH.0);
497         %nextframedata = readdatafile(DATA_PATH.1);
498         %default=readdatafile(DATA_DEFAULT_PATH);
499         
500         foreach my $ind (keys %default) {
501                 unless(defined($framedata{$ind})){
502                         $framedata{$ind}=$default{$ind};
503                 }
504                 unless(defined($nextframedata{$ind})){
505                         $nextframedata{$ind}=$default{$ind};
506                 }
507         }
508         
509         print $indexfile '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
510         print $indexfile '<html lang="en"><head>'."\n";
511         print $indexfile '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
512         print $indexfile '<title>'.entityencode($settings{'story'}).' &bull; '.WEBSITE_NAME.'</title>'."\n";
513         print $indexfile '<link rel="icon" type="image/png" href="'.FAVICON_PATH.'">'."\n";
514         print $indexfile '<link rel="stylesheet" href="'.CGI_CSS_PATH.'">'."\n";
515         print $indexfile '<link rel="index" href="'.CGI_GOTO_PATH.'">'."\n";
516         print $indexfile '<link rel="start" href="'.CGI_VIEWER_PATH.'/0">'."\n";
517         print $indexfile '<link rel="next" href="'.CGI_VIEWER_PATH.'/1">'."\n";
518         print $indexfile '<link rel="prefetch" href="'.CGI_VIEWER_PATH.'/1">'."\n";
519         print $indexfile '</head><body>'."\n";
520         print $indexfile '<a href="/"><img id="botmlogo" src="'.CGI_LOGO_PATH.'" alt="'.WEBSITE.'"></a>'."\n";
521         print $indexfile '<div id="all">'."\n";
522         
523         print $indexfile '<div id="inst" class="ins">'."\n";
524         
525         print $indexfile '<div id="title">'."\n";
526         print $indexfile '<H1 id="titletext">'.entityencode($settings{'story'}).'</H1>'."\n";
527         print $indexfile '</div>'."\n";
528         
529         print $indexfile '</div><div id="framespace">'."\n";
530         print $indexfile '<img src="'.CGI_PATH.sprintf($settings{'frame'},0,$framedata{'ext'}).'" title="'.entityencode($framedata{'title'}).'" alt="0" id="frame">'."\n";
531         
532         print $indexfile '</div><div id="insb" class="ins">'."\n";
533         print $indexfile '<div id="undertext">'."\n";
534         print $indexfile bb2htf($framedata{'content'})."\n";
535         print $indexfile '</div>'."\n";
536         
537         print $indexfile '<div id="command">'."\n";
538         print $indexfile '&gt;<a href="'.CGI_VIEWER_PATH.'/1">'.entityencode($nextframedata{'title'}).'</a>'."\n";
539         print $indexfile '</div>'."\n";
540         
541         print $indexfile '<div id="underlinks">'."\n";
542
543         
544         # <span style="float: right;"><a href="/bsta/v/0?b=2">Info</a> | <a href="/bsta/v/0?b=1">BB</a></span>
545         
546         print $indexfile '<a href="'.CGI_VIEWER_PATH.'/-1">Now</a> | <a href="'.CGI_GOTO_PATH.'">GOTO</a>';
547         print $indexfile '<span style="float: right;"><a href="'.CGI_INFO_PATH.'/0?b=2">Info</a> | <a href="'.CGI_VIEWER_PATH.'/0?b=1">BB</a></span>'."\n";
548         print $indexfile '</div>'."\n";
549         
550         print $indexfile '</div>'."\n";
551         
552         print $indexfile '</div>'."\n";
553         print $indexfile '<a href="/" class="cz">'.WEBSITE.'</a>'."\n";
554         
555         print $indexfile '</body></html>'."\n";
556         
557         unless (ref($indexpath)) {
558                 close ($indexfile);
559         }
560         else {
561                 truncate ($indexfile , tell($indexfile));
562         }
563         
564         return 1;
565 }
566
567 sub bb2htf {
568         (my $bb) = @_;
569         my $tag;
570         my $tagvalue;
571         my $pretext;
572         my $posttext;
573         
574         while($bb =~ m/(###([^#;]*);)/g) {
575                 $tag = $1;
576                 $tagvalue = $2;
577                 $pretext = substr($bb,0,pos ($bb)-length($tag));
578                 $posttext = substr ($bb,pos ($bb));
579                 
580                 if ($tagvalue =~ /^att&([0-9]+)$/) {
581                         $tagvalue = CGI_ATTACH_PATH.'/'.int($1).($passwordOK?('?p='.urlencode($password)):'');
582                 }
583                 elsif ($tagvalue =~ /^vw&([0-9]+)$/) {
584                         $tagvalue = CGI_VIEWER_PATH.'/'.int($1).($passwordOK?('?p='.urlencode($password)):'');
585                 }
586                 elsif ($tagvalue =~ /^fr&([0-9]+)$/) {
587                         $tagvalue = CGI_FRAME_PATH.'/'.int($1).($passwordOK?('?p='.urlencode($password)):'');
588                 }
589                 else {
590                         $tagvalue = '';
591                 }
592                 
593                 $bb = $pretext.$tagvalue.$posttext;
594         }
595         
596         return bb2ht ($bb);
597 }
598
599 sub bb2bbf {
600         (my $bb) = @_;
601         my $tag;
602         my $tagvalue;
603         my $pretext;
604         my $posttext;
605         
606         while($bb =~ m/(###([^#;]*);)/g) {
607                 $tag = $1;
608                 $tagvalue = $2;
609                 $pretext = substr($bb,0,pos ($bb)-length($tag));
610                 $posttext = substr ($bb,pos ($bb));
611                 
612                 if ($tagvalue =~ /^att&([0-9]+)$/) {
613                         $tagvalue = 'http://'.WEBSITE.CGI_ATTACH_PATH.'/'.int($1);
614                 }
615                 elsif ($tagvalue =~ /^vw&([0-9]+)$/) {
616                         $tagvalue = 'http://'.WEBSITE.CGI_VIEWER_PATH.'/'.int($1);
617                 }
618                 elsif ($tagvalue =~ /^fr&([0-9]+)$/) {
619                         $tagvalue = 'http://'.WEBSITE.CGI_FRAME_PATH.'/'.int($1);
620                 }
621                 else {
622                         $tagvalue = '';
623                 }
624                 
625                 $bb = $pretext.$tagvalue.$posttext;
626         }
627         
628         return linehtml(bb2bb ($bb));
629 }