-###PERL;
-#
+###RUN_PERL: #!/usr/bin/perl
+
# /bsta/v
# viewer is generated from viewer.1.pl.
-# 09.01.2023
#
# The viewer interface
#
-# Copyright (C) 2016-2017, 2019-2020, 2023 Balthasar Szczepański
+# Copyright (C) 2016, 2017, 2019, 2020, 2023, 2024 Balthasar Szczepański
#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
-#use warnings;
-###LIB;
-use bsta_lib qw(failpage gethttpheader getcgi entityencode readdatafile writedatafile printdatafileht urlencode bb2ht bb2bb linehtml);
-use File::Copy;
+use utf8;
+# use Encode::Locale ('decode_argv');
+use Encode ('encode', 'decode');
+
+###PERL_LIB: use lib /botm/lib/bsta
+use botm_common (
+ 'HTTP_STATUS',
+ 'fail_method', 'fail_content_type', 'redirect',
+ 'read_header_env',
+ 'url_query_decode',
+ 'join_path',
+ 'open_encoded', '_x_encoded',
+ 'http_header_status',
+ 'merge_settings',
+ 'merge_url'
+);
+use bsta_lib (
+ 'STATE', 'TEXT_MODE', 'INTF_STATE',
+ 'get_remote_addr', 'get_frame', 'get_password',
+ 'print_viewer_page',
+ 'write_index', 'write_static_goto', 'write_static_viewer_page',
+ 'ong',
+ 'read_frame_data', 'read_default', 'read_noaccess',
+ 'read_words_list', 'read_settings', 'read_story', 'read_goto',
+ 'read_state', 'write_state',
+ 'get_page_file'
+);
+
+###PERL_PATH_SEPARATOR: PATH_SEPARATOR = /
+
+###PERL_CGI_PATH: CGI_PATH = /bsta/
+###PERL_CGI_GOTO_PATH: CGI_GOTO_PATH = /bsta/g
+###PERL_CGI_VIEWER_PATH: CGI_VIEWER_PATH = /bsta/v
+
+###PERL_DATA_STATE_PATH: DATA_STATE_PATH = /botm/data/bsta/state
+
+###PERL_WWW_PATH: WWW_PATH = /botm/www/
+
+binmode STDIN, ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+binmode STDERR, ':encoding(UTF-8)';
+# decode_argv();
-###DATA_PATH;
-###DEFAULT_PATH;
-###SETTINGS_PATH;
-###STATE_PATH;
-###LOGO_PATH;
-###FAVICON_PATH;
-###WEBSITE;
-###WEBSITE_NAME;
-###CSS_PATH;
-###CGI_PATH;
-###FRAME_PATH;
-###VIEWER_PATH;
-###NOACCESS_PATH;
-###STORY_PATH;
-###WWW_PATH;
-###INDEX_PATH;
-###ATTACH_PATH;
-###INFO_PATH;
-###BBCODE_PATH;
-###GOTO_PATH;
-###LIST_PATH;
-###TIMER_PATH;
+my $time = time();
+srand ($time-$$);
my %http;
my %cgi;
-my %framedata;
-my %nextframedata;
+my %frame_data;
+my %prev_frame_data;
+my %next_frame_data;
my %default;
my %settings;
my %state;
-my %newstate;
-my %gotolist;
-
-my $time = time();
-srand ($time-$$);
+my %new_state;
+my %goto_list;
+my %words_data;
my $method;
my $frame;
+my $prev_frame_data_path;
+my $next_frame_data_path;
my $password;
-my $passwordOK;
+my $password_ok;
my $IP;
my $access;
-my $seconds;
-my $minutes;
-my $hours;
-my $statefile;
-my $showcommand;
+my $timer;
+my $timer_unlocked;
+my $fh;
+my $show_command;
my $ongtime;
-my $textmode;
+my $goto;
+my $text_mode;
+my $words_page;
+my $words_data_path;
+my $no_cgi;
+my $force_redirect;
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
-###PATH;
+###PERL_SET_PATH: $ENV{'PATH'} = /usr/local/bin:/usr/bin:/bin;
if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
- $method=$1;
+ $method = $1;
}
else{
- 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);
+ exit fail_method($ENV{'REQUEST_METHOD'}, ['GET', 'POST', 'HEAD']);
}
-%http = gethttpheader (\%ENV);
-%cgi = getcgi($ENV{'QUERY_STRING'});
+%http = read_header_env(\%ENV);
+%cgi = url_query_decode($ENV{'QUERY_STRING'});
if ($method eq 'POST') {
if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
- my %cgipost=getcgi( <STDIN> );
- foreach my $ind (keys %cgipost) {
- $cgi{$ind}=$cgipost{$ind};
- }
+ my %cgi_post = url_query_decode( <STDIN> );
+ %cgi = merge_settings(\%cgi, \%cgi_post);
}
# multipart not supported
else{
- exit failpage("Status: 415 Unsupported Media Type\n","415 Unsupported Media Type","Unsupported Content-type: $http{'content-type'}.");
+ exit fail_content_type($method, $http{'content-type'});
}
}
-if ($ENV{'HTTP_X_FORWARDED_FOR'} =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
- $IP=$1;
-}
-elsif ($ENV{'REMOTE_ADDR'} =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/) {
- $IP=$1;
-}
-else {
- $IP='0.0.0.0';
-}
+$no_cgi = (scalar (keys %cgi) == 0);
-if ($cgi{'f'} =~ /^(.+)$/) {
- $frame=int($1);
-}
-elsif ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) {
- $frame=int($1);
-}
-else {
- $frame = 0;
-}
+$IP = get_remote_addr();
+$frame = get_frame(\%cgi);
+$password = get_password(\%cgi);
-if ($cgi{'p'} =~ /^(.+)$/) {
- $password=$1;
-}
-else {
- $password='';
-}
-# print "Content-type: text/plain\n\n";
+%settings = read_settings();
+%default = read_default();
-%settings=readdatafile(SETTINGS_PATH);
-%default=readdatafile(DEFAULT_PATH);
-%framedata=readdatafile(DATA_PATH.$frame);
-if($password eq $settings{'password'}){
- $passwordOK = 1;
+if ($frame >= 0) {
+ %frame_data= read_frame_data($frame);
}
-else{
- $passwordOK = 0;
+
+$password_ok = ($password eq $settings{'password'});
+
+if (
+ (defined $cgi{'f'}) &&
+ ($cgi{'f'} eq '') &&
+ ($cgi{'g'} ne '')
+) { # GOTO with no value
+ my $goto_url = CGI_GOTO_PATH();
+ if ($password_ok) {
+ $goto_url = merge_url(
+ {'path' => $goto_url},
+ {'query' => {'p' => $password}}
+ );
+ }
+ exit redirect($method, $goto_url, HTTP_STATUS->{'see_other'});
}
-if (open ($statefile,"+<",STATE_PATH)){
- if (flock($statefile,2)) {
+
+# state & activation logic
+if (open_encoded($fh, "+<:encoding(UTF-8)", DATA_STATE_PATH())) {
+ if (flock($fh, 2)) {
- %state=readdatafile($statefile);
+ %state = read_state($fh);
- if($frame<0) {
+ if ($frame < 0) {
$frame = int($state{'last'}) + $frame +1;
- %framedata=readdatafile(DATA_PATH.$frame);
+ if ($frame >= 0) {
+ $force_redirect = 1;
+ %frame_data = read_frame_data($frame);
+ }
}
- if(int($state{'state'})==1 && $frame == int($state{'last'}) && $method ne 'HEAD' && !$passwordOK){
- my %newstate=%state;
- if($state{'ip1'} ne $IP) {
+ if (
+ (int($state{'state'}) == STATE->{'waiting'}) &&
+ ($frame == int($state{'last'})) &&
+ ($method ne 'HEAD') &&
+ (!$password_ok)
+ ) {
+ # register IP for progress
+ my %new_state = %state;
+ unless (
+ ($state{'ip1'} eq $IP) ||
+ ($state{'ip2'} eq $IP) ||
+ ($state{'ip3'} eq $IP)
+ )
+ {
if ($state{'ip1'} eq '') {
- $newstate{'ip1'} = $IP;
- writedatafile($statefile,%newstate);
+ $new_state{'ip1'} = $IP;
}
- elsif($state{'ip2'} ne $IP) {
- if ($state{'ip2'} eq '') {
- $newstate{'ip2'} = $IP;
- writedatafile($statefile,%newstate);
- }
- else {
- $newstate{'state'}=2;
- $newstate{'ip3'} = $IP;
- writedatafile($statefile,%newstate);
- }
+ elsif ($state{'ip2'} eq '') {
+ $new_state{'ip2'} = $IP;
}
+ elsif ($state{'ip3'} eq '') {
+ $new_state{'ip3'} = $IP;
+ $new_state{'state'} = STATE->{'ready'};
+ }
+ else {
+ $new_state{'state'} = STATE->{'ready'};
+ }
+ if ($new_state{'state'} == STATE->{'ready'}) {
+ write_static_goto(\%new_state, \%settings, '');
+ write_static_viewer_page(
+ $frame-1,
+ \%new_state,
+ \%settings,
+ \%default,
+ '', # frame data
+ '', # prev frame data
+ \%frame_data, # next frame data,
+ '' # words data
+ );
+ }
+ write_state($fh, \%new_state);
}
}
- elsif(int($state{'state'})==0 && $frame == 1) {
+ elsif (
+ (int($state{'state'}) == STATE->{'inactive'}) &&
+ ($frame == 1) &&
+ (!$password_ok)
+ ) {
+ # ready to activate?
+ # NOTE: at this point frame 0 is already ONGed.
my %story;
- my $inpath;
- my $outpath;
+ my $ong_time = int($settings{'firstongtime'});
+ my $r;
- %story = readdatafile(STORY_PATH);
- %gotolist=readdatafile(LIST_PATH);
- if(int($story{'state'}) == 17 && int($story{'pass'}) == 1) {
- #ACTIVATE!
-
- $framedata{'ongtime'} = $time;
- writedatafile(DATA_PATH.$frame,%framedata);
- $state{'state'} = 1;
- $state{'last'} = 1;
- $state {'ip1'} = '0.0.0.0';
- $state {'ip2'} = '0.0.0.0';
- $state {'ip3'} = '';
- $state {'nextong'} = (int($time / 3600) + int($settings{'firstongtime'})) * 3600 ;
- $state{'ongtime'} = int($settings{'firstongtime'});
-
- unless(defined($framedata{'ext'})){
- $framedata{'ext'}=$default{'ext'};
- }
+ %story = read_story();
+ %goto_list = read_goto();
+
+ if (
+ (int($story{'state'}) == INTF_STATE->{'>|'} ) &&
+ (int($story{'pass'}) == 1)
+ ) {
+ # conditions met; ACTIVATE!
- $inpath = DATA_PATH.sprintf($settings{'frame'},$frame,$framedata{'ext'});
- $outpath = WWW_PATH.sprintf($settings{'frame'},$frame,$framedata{'ext'});
+ # set initial state
+ $state{'state'} = STATE->{'waiting'};
+ $state{'last'} = 1;
+ $state{'ip1'} = '0.0.0.0';
+ $state{'ip2'} = '0.0.0.0';
+ $state{'ip3'} = '';
+ $state{'nextong'} = (int($time / 3600) + int($settings{'firstongtime'})) * 3600 ;
+ $state{'ongtime'} = $ong_time;
- $gotolist{'title-1'}=$framedata{'title'};
- $gotolist{'ongtime-1'}=$framedata{'ongtime'};
+ # prepare to ONG frame 1
- if(copy ($inpath, $outpath)) {
- writeindex(INDEX_PATH);
- writedatafile($statefile,%state);
- writedatafile(LIST_PATH,%gotolist);
+ $r = ong(
+ 1, # frame ID
+ $time, # ONG time,
+ $ong_time, # timer
+ 0, # update
+ 0, # print
+ \%settings,
+ \%default,
+ \%frame_data,
+ \%goto_list
+ );
+ if ($r) {
+ $r = write_index(\%state, \%settings);
}
- else {
- $state{'state'} = 0;
+ if ($r) {
+ $r = write_static_goto(\%state, \%settings, \%goto_list);
+ }
+ if ($r) {
+ $r = write_state($fh, \%state);
+ }
+ unless ($r) {
+ # FAILED ONG! Story as if it was inactive!
+ $state{'state'} = STATE->{'inactive'};
}
}
}
}
else {
- $state{'state'} = 0;
+ # FAILED GET STATE! Story as if it was inactive!
+ $state{'state'} = STATE->{'inactive'};
}
- close ($statefile);
+ close ($fh);
}
else {
- $state{'state'} = 0;
-}
-
-%nextframedata=readdatafile(DATA_PATH.($frame+1));
-foreach my $ind (keys %default) {
- unless(defined($framedata{$ind})){
- $framedata{$ind}=$default{$ind};
- }
- unless(defined($nextframedata{$ind})){
- $nextframedata{$ind}=$default{$ind};
+ $state{'state'} = STATE->{'inactive'};
+}
+
+$access = (
+ $password_ok || (
+ (int($state{'state'}) >= STATE->{'waiting'}) &&
+ ($frame <= int($state{'last'})) &&
+ ($frame >= 0)
+ )
+);
+
+if ($access) {
+ if ($no_cgi) {
+ # no CGI - static page is OK
+ if ($frame == 0) {
+ exit redirect($method, CGI_PATH(), HTTP_STATUS->{'see_other'});
+ }
+ elsif ($frame < int($state{'last'})) {
+ my $page_file = get_page_file($frame, \%frame_data, \%settings);
+ if (_x_encoded('-f',
+ join_path(PATH_SEPARATOR(), WWW_PATH() , $page_file)
+ )) {
+ my $static_url = merge_url(
+ {'path' => CGI_PATH()},
+ {'path' => $page_file}
+ );
+ exit redirect($method, $static_url, HTTP_STATUS->{'see_other'});
+ }
+ }
}
-}
-
-$hours=int($state{'nextong'})-$time;
-$ongtime=int($state{'ongtime'});
-if($ongtime == 0) {
- $ongtime=int($settings{'ongtime'})
-}
-
-$showcommand = ($hours < ($ongtime*3600/3));
-if($hours>0){
- $seconds = sprintf('%02d',$hours % 60);
- $hours = int($hours/60);
- $minutes = sprintf('%02d',$hours % 60);
- $hours = sprintf('%02d',int($hours/60));
-}
-elsif(($hours>=-15) && (int($state{'state'}) == 2)){
- $seconds='NG';
- $minutes='00';
- $hours='00';
-}
-else{
- $seconds='EE';
- $minutes='EE';
- $hours='EE';
-}
-
-
-if ($passwordOK || (int($state{'state'}) >= 1 && $frame <= int($state{'last'}) && $frame >= 0)) {
- $access=1;
-}
-else {
- $access=0;
- %framedata = readdatafile(NOACCESS_PATH);
- foreach my $ind (keys %default) {
- unless(defined($framedata{$ind})){
- $framedata{$ind}=$default{$ind};
+ if ($force_redirect) {
+ my $redirect_url = merge_url(
+ {'path' => CGI_VIEWER_PATH()},
+ {'path' => $frame}
+ );
+ unless ($no_cgi) {
+ delete $cgi{'f'}; # to avoid infinite loop
+ $redirect_url = merge_url(
+ {'path' => $redirect_url},
+ {'query' => \%cgi}
+ );
}
+ exit redirect($method, $redirect_url, HTTP_STATUS->{'see_other'});
}
-}
-
-$textmode = int($cgi{'b'});
-if($textmode > 2) {
- $textmode = 0;
-}
-
-# print "Content-type: text/plain\n\n";
-# print 'frame='.$frame."\n";
-# print 'password='.$password."\n";
-# print 'passwordOK='.$passwordOK."\n";
-# print 'access='.$access."\n";
-# print "\n>>>ENV<<<\n\n";
-# foreach my $ind (keys %ENV) {
- # print $ind.'='.$ENV{$ind}."\n";
-# }
-# print "\n>>>HTTP<<<\n\n";
-# foreach my $ind (keys %http) {
- # print $ind.': '.$http{$ind}."\n";
-# }
-# print "\n>>>CGI<<<\n\n";
-# foreach my $ind (keys %cgi) {
- # print $ind.'='.$cgi{$ind}."\n";
-# }
-# print "\n>>>FRAMEDATA<<<\n\n";
-# foreach my $ind (keys %framedata) {
- # print $ind.': '.$framedata{$ind}."\n";
-# }
-# print "\n>>>NEXTFRAMEDATA<<<\n\n";
-# foreach my $ind (keys %nextframedata) {
- # print $ind.': '.$nextframedata{$ind}."\n";
-# }
-# print "\n>>>SETTINGS<<<\n\n";
-# foreach my $ind (keys %settings) {
- # print $ind.': '.$settings{$ind}."\n";
-# }
-# print "\n>>>STATE<<<\n\n";
-# foreach my $ind (keys %state) {
- # print $ind.': '.$state{$ind}."\n";
-# }
-
-print "Content-type: text/html\n";
-if(!$access) {
- print "Status: 403 Forbidden\n";
-}
-print "\n";
-if($method eq 'HEAD') {
- exit;
-}
-
-print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
-print '<html lang="en"><head>'."\n";
-print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
-print '<title>';
-unless($framedata{'title'} eq '' || $framedata{'title'} eq $settings{'story'}) {
- print entityencode($framedata{'title'}).' • ';
-}
-print entityencode($settings{'story'}).' • '.WEBSITE_NAME.'</title>'."\n";
-print '<link rel="icon" type="image/png" href="'.FAVICON_PATH.'">'."\n";
-print '<link rel="stylesheet" href="'.CSS_PATH.'">'."\n";
-print '<link rel="index" href="'.GOTO_PATH.($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
-print '<link rel="start" href="'.VIEWER_PATH.'/0'.($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
-if($frame>0 && $access) {
- print '<link rel="prev" href="'.VIEWER_PATH.'/'.($frame - 1).($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
-}
-if ($passwordOK || $frame<int($state{'last'})) {
- print '<link rel="next" href="'.VIEWER_PATH.'/'.($frame + 1).($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
- print '<link rel="prefetch" href="'.VIEWER_PATH.'/'.($frame + 1).($passwordOK?('?p='.urlencode($password)):'').'">'."\n";
-}
-if($frame==int($state{'last'}) && int($state{'state'}) >= 1 && int($state{'state'}) < 3) {
- print '<!-- <script src="'.TIMER_PATH.'"></script> -->'."\n";
-}
-print '</head><body>'."\n";
-print '<a href="/"><img id="botmlogo" src="'.LOGO_PATH.'" alt="'.WEBSITE.'"></a>'."\n";
-print '<div id="all">'."\n";
-
-print '<div id="inst" class="ins">'."\n";
-
-print '<div id="title">'."\n";
-print '<H1 id="titletext">'.entityencode($framedata{'title'}).'</H1>'."\n";
-print '</div>'."\n";
-
-print '</div><div id="framespace">'."\n";
-if(!$access) {
- print '<img src="'.CGI_PATH.$framedata{'frame'}.'" id ="frame" alt="'.$frame.'" title="'.entityencode($framedata{'title'}).'">'."\n";
-}
-else {
- print'<img src="';
- if($frame<=int($state{'last'}) && int($state{'state'}) >= 1) {
- print CGI_PATH.sprintf($settings{'frame'},$frame,$framedata{'ext'});
+
+ if ($frame > 0) {
+ %prev_frame_data = read_frame_data($frame-1, \%default);
}
else {
- print FRAME_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'');
+ %prev_frame_data = %default;
}
- print '" id="frame" alt="'.$frame.'" title="'.entityencode($framedata{'title'}).'">'."\n";
+ %next_frame_data = read_frame_data($frame+1, \%default);
+ %frame_data = merge_settings(\%default, \%frame_data);
}
-print '</div><div id="insb" class="ins">'."\n";
-
-if($textmode==2){
- print '<div id="chat">'."\n";
-
- if ($passwordOK || $frame<int($state{'last'}) || (int($state{'state'}) >= 2 && $showcommand)) {
- $framedata{'command'}=$nextframedata{'title'};
- }
- if ($access) {
- $framedata{'frame'}=sprintf($settings{'frame'},$frame,$framedata{'ext'});
- }
-
- printdatafileht(%framedata);
- print '</div>'."\n";
-}
-elsif($textmode==1){
- print '<div id="chat">'."\n";
- print '[quote][center][size=200]'.entityencode($framedata{'title'}).'[/size]<br>'."\n";
- print '[url=http://'.WEBSITE.VIEWER_PATH.'/'.$frame.'][img]http://'.WEBSITE.CGI_PATH.($access?sprintf($settings{'frame'},$frame,$framedata{'ext'}):$framedata{'frame'}).'[/img][/url][/center]<br>'."\n";
- print bb2bbf($framedata{'content'}).'[/quote]</div>'."\n";
+else {
+ # replace frame data with fail state replacement
+ %frame_data = read_noaccess(\%default);
}
-elsif($framedata{'content'} ne ''){
- print '<div id="undertext">'."\n";
- print bb2htf($framedata{'content'})."\n";
- print '</div>'."\n";
+
+$timer = int($state{'nextong'}) - $time;
+$ongtime = int($state{'ongtime'});
+if($ongtime == 0) {
+ $ongtime = int($settings{'ongtime'})
}
-print '<div id="command">'."\n";
-if($frame==int($state{'last'}) && int($state{'state'}) >= 1 && int($state{'state'}) < 3) {
- print '[<span id="ongh" class="';
- if(int($state{'state'}) >= 2 || $state{'ip1'} ne '') {
- print 'br';
- }
- else {
- print 'ni';
- }
- print '">'.$hours.'</span>:<span id="ongm" class="';
- if(int($state{'state'}) >= 2 || $state{'ip2'} ne '') {
- print 'br';
- }
- else {
- print 'ni';
- }
- print '">'.$minutes.'</span>:<span id="ongs" class="';
- if(int($state{'state'}) >= 2 || $state{'ip3'} ne '') {
- print 'br';
- }
- else {
- print 'ni';
- }
- print '">'.$seconds.'</span>]<br>';
+$show_command = ($timer < ($ongtime*3600/3));
+if ($state{'state'} >= STATE->{'ready'}) {
+ $timer_unlocked = 3;
}
-print '>';
-if (!$access){
- print '<a href="'.VIEWER_PATH.'/-1">'.entityencode($framedata{'command'}).'</a><br>'."\n";
+elsif ($state{'ip3'} ne '') {
+ $timer_unlocked = 3;
}
-else {
- if ($passwordOK || $frame<int($state{'last'}) || (int($state{'state'}) >= 2 && $showcommand)) {
- if ($passwordOK || $frame<int($state{'last'})) {
- print '<a href="'.VIEWER_PATH.'/'.($frame + 1).($passwordOK?('?p='.urlencode($password)):'').'">';
- }
- if($nextframedata{'title'} ne '') {
- print entityencode($nextframedata{'title'});
- }
- elsif ($passwordOK || $frame<int($state{'last'})) {
- print'<span class="inp">_</span>';
- }
- if ($passwordOK || $frame<int($state{'last'})) {
- print '</a>';
- }
- else {
- print'<span class="inp">_</span>';
- }
- }
- else {
- print'<span class="inp">_</span>';
- }
- print '<br>'."\n";
+elsif ($state{'ip2'} ne '') {
+ $timer_unlocked = 2;
}
-print '</div>'."\n";
-
-print '<div id="underlinks">'."\n";
-print '<a href="'.CGI_PATH.'">Once again</a>';
-if($frame>0 && $access) {
- print ' | <a href="'.VIEWER_PATH.'/'.($frame-1).($passwordOK?('?p='.urlencode($password)):'').'">Before</a>';
+elsif ($state{'ip1'} ne '') {
+ $timer_unlocked = 1;
}
-if($frame != int($state{'last'})) {
- print ' | <a href="'.VIEWER_PATH.'/'.int($state{'last'}).($passwordOK?('?p='.urlencode($password)):'').'">Now</a>';
+else {
+ $timer_unlocked = 0;
}
-print ' | <a href="'.GOTO_PATH.($passwordOK?('?p='.urlencode($password)):'').'">GOTO</a>'."\n";
-print '<span style="float: right;">'."\n";
-if ($textmode!=0) {
- print '<a href="'.VIEWER_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'').'">Without</a> | ';
+$text_mode = int($cgi{'b'});
+if($text_mode > TEXT_MODE->{'words'}) {
+ $text_mode = TEXT_MODE->{'normal'};
}
+$words_page = int($cgi{'i'});
+$goto = int($cgi{'g'});
-print '<a href="'.(($textmode==2)?(INFO_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'')):(VIEWER_PATH.'/'.$frame.'?b=2'.($passwordOK?('&p='.urlencode($password)):''))).'">Info</a>';
-print ' | <a href="'.(($textmode==1)?(BBCODE_PATH.'/'.$frame.($passwordOK?('?p='.urlencode($password)):'')):(VIEWER_PATH.'/'.$frame.'?b=1'.($passwordOK?('&p='.urlencode($password)):''))).'">BB</a>';
-print "\n</span>\n";
-
-print '</div>'."\n";
+%words_data = read_words_list(
+ $frame,
+ ($text_mode != TEXT_MODE->{'words'})
+);
-print '</div>'."\n";
-
-print '</div>'."\n";
-print '<a href="/" class="cz">'.WEBSITE.'</a>'."\n";
-
-print '</body></html>'."\n";
-
-sub writeindex {
- (my $indexpath) = @_;
- my $indexfile;
- my %framedata;
- my %nextframedata;
- my %default;
-
- if(ref($indexpath)) {
- $indexfile=$indexpath;
- unless (seek($indexfile, 0, 0)) {
- return 0;
- }
- }
- else {
- unless (open ($indexfile, ">", $indexpath)) {
- return 0;
- }
- }
-
- %framedata = readdatafile(DATA_PATH.0);
- %nextframedata = readdatafile(DATA_PATH.1);
- %default=readdatafile(DEFAULT_PATH);
-
- foreach my $ind (keys %default) {
- unless(defined($framedata{$ind})){
- $framedata{$ind}=$default{$ind};
- }
- unless(defined($nextframedata{$ind})){
- $nextframedata{$ind}=$default{$ind};
- }
- }
-
- print $indexfile '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
- print $indexfile '<html lang="en"><head>'."\n";
- print $indexfile '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
- print $indexfile '<title>'.entityencode($settings{'story'}).' • '.WEBSITE_NAME.'</title>'."\n";
- print $indexfile '<link rel="icon" type="image/png" href="'.FAVICON_PATH.'">'."\n";
- print $indexfile '<link rel="stylesheet" href="'.CSS_PATH.'">'."\n";
- print $indexfile '<link rel="index" href="'.GOTO_PATH.'">'."\n";
- print $indexfile '<link rel="start" href="'.VIEWER_PATH.'/0">'."\n";
- print $indexfile '<link rel="next" href="'.VIEWER_PATH.'/1">'."\n";
- print $indexfile '<link rel="prefetch" href="'.VIEWER_PATH.'/1">'."\n";
- print $indexfile '</head><body>'."\n";
- print $indexfile '<a href="/"><img id="botmlogo" src="'.LOGO_PATH.'" alt="'.WEBSITE.'"></a>'."\n";
- print $indexfile '<div id="all">'."\n";
-
- print $indexfile '<div id="inst" class="ins">'."\n";
-
- print $indexfile '<div id="title">'."\n";
- print $indexfile '<H1 id="titletext">'.entityencode($settings{'story'}).'</H1>'."\n";
- print $indexfile '</div>'."\n";
-
- print $indexfile '</div><div id="framespace">'."\n";
- print $indexfile '<img src="'.CGI_PATH.sprintf($settings{'frame'},0,$framedata{'ext'}).'" title="'.entityencode($framedata{'title'}).'" alt="0" id="frame">'."\n";
-
- print $indexfile '</div><div id="insb" class="ins">'."\n";
- print $indexfile '<div id="undertext">'."\n";
- print $indexfile bb2htf($framedata{'content'})."\n";
- print $indexfile '</div>'."\n";
-
- print $indexfile '<div id="command">'."\n";
- print $indexfile '><a href="'.VIEWER_PATH.'/1">'.entityencode($nextframedata{'title'}).'</a>'."\n";
- print $indexfile '</div>'."\n";
-
- print $indexfile '<div id="underlinks">'."\n";
-
-
- # <span style="float: right;"><a href="/bsta/v/0?b=2">Info</a> | <a href="/bsta/v/0?b=1">BB</a></span>
-
- print $indexfile '<a href="'.VIEWER_PATH.'/-1">Now</a> | <a href="'.GOTO_PATH.'">GOTO</a>';
- print $indexfile '<span style="float: right;"><a href="'.INFO_PATH.'/0?b=2">Info</a> | <a href="'.VIEWER_PATH.'/0?b=1">BB</a></span>'."\n";
- print $indexfile '</div>'."\n";
-
- print $indexfile '</div>'."\n";
-
- print $indexfile '</div>'."\n";
- print $indexfile '<a href="/" class="cz">'.WEBSITE.'</a>'."\n";
-
- print $indexfile '</body></html>'."\n";
-
- unless (ref($indexpath)) {
- close ($indexfile);
- }
- else {
- truncate ($indexfile , tell($indexfile));
- }
-
- return 1;
+if (!$access) {
+ print http_header_status(HTTP_STATUS->{'forbidden'});
}
-
-sub bb2htf {
- (my $bb) = @_;
- my $tag;
- my $tagvalue;
- my $pretext;
- my $posttext;
-
- while($bb =~ m/(###([^#;]*);)/g) {
- $tag = $1;
- $tagvalue = $2;
- $pretext = substr($bb,0,pos ($bb)-length($tag));
- $posttext = substr ($bb,pos ($bb));
-
- if ($tagvalue =~ /^att&([0-9]+)$/) {
- $tagvalue = ATTACH_PATH.'/'.int($1).($passwordOK?('?p='.urlencode($password)):'');
- }
- elsif ($tagvalue =~ /^vw&([0-9]+)$/) {
- $tagvalue = VIEWER_PATH.'/'.int($1).($passwordOK?('?p='.urlencode($password)):'');
- }
- elsif ($tagvalue =~ /^fr&([0-9]+)$/) {
- $tagvalue = FRAME_PATH.'/'.int($1).($passwordOK?('?p='.urlencode($password)):'');
- }
- else {
- $tagvalue = '';
- }
-
- $bb = $pretext.$tagvalue.$posttext;
- }
-
- return bb2ht ($bb);
+print "Content-type: text/html; charset=UTF-8\n\n";
+if($method eq 'HEAD') {
+ exit;
}
-sub bb2bbf {
- (my $bb) = @_;
- my $tag;
- my $tagvalue;
- my $pretext;
- my $posttext;
-
- while($bb =~ m/(###([^#;]*);)/g) {
- $tag = $1;
- $tagvalue = $2;
- $pretext = substr($bb,0,pos ($bb)-length($tag));
- $posttext = substr ($bb,pos ($bb));
-
- if ($tagvalue =~ /^att&([0-9]+)$/) {
- $tagvalue = 'http://'.WEBSITE.ATTACH_PATH.'/'.int($1);
- }
- elsif ($tagvalue =~ /^vw&([0-9]+)$/) {
- $tagvalue = 'http://'.WEBSITE.VIEWER_PATH.'/'.int($1);
- }
- elsif ($tagvalue =~ /^fr&([0-9]+)$/) {
- $tagvalue = 'http://'.WEBSITE.FRAME_PATH.'/'.int($1);
- }
- else {
- $tagvalue = '';
- }
-
- $bb = $pretext.$tagvalue.$posttext;
- }
-
- return linehtml(bb2bb ($bb));
-}
+print_viewer_page (
+ \*STDOUT,
+ {
+ 'launch' => 0,
+ 'frame' => $frame,
+ 'access' => $access,
+ 'password_ok' => $password_ok,
+ 'timer_unlocked'=> $timer_unlocked,
+ 'timer' => $timer,
+ 'static' => 0,
+ 'show_command' => $show_command,
+ 'text_mode' => $text_mode,
+ 'words_page' => $words_page,
+ 'goto' => $goto
+ },
+ \%state,
+ \%settings,
+ \%frame_data,
+ $access ? \%prev_frame_data : \%frame_data,
+ $access ? \%next_frame_data : \%frame_data,
+ \%words_data,
+);