1 # bsta_lib.pm is generated from bsta_lib.1.pm
5 # Copyright (C) 2016, 2017, 2019, 2020, 2022, 2023 Balthasar SzczepaĆski
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # TODO: BB & INFO indent
31 use Encode ('encode', 'decode');
33 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
35 ###PERL_EXPORT_VERSION: our $VERSION = 'x.x.x';
36 our @ISA = qw(Exporter);
39 'STATE', 'TEXT_MODE', 'INTF_STATE',
40 'failpage', 'fail_method', 'fail_content_type',
41 'get_remote_addr', 'get_frame', 'get_password',
46 'readdatafile', 'writedatafile', 'printdatafile', # TO REMOVE
47 'entityencode', # TO REMOVE
48 'printdatafileht', # TO REMOVE ???
49 'gethttpheader', 'getcgi', # TO REMOVE
50 'urldecode', # TO REMOVE
51 'urlencode', # TO REMOVE
52 'linehtml', # TO REMOVE
53 'bb2ht', 'bb2bb' # TO REMOVE
56 ###PERL_LIB: use lib /botm/lib/bsta
58 'url_query_decode', 'url_query_encode',
59 'url_decode', 'url_encode',
60 'html_entity_encode_dec',
63 'read_data_file', 'write_data_file',
67 ###PERL_PATH_SEPARATOR: PATH_SEPARATOR = /
69 ###PERL_CGI_PATH: CGI_PATH = /bsta/
70 ###PERL_CGI_BBCODE_PATH: CGI_BBCODE_PATH = /bsta/b
71 ###PERL_CGI_CSS_PATH: CGI_CSS_PATH = /bsta/bsta.css
72 ###PERL_CGI_FRAME_PATH: CGI_FRAME_PATH = /bsta/f
73 ###PERL_CGI_GOTO_PATH: CGI_GOTO_PATH = /bsta/g
74 ###PERL_CGI_INFO_PATH: CGI_INFO_PATH = /bsta/i
75 ###PERL_CGI_LOGO_PATH: CGI_LOGO_PATH = /bsta/botmlogo.png
76 ###PERL_CGI_TIMER_PATH: CGI_TIMER_PATH = /bsta/timer.js
77 ###PERL_CGI_VIEWER_PATH: CGI_VIEWER_PATH = /bsta/v
79 ###PERL_DATA_PATH: DATA_PATH = /botm/data/bsta/
80 ###PERL_DATA_DEFAULT_PATH: DATA_DEFAULT_PATH = /botm/data/bsta/default
82 ###PERL_WWW_INDEX_PATH: WWW_INDEX_PATH = /botm/www/1190/bsta/index.htm
84 ###PERL_SCHEME: SCHEME = http
85 ###PERL_WEBSITE: WEBSITE = 1190.bicyclesonthemoon.info
86 ###PERL_WEBSITE_NAME: WEBSITE_NAME = Bicycles on the Moon
87 ###PERL_FAVICON_PATH: FAVICON_PATH = /img/favicon.png
90 use constant STATE => {
96 use constant INTF_STATE => {
109 use constant TEXT_MODE => {
115 use constant tags_bbcode => {
122 'ni' => '[color=#0057AF]',
124 'br' => '[color=#BB6622]',
126 'po' => '[color=#FF8800]',
137 '/list' => '[/list]',
141 '/?' => '[/unknown!]',
143 use constant tags_html => {
146 'fq' => '<div class="fq">',
148 'tq' => '<div class="tq">',
150 'ni' => '<span class="ni">',
152 'br' => '<span class="br">',
154 'po' => '<span class="po">',
156 'url' => '<a href="#">',#think: how to add selfincluding?
157 'url=' => '<a href="',
163 'list=' => '<ol style="list-style-type: ',
164 'list=1' => 'decimal',
165 'list=A' => 'upper-alpha',
166 'list=a' => 'lower-alpha',
167 'list=I' => 'upper-roman',
168 'list=i' => 'lower-roman',
175 '/?' => '[/unknown!]',
180 # Function to return an error page
181 # arguments: 1 - header fields, 2 - page title, 3 - error message, 4 method
183 (my $header, my $title, my $message, my $method) = @_;
187 if($method eq 'HEAD') {
191 print "Content-type: text/html; charset=UTF-8\n\n";
193 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
194 print ' <html lang="en">'."\n";
195 print ' <head>'."\n";
196 print ' <meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
198 print ' <title>'.html_entity_encode_dec($title, 1).'</title>'."\n";
200 print ' </head>'."\n";
201 print ' <body>'."\n";
203 print ' <h1>'.html_entity_encode_dec($title, 1).'</h1>'."\n";
205 if ($message ne '') {
206 print ' <p>'.html_entity_encode_dec($message, 1).'</p>'."\n";
208 print ' </body>'."\n";
209 print '</html>'."\n";
213 (my $method, my $allowed) = @_;
215 my $header = "Status: 405 Method Not Allowed\n";
216 if ($allowed ne '') {
217 $header .= "Allow: $allowed\n";
221 "405 Method Not Allowed",
222 "The interface does not support the $method method.",
227 sub fail_content_type
229 (my $content_type, my $method) = @_;
232 "Status: 415 Unsupported Media Type\n",
233 "415 Unsupported Media Type",
234 "Unsupported Content-type: $content_type.",
239 # function to obtain address of remote agent
240 sub get_remote_addr {
241 if ($ENV{'HTTP_X_FORWARDED_FOR'} =~ /^.+$/) {
244 elsif ($ENV{'REMOTE_ADDR'} =~ /^.+$/) {
252 # function to obtain frame number
256 if ($cgi->{'f'} =~ /^.+$/) {
259 elsif ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) {
267 # function to obtain password
271 if ($cgi->{'p'} =~ /^.+$/) {
282 foreach my $settings (@_) {
283 foreach my $ind (keys %$settings) {
284 $final_settings{$ind} = $settings->{$ind};
287 return %final_settings;
291 # function to encode entities, decimal,
293 (my $t, my $all) = @_;
294 return html_entity_encode_dec($t, 1, $all);
298 # function to get values of http header fields. Returns a hash. names of header
299 # fields are lowercase
303 return read_header_env($env);
307 # The function to get CGI parameters from string.
308 # Format is: name=url_encoded_value&name=url_encoded_value& ... &name=url_encoded_value
310 return url_query_decode($_[0]);
314 # Function for decoding URL-encoded text
316 return url_decode($_[0]);
320 # Function to read data from datafiles.
321 # Very similar to http header file reading. (function readheaderfile() in proxy
326 # 1. After field name and colon there must be exactly one whitespace (space or
327 # tab). Any other leading or trailing whitespace (but not the newline character
328 # at the end of the line) is treated as part of the field value.
330 # 2. Instead of colon an equal sign can be used. The number of whitespaces after
331 # it is then zero and not one.
333 # 3. When header field is split into multiple lines the next lines must start
334 # with exactly one whitespace (tab or space) Any other leading or trailing
335 # whitespace (but not the newline character at the end of the line) is treated
336 # as part of the field value. the lines will be joined with a newline between
339 # 4. When the same field name appears it replaces the previous one.
341 # 5. Line separator is LF and not CR LF. The CR character is treated as part of
344 # 6. After the end of header (double newline) all next lines are treated as the
345 # value of the "content" field.
347 # Returns a hash containing the values.
348 # Names are case sensitive and are converted to lowercase
350 # Argument can be a path or a file handle. In case of a file handle it will just
351 # read the file. In case of path it opens the file before reading and closes
352 # after. On failure (file not open) returns empty hash.
357 return read_data_file($datapath);
361 # the function to write data to datafiles (see readdatafile() description)
363 # First argument can be a path or a file handle. In case of a file handle it
364 # will just write the file. In case of path it opens the file before writing and
367 # On failure (file not open) returns 0.
368 # On success returns 1.
371 (my $headerpath, my %header) = @_;
373 return write_data_file($headerpath, '', 0, \%header);
377 # the function to print data to stdout (see readdatafile() description)
379 # On success returns 1.
384 return write_data_file(\*STDOUT, '', 0, \%header);
388 # the function to print data to stdout as html (see readdatafile() description)
390 # On success returns 1.
392 sub printdatafileht {
395 print_html_data(\*STDOUT, \%header);
401 (my $t, my $all) = @_;
402 return url_encode($t, '', $all);
406 # different & simpler implementation than in post library
410 #analyse bbcode text to build tag tree
411 #TODO make [/*] optional!
413 (my $bb, my $printdebug) = @_;
426 $bbtree{"_.name" } = "ht";
427 $bbtree{"_.value" } = '';
428 $bbtree{"_.type" } = "tag";
429 $bbtree{"_.count" } = 0;
430 $bbtree{"_.closed"} = 0;
431 $debug .= debug($printdebug,
433 "<!--GENERATING BBCODE TREE:\n".
434 '[_]automatic tag: [ht]'."\n"
438 my $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
440 if($bb =~ m/\[(\/?)([a-z]+|\*)(=([^\[\]]*))?\]/g) {
448 if ($pre_text ne '') {
449 $debug .= debug($printdebug, "[$new_ind]text: $pre_text\n");
450 $bbtree{$new_ind.'.type' } = 'text';
451 $bbtree{$new_ind.'.value'} = $pre_text;
452 $bbtree{ $ind.'.count'}+= 1;
453 $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
456 if($tag_name =~ /^(fq|tq|br|ni|po|url|i|list|\*)$/) {
457 if ($tag_end ne '') {
459 ($tag_name ne $bbtree{$ind.'.name'}) ||
462 $debug .= debug($printdebug, "[$new_ind]text: $tag\n");
463 $bbtree{$new_ind.'.type' } = 'text';
464 $bbtree{$new_ind.'.value'} = $tag;
465 $bbtree{ $ind.'.count'}+= 1;
466 # $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
469 $debug .= debug($printdebug, "[$new_ind]tag: $tag\n");
470 $bbtree{$new_ind.'.type' } = 'tag';
471 $bbtree{$new_ind.'.name' } = '/'.$tag_name;
472 $bbtree{$new_ind.'.value' } = $tag_value;
473 $bbtree{ $ind.'.count' }+= 1;
474 $bbtree{ $ind.'.closed'} = 1;
476 $ind =~ s/\.[0-9]+$//;
477 # $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
482 $debug .= debug($printdebug, "[$new_ind]tag: $tag\n");
483 $bbtree{$new_ind.'.type' } = 'tag';
484 $bbtree{$new_ind.'.name' } = $tag_name;
485 $bbtree{$new_ind.'.value' } = $tag_value;
486 $bbtree{$new_ind.'.count' } = 0;
487 $bbtree{$new_ind.'.closed'} = 0;
488 $bbtree{ $ind.'.count' }+= 1;
491 # $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
495 $debug .= debug($printdebug, "[$new_ind]text: $tag\n");
496 $bbtree{$new_ind.'.type' } = 'text';
497 $bbtree{$new_ind.'.value'} = $tag;
498 $bbtree{ $ind.'.count'}+= 1;
499 # $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
503 $debug .= debug($printdebug, "[$new_ind]text: $bb\n");
504 $bbtree{$new_ind.'.type' } = 'text';
505 $bbtree{$new_ind.'.value'} = $bb;
506 $bbtree{ $ind.'.count'}+= 1;
507 # $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
511 my $final_ind = '_.'.$bbtree{"_.count"};
512 $debug .= debug($printdebug, "[$final_ind]automatic tag: [/ht]\n -->\n");
513 $bbtree{$final_ind.'.type' } = "tag";
514 $bbtree{$final_ind.'.name' } = '/ht';
515 $bbtree{ '_.count' }+= 1;
516 $bbtree{ '_.closed'} = 1;
518 return ($debug, %bbtree);
521 #convert tag tree to final text
523 (my $printdebug, my $debug, my $lang, my $bbtree) = @_;
528 my $tags = ($lang eq 'html') ? tags_html : tags_bbcode;
529 my $escape = ($lang eq 'html');
531 # $debug .= debug($printdebug, "\n****\n");
532 # foreach my $iiii (keys %tags) {
533 # $debug .= debug($printdebug, $iiii.'='.$tags->{$iiii}."\n");
535 # $debug .= debug($printdebug, "****\n");
540 $debug .= debug($printdebug, "\n<!--PROCESSING BBCODE TREE:\n");
542 while ($level >= 0) {
544 $debug .= debug($printdebug, "[$level:$ind:".int($bbtree->{$ind.'.count'})."]");
546 if ($bbtree->{$ind.'.type'} eq 'text') {
547 my $text = $bbtree->{$ind.'.value'};
548 $debug .= debug($printdebug, "text: ".$text);
549 $out .= $escape ? html_encode_line($text) : $text;
554 elsif ($bbtree->{$ind.'.type'} eq 'tag') {
555 my $name = $bbtree->{$ind.'.name'};
557 if ($name =~ /^\//) {
558 $debug .= debug($printdebug, "tag: [$name]");
560 $indd =~ s/\.([0-9]+)$//;
561 if (exists($tags->{$name.'='}) && ($bbtree->{$indd.'.value'} ne '')) {
562 $out .= $tags->{$name.'='};
564 elsif (exists($tags->{$name})) {
565 $out .= $tags->{$name};
568 $out .= $tags->{'/?'};
569 $debug .= debug($printdebug, "[unknown!]");
572 $ind =~ s/\.([0-9]+)$//;
574 $debug .= debug($printdebug, "[<]");
585 my $value = $bbtree->{$ind.'.value'};
586 if($bbtree->{$ind.'.closed'} ne '') {
587 $debug .= debug($printdebug, "tag: [$name]");
589 if (exists($tags->{$name.'='}) && ($value ne '')) {
590 if (exists($tags->{$name.'='.$value})) {
593 $tags->{$name.'='.$value} .
599 ($escape ? html_entity_encode_dec($value, 1) : $value) .
603 elsif (exists($tags->{$name})) {
604 $out .= $tags->{$name};
607 $out .= $out.$tags->{'?'};
608 $debug .= debug($printdebug, "[unknown!]");
612 $debug .= debug($printdebug, "unclosed tag: [$name]");
613 my $text = $name . (($value ne '') ? ('='.$value) : '');
614 $out .= '['.($escape ? html_encode_line($text) : $text).']';
616 if ($bbtree->{$ind.'.count'} > 0) {
619 $debug .= debug($printdebug, "[>]");
628 $debug .= debug($printdebug, "unknown thing: ".$bbtree->{$ind.'.type'});
629 #should not occur with a correct bbtree
630 #unless unimplemented
631 $ind =~ s/\.([0-9]+)$//;
633 $debug .= debug($printdebug, "[<ui]");
642 if ($goto_next ne '') {
644 $ind =~ s/\.([0-9]+)$//;
646 if (($i < $bbtree->{$ind.'.count'}) and ($1 ne '')){
653 # should not occur with a correct bbtree
654 $debug .= debug($printdebug, "[<$goto_next]");
657 } while ($level >= 0);}
660 $debug .= debug($printdebug, "[>$level:$ind]\n");
663 $debug .= debug($printdebug, "-->\n");
664 return ($debug, $out);
669 (my $bb, my $printdebug) = @_;
674 ($debug, %bbtree) = bbtree($bb, $printdebug);
675 ($debug, $ht) = convtree ($printdebug, $debug, 'html', \%bbtree);
682 (my $bb, my $printdebug) = @_;
687 ($debug, %bbtree) = bbtree($bb, $printdebug);
688 ($debug, $ht) = convtree ($printdebug, $debug, 'bb', \%bbtree);
695 return bb_to_html(@_);
700 return bb_to_bbcode(@_);
709 while ($bb =~ m/###([^#;]*);/g) {
714 if ($value =~ /^att&([0-9]+)$/) {
721 elsif ($value =~ /^vw&([0-9]+)$/) {
728 elsif ($value =~ /^fr&([0-9]+)$/) {
738 $bb = $before . $value . $after;
744 sub html_encode_line {
745 (my $text, my $non_ascii, my $all) = @_;
749 $text =~ s/\r\n/\n/gs;
752 while ($text ne '') {
753 $ind = index($text, "\n");
755 $html .= html_entity_encode_dec(substr($text, 0, $ind), $non_ascii, $all)."<br>\n";
756 $text = substr($text, $ind+1);
760 $html .= html_entity_encode_dec($text, 1);
769 return html_encode_line($_[0], 1);
773 (my $print, my $text) = @_;
783 sub print_html_start {
785 print $fh '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
786 print $fh '<html lang="en">'."\n";
791 print $fh '</html>'."\n";
794 sub print_html_head_start {
796 print $fh ' <head>'."\n";
797 print $fh ' <meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
798 print $fh ' <link rel="icon" type="image/png" href="'.html_entity_encode_dec(FAVICON_PATH(),1).'">'."\n";
799 print $fh ' <link rel="stylesheet" href="'.html_entity_encode_dec(CGI_CSS_PATH(),1).'">'."\n";
802 sub print_html_head_end {
804 print $fh ' </head>'."\n";
807 sub print_html_body_start {
809 print $fh ' <body>'."\n";
810 print $fh ' <a href="/"><img id="botmlogo" src="'.html_entity_encode_dec(CGI_LOGO_PATH(),1).'" alt="'.html_entity_encode_dec(WEBSITE(),1).'"></a>'."\n";
811 print $fh ' <div id="all">'."\n";
814 sub print_html_body_end {
816 print $fh ' </div>'."\n";
817 print $fh ' <a href="/" class="cz">'.html_entity_encode_dec(WEBSITE(),1).'</a>'."\n";
818 print $fh ' </body>'."\n";
821 sub print_html_data {
822 (my $fh, my $data) = @_;
824 foreach my $key (keys %$data) {
825 unless ($key eq 'content') {
826 my $val = $data->{$key};
827 $val =~ s/(\r)?\n/\n /gs; # does the space make sense in HTML anyway?
828 print $fh html_encode_line("$key: $val\n", 1);
831 print $fh html_encode_line("\n".$data->{'content'});
834 sub print_viewer_page {
845 my $frame = int($context->{'frame'});
846 # my $prev_frame = $frame - 1;
847 my $next_frame = $frame + 1;
849 my $story = $settings->{'story'};
850 my $title = $frame_data->{'title'};
851 my $command = ($frame_data->{'command'} ne '') ?
852 $frame_data->{'command'} :
853 $next_frame_data->{'title'};
855 my $access = $context->{'access'};
856 my $password_ok = $context->{'password_ok'};
857 my $static = $context->{'static'};
859 my $text_mode = int($context->{'text_mode'});
860 my $timer_unlocked = int($context->{'timer_unlocked'});
861 my $timer = int($context->{'timer'});
863 my $last_frame = int($state->{'last'});
864 my $ong_state = int($state->{'state'});
866 my $timer_color_h = (($timer_unlocked >= 1) || ($ong_state >= STATE->{'ready'})) ? 'br' : 'ni';
867 my $timer_color_m = (($timer_unlocked >= 2) || ($ong_state >= STATE->{'ready'})) ? 'br' : 'ni';
868 my $timer_color_s = (($timer_unlocked >= 3) || ($ong_state >= STATE->{'ready'})) ? 'br' : 'ni';
874 $timer_s = sprintf('%02d', $timer % 60);
875 $timer_h = int($timer / 60);
876 $timer_m = sprintf('%02d', $timer_h % 60);
877 $timer_h = sprintf('%02d', $timer_h / 60);
879 elsif (($timer >= -15) && ($ong_state >= STATE->{'ready'})) {
890 my $prev_available = (($frame > 0) && $access);
891 my $next_available = ($password_ok || ($next_frame <= $last_frame));
892 my $prefetch_next = (
894 ($next_frame < $last_frame) || ( # avoid unseen trigger!
895 ($next_frame <= $last_frame) &&
896 ($ong_state >= STATE->{'ready'})
900 ($frame == $last_frame) && (
901 ($ong_state == STATE->{'waiting'}) ||
902 ($ong_state == STATE->{'ready'})
908 ($frame < $last_frame) || (
909 ($ong_state >= STATE->{'ready'}) &&
910 $context->{'show_command'}
913 my $show_command_link = ($next_available || (!$access));
914 my $show_command_cursor = ((!$next_available) || ($command eq ''));
915 my $frame_indirect = !(
917 ($frame <= $last_frame) &&
918 ($ong_state > STATE->{'inactive'})
921 my $nextframe_indirect = !($next_frame <= $last_frame);
925 my $base_url = CGI_PATH;
926 my $goto_url = CGI_GOTO_PATH;
927 my $info_url = CGI_INFO_PATH;
928 my $bbcode_url = CGI_BBCODE_PATH;
929 my $timer_url = CGI_TIMER_PATH;
930 my $viewer_full_url = merge_url(
931 {'scheme' => SCHEME(), 'host' => WEBSITE()},
932 {'path' => CGI_VIEWER_PATH()},
935 my $viewer_url = merge_url(
936 {'path' => CGI_VIEWER_PATH()},
939 my $viewer_0_url = merge_url(
940 {'path' => CGI_VIEWER_PATH()},
943 my $viewer_prev_url = merge_url(
944 {'path' => CGI_VIEWER_PATH()},
947 my $viewer_next_url = merge_url(
948 {'path' => CGI_VIEWER_PATH()},
949 {'path' => $next_frame}
951 my $viewer_last_url = merge_url(
952 {'path' => CGI_VIEWER_PATH()},
953 {'path' => ($static ? -1 : $last_frame)}
955 if ($text_mode != TEXT_MODE->{'bb'}) {
956 $bbcode_url = merge_url(
959 'b' => TEXT_MODE->{'bb'}
963 if ($text_mode != TEXT_MODE->{'info'}) {
964 $info_url = merge_url(
967 'b' => TEXT_MODE->{'info'}
974 my $frame_normal_url;
976 if ($frame_data->{'frame'} ne '') {
977 $frame_file = $frame_data->{'frame'};
980 $frame_file = sprintf(
981 $settings->{'frame'},
982 $frame, $frame_data->{'ext'}
985 $frame_normal_url = merge_url(
986 {'path' => CGI_PATH()},
987 {'path' => $frame_file}
989 $frame_url = $frame_indirect ?
991 {'path' => CGI_FRAME_PATH()},
995 $frame_full_url = merge_url(
996 {'scheme' => SCHEME(), 'host' => WEBSITE()},
997 {'path' => $frame_normal_url}
999 if ($nextframe_indirect) {
1000 $frame_next_url = merge_url(
1001 {'path' => CGI_FRAME_PATH()},
1002 {'path' => $next_frame}
1005 elsif ($next_frame_data->{'frame'} ne '') {
1006 $frame_next_url = merge_url(
1007 {'path' => CGI_PATH()},
1008 {'path' => $next_frame_data->{'frame'}}
1012 $frame_next_url = merge_url(CGI_PATH(), sprintf(
1013 $settings->{'frame'}, $next_frame, $next_frame_data->{'ext'}
1018 $password_query = url_query_encode({'p', $settings->{'password'}});
1019 $goto_url = merge_url($goto_url , {'query' => $password_query, 'append_query' => 1});
1020 $info_url = merge_url($info_url , {'query' => $password_query, 'append_query' => 1});
1021 $bbcode_url = merge_url($bbcode_url , {'query' => $password_query, 'append_query' => 1});
1022 $viewer_url = merge_url($viewer_url , {'query' => $password_query, 'append_query' => 1});
1023 $viewer_0_url = merge_url($viewer_0_url , {'query' => $password_query, 'append_query' => 1});
1024 $viewer_prev_url = merge_url($viewer_prev_url, {'query' => $password_query, 'append_query' => 1});
1025 $viewer_next_url = merge_url($viewer_next_url, {'query' => $password_query, 'append_query' => 1});
1026 $viewer_last_url = merge_url($viewer_last_url, {'query' => $password_query, 'append_query' => 1});
1027 if ($frame_indirect) {
1028 $frame_url = merge_url($frame_url , {'query' => $password_query, 'append_query' => 1});
1030 if ($nextframe_indirect) {
1031 $frame_next_url= merge_url($frame_next_url , {'query' => $password_query, 'append_query' => 1});
1034 my $_base_url = html_entity_encode_dec($base_url , 1);
1035 my $_goto_url = html_entity_encode_dec($goto_url , 1);
1036 my $_info_url = html_entity_encode_dec($info_url , 1);
1037 my $_bbcode_url = html_entity_encode_dec($bbcode_url , 1);
1038 my $_timer_url = html_entity_encode_dec($timer_url , 1);
1039 my $_viewer_full_url = html_entity_encode_dec($viewer_full_url, 1);
1040 my $_viewer_url = html_entity_encode_dec($viewer_url , 1);
1041 my $_viewer_0_url = html_entity_encode_dec($viewer_0_url , 1);
1042 my $_viewer_prev_url = html_entity_encode_dec($viewer_prev_url, 1);
1043 my $_viewer_next_url = html_entity_encode_dec($viewer_next_url, 1);
1044 my $_viewer_last_url = html_entity_encode_dec($viewer_last_url, 1);
1045 my $_frame_url = html_entity_encode_dec($frame_url , 1);
1046 my $_frame_next_url = html_entity_encode_dec($frame_next_url , 1);
1047 my $_frame_full_url = html_entity_encode_dec($frame_full_url , 1);
1049 my $_story = html_entity_encode_dec($story, 1);
1050 my $_title = html_entity_encode_dec($title, 1);
1051 my $_command = html_entity_encode_dec($command, 1);
1053 my $_website_name = html_entity_encode_dec(WEBSITE_NAME(), 1);
1055 if ($text_mode == TEXT_MODE->{'info'}) {
1056 if ($show_command) {
1057 $frame_data->{'command'} = $command;
1059 if ($context->{'access'}) {
1060 $frame_data->{'frame'} = $frame_file;
1064 # everything determined, now start generating
1068 unless (seek($fh, 0, 0)) {
1069 #don't actually fail here
1073 unless (open ($fh, ">:encoding(UTF-8)", encode('locale_fs', $file))) {
1078 print_html_start($fh);
1079 print_html_head_start($fh);
1081 print $fh ' <title>'.$_title;
1082 if ($story ne $title) {
1083 print $fh ' • '.$_story;
1085 print $fh ' • '.$_website_name.'</title>'."\n";
1086 print $fh ' <link rel="index" href="'.$_goto_url.'">'."\n";
1087 print $fh ' <link rel="start" href="'.$_viewer_0_url.'">'."\n";
1088 if ($prev_available) {
1089 print $fh ' <link rel="prev" href="'.$_viewer_prev_url.'">'."\n";
1091 if ($next_available) {
1092 print $fh ' <link rel="next" href="'.$_viewer_next_url.'">'."\n";
1093 if ($prefetch_next) {
1094 print $fh ' <link rel="prefetch" href="'.$_viewer_next_url.'">'."\n";
1095 print $fh ' <link rel="prefetch" href="'.$_frame_next_url.'">'."\n";
1099 print $fh ' <!-- <script src="'.$_timer_url.'"></script> -->'."\n";
1102 print_html_head_end($fh);
1103 print_html_body_start($fh);
1105 print $fh ' <div id="inst" class="ins">'."\n";
1107 print $fh ' <div id="title">'."\n";
1108 print $fh ' <h1 id="titletext">'.$_title.'</h1>'."\n";
1109 print $fh ' </div>'."\n";
1111 print $fh ' </div>'."\n";
1112 print $fh ' <div id="framespace">'."\n";
1114 print $fh ' <img src="'.$_frame_url.'" id="frame" alt="'.$frame.'" title="'.$_title.'">'."\n";
1116 print $fh ' </div>'."\n";
1117 print $fh ' <div id="insb" class="ins">'."\n";
1119 if ($text_mode == TEXT_MODE->{'info'}) {
1120 print $fh ' <div id="chat">'."\n";
1122 print_html_data($fh, $frame_data);
1124 print $fh ' </div>'."\n";
1126 elsif ($text_mode == TEXT_MODE->{'bb'}) {
1127 print $fh ' <div id="chat">'."\n";
1129 print $fh '[quote][center][size=200]'.$_title.'[/size]<br>'."\n";
1130 print $fh '[url='.$_viewer_full_url.'][img]'.$_frame_full_url.'[/img][/url][/center]<br>'."\n";
1131 print $fh html_encode_line(bb_to_bbcode(eval_bb($frame_data->{'content'})));
1132 print $fh '[/quote]'."\n";
1134 print $fh ' </div>'."\n";
1136 elsif ($frame_data->{'content'} ne '') {
1137 print $fh ' <div id="undertext">'."\n";
1138 print $fh bb_to_html(eval_bb($frame_data->{'content'}))."\n";
1139 print $fh ' </div>'."\n";
1142 print $fh ' <div id="command">'."\n";
1145 print $fh ' [<span id="ongh" class="'.$timer_color_h.'">'.$timer_h.'</span>';
1146 print $fh ':<span id="ongm" class="'.$timer_color_m.'">'.$timer_m.'</span>';
1147 print $fh ':<span id="ongs" class="'.$timer_color_s.'">'.$timer_s.'</span>]<br>'."\n";
1150 if ($show_command_link) {
1151 print $fh '<a href="'.($access ? $_viewer_next_url : $_viewer_last_url).'">';
1153 if ($show_command) {
1154 print $fh $_command;
1156 if ($show_command_cursor) {
1157 print $fh '<span class="inp">_</span>';
1159 if ($show_command_link) {
1163 print $fh " </div>\n";
1165 print $fh ' <div id="underlinks">'."\n ";
1167 unless (($frame == 0) && $static) {
1168 print $fh '<a href="'.$_base_url.'">Once again</a> | ';
1170 if ($prev_available) {
1171 print $fh '<a href="'.$_viewer_prev_url.'">Before</a> | ';
1173 unless ($frame == $last_frame) {
1174 print $fh '<a href="'.$_viewer_last_url.'">Now</a> | ';
1176 print $fh '<a href="'.$_goto_url.'">GOTO</a>'."\n";
1177 print $fh ' <span style="float: right;">'."\n ";
1178 if ($text_mode != TEXT_MODE->{'normal'}) {
1179 print $fh '<a href="'.$_viewer_url.'">Without</a> | ';
1181 print $fh '<a href="'.$_info_url.'">Info</a> | ';
1182 print $fh '<a href="'.$_bbcode_url.'">BB</a>';
1183 print $fh "\n </span>\n";
1185 print $fh " </div>\n";
1186 print $fh " </div>\n";
1188 print_html_body_end($fh);
1189 print_html_end($fh);
1192 unless (ref($file)) {
1196 truncate ($fh , tell($fh));
1214 unless (open ($fh, ">:encoding(UTF-8)", encode('locale_fs', WWW_INDEX_PATH()))) {
1218 # normal running story
1219 if ($state > STATE->{'inactive'}) {
1220 my %frame_data = read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), 0));
1221 my %next_frame_data= read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), 1));
1222 my %default = read_data_file(DATA_DEFAULT_PATH());
1224 %frame_data = merge_settings(\%default, \%frame_data);
1225 %next_frame_data= merge_settings(\%default, \%next_frame_data);
1227 $r = print_viewer_page(
1233 'timer_unlocked' => 3, # not relevant
1234 'timer' => 0, # not relevant
1244 # no conditions met, pretend a normal Apache2 index
1245 elsif ($pass != 1) {
1246 my $index_of = CGI_PATH;
1247 $index_of =~ s/\/$//g;
1249 my $_index_of = html_entity_encode_dec($index_of, 1);
1252 print_html_start ($fh);
1253 print $fh ' <head>'."\n";
1254 print $fh ' <meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
1255 print $fh ' <title>Index of '.$_index_of.'</title>'."\n";
1256 print $fh ' </head>'."\n";
1257 print $fh ' <body>'."\n";
1258 print $fh ' <h1>Index of '.$_index_of.'</h1>'."\n";
1259 print $fh ' <table>'."\n";
1260 print $fh ' <tr>'."\n";
1261 print $fh ' <th><img src="/icons/blank.gif" alt="[ICO]"></th>'."\n";
1262 print $fh ' <th><a href="?C=N;O=D">Name</a></th>'."\n";
1263 print $fh ' <th><a href="?C=M;O=A">Last modified</a></th>'."\n";
1264 print $fh ' <th><a href="?C=S;O=A">Size</a></th>'."\n";
1265 print $fh ' <th><a href="?C=D;O=A">Description</a></th>'."\n";
1266 print $fh ' </tr><tr>'."\n";
1267 print $fh ' <th colspan="5"><hr></th>'."\n";
1268 print $fh ' </tr><tr>'."\n";
1269 print $fh ' <td valign="top"><img src="/icons/back.gif" alt="[DIR]"></td>'."\n";
1270 print $fh ' <td><a href="/">Parent Directory</a></td>'."\n";
1271 print $fh ' <td> </td>'."\n";
1272 print $fh ' <td align="right"> - </td>'."\n";
1273 print $fh ' <td> </td>'."\n";
1274 print $fh ' </tr><tr>'."\n";
1275 print $fh ' <td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td>'."\n";
1276 print $fh ' <td><a href="2words/">2words/</a></td>'."\n";
1277 print $fh ' <td align="right">'.INTF_DATE.' </td>'."\n";
1278 print $fh ' <td align="right"> - </td><td> </td>'."\n";
1279 print $fh ' </tr><tr>'."\n";
1280 print $fh ' <td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td>'."\n";
1281 print $fh ' <td><a href="coin/">coin/</a></td>'."\n";
1282 print $fh ' <td align="right">'.COIN_DATE.' </td>'."\n";
1283 print $fh ' <td align="right"> - </td><td> Coincidence </td>'."\n";
1284 print $fh ' </tr><tr>'."\n";
1285 print $fh ' <th colspan="5"><hr></th>'."\n";
1286 print $fh ' </tr>'."\n";
1287 print $fh ' </table>'."\n";
1288 print $fh ' <address>Apache/2.2.22 (Debian) Server at '.WEBSITE.' Port 80</address>'."\n";
1289 print $fh ' /body>'."\n";
1290 print_html_end ($fh);