'print_html_head_start', 'print_html_head_end',
'print_html_body_start', 'print_html_body_end',
'print_viewer_page',
- 'write_index',
+ 'write_index', 'write_static_viewer_page', 'write_static_goto',
'ong',
'eval_bb', 'bb_to_bbcode', 'bb_to_html'
-
- ,
- 'readdatafile', 'writedatafile', 'printdatafile', # TO REMOVE
- 'entityencode', # TO REMOVE
- 'printdatafileht', # TO REMOVE ???
- 'gethttpheader', 'getcgi', # TO REMOVE
- 'urldecode', # TO REMOVE
- 'urlencode', # TO REMOVE
- 'linehtml', # TO REMOVE
- 'bb2ht', 'bb2bb' # TO REMOVE
);
###PERL_LIB: use lib /botm/lib/bsta
use botm_common (
+ 'HTTP_STATUS',
'url_query_decode', 'url_query_encode',
'url_decode', 'url_encode',
'html_entity_encode_dec',
'merge_url',
'read_header_env',
'read_data_file', 'write_data_file',
- 'join_path'
+ 'join_path',
+ 'copy_encoded', 'open_encoded',
+ 'http_header_line', 'http_status',
+ 'http_header_status', 'http_header_allow', 'http_header_location'
);
-use File::Copy;
###PERL_PATH_SEPARATOR: PATH_SEPARATOR = /
###PERL_CGI_LOGO_PATH: CGI_LOGO_PATH = /bsta/botmlogo.png
###PERL_CGI_TIMER_PATH: CGI_TIMER_PATH = /bsta/timer.js
###PERL_CGI_VIEWER_PATH: CGI_VIEWER_PATH = /bsta/v
+###PERL_CGI_WORDS_PATH: CGI_WORDS_PATH = /bsta/w
###PERL_DATA_PATH: DATA_PATH = /botm/data/bsta/
###PERL_DATA_ATTACH_PATH: DATA_ATTACH_PATH = /botm/data/bsta/a
###PERL_DATA_DEFAULT_PATH: DATA_DEFAULT_PATH = /botm/data/bsta/default
###PERL_DATA_LIST_PATH: DATA_LIST_PATH = /botm/data/bsta/list
###PERL_DATA_NOACCESS_PATH: DATA_NOACCESS_PATH = /botm/data/bsta/noaccess
+###PERL_DATA_STATE_PATH: DATA_STATE_PATH = /botm/data/bsta/state
+###PERL_DATA_WORDS_PATH: DATA_WORDS_PATH = /botm/data/bsta/words/
###PERL_WWW_PATH: WWW_PATH = /botm/www/
###PERL_WWW_INDEX_PATH: WWW_INDEX_PATH = /botm/www/1190/bsta/index.htm
###PERL_INTF_CREDITS: INTF_CREDITS = Online interface © Balthasar Szczepański; AGPL 3 license
###PERL_SOURCE_URL: SOURCE_URL = http://bicyclesonthemoon.info/git-projects/?p=ott/bsta
+###PERL_COMMENT_PAGE_LENGTH:COMMENT_PAGE_LENGTH= 16
+
use constant STATE => {
'inactive' => 0,
'waiting' => 1,
'normal' => 0,
'bb' => 1,
'info' => 2,
+ 'words' => 3
};
use constant CHAT_STATE => {
'disconnected' => 0,
};
use constant tags_bbcode => {
- 'ht' => '',
- '/ht' => '',
- 'fq' => '[quote]',
- '/fq' => '[/quote]',
- 'tq' => '[quote]',
- '/tq' => '[/quote]',
- 'ni' => '[color=#0057AF]',
- '/ni' => '[/color]',
- 'br' => '[color=#BB6622]',
- '/br' => '[/color]',
- 'po' => '[color=#FF8800]',
- '/po' => '[/color]',
- 'url' => '[url]',
- 'url=' => '[url=',
- 'url/=' => ']',
- '/url' => '[/url]',
- 'i' => '[i]',
- '/i' => '[/i]',
- 'list' => '[list]',
- 'list=' => '[list=',
- 'list/='=> ']',
- '/list' => '[/list]',
- '*' => '[*]',
- '/*' => '[/*]',
- '?' => '[unknown!]',
- '/?' => '[/unknown!]',
+ 'ht' => '',
+ '/ht' => '',
+ 'fq' => '[quote]',
+ '/fq' => '[/quote]',
+ 'tq' => '[quote]',
+ '/tq' => '[/quote]',
+ 'quote' => '[quote]',
+ 'quote=' => '[quote="',
+ 'quote/='=> '"]',
+ '/quote' => '[/quote]',
+ 'ni' => '[color=#0057AF]',
+ '/ni' => '[/color]',
+ 'br' => '[color=#BB6622]',
+ '/br' => '[/color]',
+ 'po' => '[color=#FF8800]',
+ '/po' => '[/color]',
+ 'url' => '[url]',
+ 'url=' => '[url=',
+ 'url/=' => ']',
+ '/url' => '[/url]',
+ 'i' => '[i]',
+ '/i' => '[/i]',
+ 'list' => '[list]',
+ 'list=' => '[list=',
+ 'list/=' => ']',
+ '/list' => '[/list]',
+ '*' => '[*]',
+ '/*' => '[/*]',
+ '?' => '[unknown!]',
+ '/?' => '[/unknown!]',
};
use constant tags_html => {
'ht' => '',
'/fq' => '</div>',
'tq' => '<div class="tq">',
'/tq' => '</div>',
+ 'quote' => '<div class="opomba"><div class="opomba_text">',
+ 'quote=' => '<div class="opomba"><div class="opomba_info"><b>',
+ 'quote/='=> '</b> wrote:</div><div class="opomba_text">',
+ '/quote' => '</div></div>',
'ni' => '<span class="ni">',
'/ni' => '</span>',
'br' => '<span class="br">',
# arguments: 1 - header fields, 2 - page title, 3 - error message, 4 method
sub failpage {
(my $header, my $title, my $message, my $method, my $hyperlink) = @_;
- if($header ne ''){
+
+ if (ref($header)) {
+ foreach my $header_name (keys %$header) {
+ print http_header_line($header_name, $header->{$header_name});
+ }
+ }
+ elsif($header ne '') {
print $header;
}
if($method eq 'HEAD') {
sub fail_method {
(my $method, my $allowed) = @_;
- my $header = "Status: 405 Method Not Allowed\n";
- if ($allowed ne '') {
- $header .= "Allow: $allowed\n";
- }
+ my $status = http_status(HTTP_STATUS->{'method_not_allowed'});
+ my $header =
+ http_header_line('status', $status) .
+ http_header_allow($allowed);
+
return failpage(
$header,
- "405 Method Not Allowed",
+ $status,
"The interface does not support the $method method.",
$method
);
{
(my $method, my $content_type) = @_;
+ my $status = http_status(HTTP_STATUS->{'unsupported_media_type'});
+ my $header = http_header_line('status', $status);
+
return failpage(
- "Status: 415 Unsupported Media Type\n",
- "415 Unsupported Media Type",
+ $header,
+ $status,
"Unsupported Content-type: $content_type.",
$method
);
{
(my $method, my $type, my $path) = @_;
+ my $status = http_status(HTTP_STATUS->{'not_found'});
+ my $header = http_header_line('status', $status);
+
return failpage(
- "Status: 404 Not Found\n",
- "404 Not Found",
+ $header,
+ $status,
"Can't open ".
($type ne '' ? $type : 'file').
($path ne '' ? ': "'.$path.'"' : '').
{
(my $method, my $ID) = @_;
+ my $status = http_status(HTTP_STATUS->{'not_found'});
+ my $header = http_header_line('status', $status);
+
return failpage(
- "Status: 404 Not Found\n",
- "404 Not Found",
+ $header,
+ $status,
"Attachment $ID not found.",
$method
);
sub fail_500
{
(my $method, my $text) = @_;
+
+ my $status = http_status(HTTP_STATUS->{'internal_server_error'});
+ my $header = http_header_line('status', $status);
+
return failpage(
- "Status: 500 Internal Server Error\n",
- "500 Internal Server Error",
+ $header,
+ $status,
$text,
$method
);
sub redirect
{
(my $method, my $uri, my $code) = @_;
+ my $header;
my $status;
if ($code eq '') {
- $code = 302
- }
- $code = int($code);
- if ($code == 301) {
- $status = '301 Moved Permanently';
- }
- elsif ($code == 302) {
- $status = '302 Found';
- }
- elsif ($code == 303) {
- $status = '303 See Other';
- }
- elsif ($code == 307) {
- $status = '307 Temporary Redirect';
- }
- elsif ($code == 308) {
- $status = '308 Permanent Redirect';
- }
- else{
- $status = "$code Redirect";
+ $code = HTTP_STATUS->{'found'};
}
+ # 301 Moved Permanently
+ # 302 Found
+ # 303 See Other
+ # 307 Temporary Redirect
+ # 308 Permanent Redirect
+ $status = http_status($code);
+ $header = http_header_line('status', $status);
+ $header .= http_header_location($uri);
+
return failpage(
- "Status: $status\nLocation: $uri\n",
+ $header,
$status,
'',
$method,
return %final_settings;
}
-# TO REMOVE
-# function to encode entities, decimal,
-sub entityencode {
- (my $t, my $all) = @_;
- return html_entity_encode_dec($t, 1, $all);
-}
-
-# TO REMOVE
-# function to get values of http header fields. Returns a hash. names of header
-# fields are lowercase
-sub gethttpheader {
- (my $env) = @_;
-
- return read_header_env($env);
-}
-
-# TO REMOVE
-# The function to get CGI parameters from string.
-# Format is: name=url_encoded_value&name=url_encoded_value& ... &name=url_encoded_value
-sub getcgi {
- return url_query_decode($_[0]);
-}
-
-# TO REMOVE
-# Function for decoding URL-encoded text
-sub urldecode {
- return url_decode($_[0]);
-}
-
-# TO REMOVE
-# Function to read data from datafiles.
-# Very similar to http header file reading. (function readheaderfile() in proxy
-# library)
-#
-# Differences:
-#
-# 1. After field name and colon there must be exactly one whitespace (space or
-# tab). Any other leading or trailing whitespace (but not the newline character
-# at the end of the line) is treated as part of the field value.
-#
-# 2. Instead of colon an equal sign can be used. The number of whitespaces after
-# it is then zero and not one.
-#
-# 3. When header field is split into multiple lines the next lines must start
-# with exactly one whitespace (tab or space) Any other leading or trailing
-# whitespace (but not the newline character at the end of the line) is treated
-# as part of the field value. the lines will be joined with a newline between
-# them.
-#
-# 4. When the same field name appears it replaces the previous one.
-#
-# 5. Line separator is LF and not CR LF. The CR character is treated as part of
-# the field value.
-#
-# 6. After the end of header (double newline) all next lines are treated as the
-# value of the "content" field.
-#
-# Returns a hash containing the values.
-# Names are case sensitive and are converted to lowercase
-#
-# Argument can be a path or a file handle. In case of a file handle it will just
-# read the file. In case of path it opens the file before reading and closes
-# after. On failure (file not open) returns empty hash.
-#
-sub readdatafile {
- (my $datapath) = @_;
-
- return read_data_file($datapath);
-}
-
-# TO REMOVE
-# the function to write data to datafiles (see readdatafile() description)
-#
-# First argument can be a path or a file handle. In case of a file handle it
-# will just write the file. In case of path it opens the file before writing and
-# closes after.
-#
-# On failure (file not open) returns 0.
-# On success returns 1.
-#
-sub writedatafile {
- (my $headerpath, my %header) = @_;
-
- return write_data_file($headerpath, '', 0, \%header);
-}
-
-# TO REMOVE
-# the function to print data to stdout (see readdatafile() description)
-#
-# On success returns 1.
-#
-sub printdatafile {
- (my %header) = @_;
-
- return write_data_file(\*STDOUT, '', 0, \%header);
-}
-
-# TO REMOVE
-# the function to print data to stdout as html (see readdatafile() description)
-#
-# On success returns 1.
-#
-sub printdatafileht {
- (my %header) = @_;
-
- print_html_data(\*STDOUT, \%header);
- return 1;
-}
-
-# TO REMOVE
-sub urlencode {
- (my $t, my $all) = @_;
- return url_encode($t, '', $all);
-}
-
# BB code stuff
# different & simpler implementation than in post library
while ($bb ne '') {
my $new_ind = $ind.'.'.$bbtree{$ind.'.count'};
- if($bb =~ m/\[(\/?)([a-z]+|\*)(=([^\[\]]*))?\]/g) {
+ if($bb =~ m/\[(\/?)([A-Za-z]+|\*)(=([^\[\]]*))?\]/g) {
$pre_text = $`;
$tag = $&;
$tag_end = $1;
- $tag_name = $2;
+ $tag_name = lc($2);
$tag_value = $4;
$bb = $';
+ if ($tag_value =~ /^"(.*)"$/) {
+ $tag_value = $1;
+ }
if ($pre_text ne '') {
$debug .= debug($printdebug, "[$new_ind]text: $pre_text\n");
$new_ind = $ind.'.'.$bbtree{$ind.'.count'};
}
- if($tag_name =~ /^(fq|tq|br|ni|po|url|i|list|\*)$/) {
+ if($tag_name =~ /^(fq|tq|quote|br|ni|po|url|i|list|\*)$/) {
if ($tag_end ne '') {
if (
($tag_name ne $bbtree{$ind.'.name'}) ||
return $ht;
}
-# TO REMOVE
-sub bb2ht {
- return bb_to_html(@_);
-}
-
-# TO REMOVE
-sub bb2bb {
- return bb_to_bbcode(@_);
-}
-
sub eval_bb {
- (my $bb, my $full_url) = @_;
+ (my $bb, my $full_url, my $password) = @_;
my $value;
my $before;
my $after;
else {
$value = '';
}
+ if (($value ne '') && ($password ne '')) {
+ $value = merge_url(
+ $value,
+ {'query' => {'p' => $password}}
+ );
+ }
$bb = $before . $value . $after;
}
return $bb;
return $html;
}
-# TO REMOVE
-sub linehtml {
- return html_encode_line($_[0], 1);
-}
-
sub debug {
(my $print, my $text) = @_;
my $state,
my $settings,
my $frame_data,
- my $next_frame_data
+ my $prev_frame_data,
+ my $next_frame_data,
+ my $words_data,
) = @_;
my $fh;
my $text_mode = int($context->{'text_mode'});
my $timer_unlocked = int($context->{'timer_unlocked'});
my $timer = int($context->{'timer'});
+ # my $words_page = int($context->{'words_page'});
- # my $prev_frame = $frame - 1;
+ my $prev_frame = $frame - 1;
my $next_frame = $frame + 1;
my $story = $settings->{'story'};
my $last_frame = int($state->{'last'});
my $ong_state = int($state->{'state'});
+ my $width = int($frame_data->{'width'});
+ my $height = int($frame_data->{'height'});
+ my $frame_type = $frame_data->{'frametype'};
+
my $timer_color_h = (($timer_unlocked >= 1) || ($ong_state >= STATE->{'ready'})) ? 'br' : 'ni';
my $timer_color_m = (($timer_unlocked >= 2) || ($ong_state >= STATE->{'ready'})) ? 'br' : 'ni';
my $timer_color_s = (($timer_unlocked >= 3) || ($ong_state >= STATE->{'ready'})) ? 'br' : 'ni';
$timer_s = 'EE';
}
+ my $words_posts = int($words_data->{'posts'});
+ my $words_link_text = 'Words'.(($words_posts > 0) ? "[$words_posts]" : '');
+
my $prev_available = (($frame > 0) && $access);
my $next_available = ($launch || $password_ok || ($next_frame <= $last_frame));
+ my $prefetch_prev = (
+ $password_ok ||
+ ($prev_frame < $last_frame) || ( # avoid unseen trigger!
+ ($prev_frame <= $last_frame) &&
+ ($ong_state >= STATE->{'ready'})
+ )
+ );
my $prefetch_next = (
$password_ok ||
($next_frame < $last_frame) || ( # avoid unseen trigger!
);
my $show_command_link = ($next_available || (!$access));
my $show_command_cursor = ((!$next_available) || ($command eq ''));
+ my $show_words = ($password_ok || ($access && !$launch));
+
my $frame_indirect = !(
(!$access) || (
($frame <= $last_frame) &&
($ong_state > STATE->{'inactive'})
)
);
+ my $prevframe_indirect = !($prev_frame <= $last_frame);
my $nextframe_indirect = !($next_frame <= $last_frame);
my $password_query;
);
my $viewer_prev_url = merge_url(
{'path' => CGI_VIEWER_PATH()},
- {'path' => $frame-1}
+ {'path' => $prev_frame}
);
my $viewer_next_url = merge_url(
{'path' => CGI_VIEWER_PATH()},
) :
merge_url (
$viewer_url,
- {'query'=>{
+ {
+ 'query'=>{
'b' => TEXT_MODE->{'bb'}
- }}
+ },
+ 'fragment'=>'insb'
+ }
);
my $info_url = ($text_mode == TEXT_MODE->{'info'}) ?
merge_url(
) :
merge_url (
$viewer_url,
- {'query'=>{
+ {
+ 'query'=>{
'b' => TEXT_MODE->{'info'}
- }}
+ },
+ 'fragment'=>'insb'
+ }
);
+ my $words_url = merge_url (
+ $viewer_url,
+ {
+ 'query'=>{
+ 'b' => TEXT_MODE->{'words'}
+ },
+ 'fragment'=>'insw'
+ }
+ );
my $frame_file;
my $frame_url;
+ my $frame_prev_url;
my $frame_next_url;
my $frame_normal_url;
my $frame_full_url;
{'scheme' => SCHEME(), 'host' => WEBSITE()},
{'path' => $frame_normal_url}
);
+ if ($prevframe_indirect) {
+ $frame_prev_url = merge_url(
+ {'path' => CGI_FRAME_PATH()},
+ {'path' => $prev_frame}
+ );
+ }
+ elsif ($prev_frame_data->{'frame'} ne '') {
+ $frame_prev_url = merge_url(
+ {'path' => CGI_PATH()},
+ {'path' => $prev_frame_data->{'frame'}}
+ );
+ }
+ else {
+ $frame_prev_url = merge_url(CGI_PATH(), sprintf(
+ $settings->{'frame'}, $prev_frame, $prev_frame_data->{'ext'}
+ ));
+ }
if ($nextframe_indirect) {
$frame_next_url = merge_url(
{'path' => CGI_FRAME_PATH()},
if ($password_ok) {
$password_query = url_query_encode({'p', $settings->{'password'}});
- $goto_url = merge_url($goto_url , {'query' => $password_query, 'append_query' => 1});
- $info_url = merge_url($info_url , {'query' => $password_query, 'append_query' => 1});
- $bbcode_url = merge_url($bbcode_url , {'query' => $password_query, 'append_query' => 1});
- $viewer_url = merge_url($viewer_url , {'query' => $password_query, 'append_query' => 1});
- $viewer_0_url = merge_url($viewer_0_url , {'query' => $password_query, 'append_query' => 1});
- $viewer_prev_url = merge_url($viewer_prev_url, {'query' => $password_query, 'append_query' => 1});
- $viewer_next_url = merge_url($viewer_next_url, {'query' => $password_query, 'append_query' => 1});
- $viewer_last_url = merge_url($viewer_last_url, {'query' => $password_query, 'append_query' => 1});
+ $goto_url = merge_url($goto_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $info_url = merge_url($info_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $words_url = merge_url($words_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $bbcode_url = merge_url($bbcode_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $viewer_url = merge_url($viewer_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $viewer_0_url = merge_url($viewer_0_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $viewer_prev_url = merge_url($viewer_prev_url, {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $viewer_next_url = merge_url($viewer_next_url, {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $viewer_last_url = merge_url($viewer_last_url, {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
if ($frame_indirect) {
- $frame_url = merge_url($frame_url , {'query' => $password_query, 'append_query' => 1});
+ $frame_url = merge_url($frame_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ }
+ if ($prevframe_indirect) {
+ $frame_prev_url= merge_url($frame_prev_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
}
if ($nextframe_indirect) {
- $frame_next_url= merge_url($frame_next_url , {'query' => $password_query, 'append_query' => 1});
+ $frame_next_url= merge_url($frame_next_url , {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
}
}
my $_base_url = html_entity_encode_dec($base_url , 1);
my $_goto_url = html_entity_encode_dec($goto_url , 1);
my $_info_url = html_entity_encode_dec($info_url , 1);
+ my $_words_url = html_entity_encode_dec($words_url , 1);
my $_bbcode_url = html_entity_encode_dec($bbcode_url , 1);
my $_timer_url = html_entity_encode_dec($timer_url , 1);
my $_viewer_full_url = html_entity_encode_dec($viewer_full_url, 1);
my $_viewer_next_url = html_entity_encode_dec($viewer_next_url, 1);
my $_viewer_last_url = html_entity_encode_dec($viewer_last_url, 1);
my $_frame_url = html_entity_encode_dec($frame_url , 1);
+ my $_frame_prev_url = html_entity_encode_dec($frame_prev_url , 1);
my $_frame_next_url = html_entity_encode_dec($frame_next_url , 1);
my $_frame_full_url = html_entity_encode_dec($frame_full_url , 1);
- my $_story = html_entity_encode_dec($story, 1);
- my $_title = html_entity_encode_dec($title, 1);
- my $_command = html_entity_encode_dec($command, 1);
+ my $_story = html_entity_encode_dec($story , 1);
+ my $_title = html_entity_encode_dec($title , 1);
+ my $_command = html_entity_encode_dec($command , 1);
+ my $_frame_type = html_entity_encode_dec($frame_type, 1);
my $_website_name = html_entity_encode_dec(WEBSITE_NAME(), 1);
}
}
else {
- unless (open ($fh, ">:encoding(UTF-8)", encode('locale_fs', $file))) {
+ unless (open_encoded($fh, ">:encoding(UTF-8)", $file)) {
return 0;
}
}
print $fh ' <link rel="start" href="'.$_viewer_0_url.'">'."\n";
if ($prev_available) {
print $fh ' <link rel="prev" href="'.$_viewer_prev_url.'">'."\n";
+ if ($prefetch_prev) {
+ print $fh ' <link rel="prefetch" href="'.$_viewer_prev_url.'">'."\n";
+ print $fh ' <link rel="prefetch" href="'.$_frame_prev_url.'">'."\n";
+ }
}
if ($next_available) {
print $fh ' <link rel="next" href="'.$_viewer_next_url.'">'."\n";
print $fh ' </div>'."\n";
print $fh ' <div id="framespace">'."\n";
- print $fh ' <img src="'.$_frame_url.'" id="frame" alt="'.$frame.'" title="'.$_title.'">'."\n";
+ print $fh ' <img src="'.$_frame_url.'" id="frame" class="'.$_frame_type.'" alt="'.$frame.'" title="'.$_title.'" width="'.$width.'" height="'.$height.'">'."\n";
print $fh ' </div>'."\n";
print $fh ' <div id="insb" class="ins">'."\n";
print $fh '[quote][center][size=200]'.$_title.'[/size]<br>'."\n";
print $fh '[url='.$_viewer_full_url.'][img]'.$_frame_full_url.'[/img][/url][/center]<br>'."\n";
- print $fh html_encode_line(bb_to_bbcode(eval_bb($frame_data->{'content'}, 1)));
+ print $fh html_encode_line(
+ bb_to_bbcode(
+ eval_bb(
+ $frame_data->{'content'},
+ 1
+ )
+ )
+ );
print $fh '[/quote]'."\n";
print $fh ' </div>'."\n";
}
elsif ($frame_data->{'content'} ne '') {
print $fh ' <div id="undertext">'."\n";
- print $fh bb_to_html(eval_bb($frame_data->{'content'}), 0)."\n";
+ print $fh bb_to_html(
+ eval_bb(
+ $frame_data->{'content'},
+ 0,
+ $password_ok ? $settings->{'password'} : ''
+ )
+ )."\n";
print $fh ' </div>'."\n";
}
if ($show_timer) {
print $fh ' <span id="timer">';
- print $fh '[<span id="ongh" class="'.$timer_color_h.'">'.$timer_h.'</span>';
- print $fh ':<span id="ongm" class="'.$timer_color_m.'">'.$timer_m.'</span>';
- print $fh ':<span id="ongs" class="'.$timer_color_s.'">'.$timer_s.'</span>]';
+ print $fh '[<span id="ongh" class="hv '.$timer_color_h.'">'.$timer_h.'</span>';
+ print $fh ':<span id="ongm" class="hv '.$timer_color_m.'">'.$timer_m.'</span>';
+ print $fh ':<span id="ongs" class="hv '.$timer_color_s.'">'.$timer_s.'</span>]';
print $fh '</span><br>'."\n";
}
print $fh ' >';
}
print $fh '<a href="'.$_goto_url.'">GOTO</a>'."\n";
print $fh ' <span style="float: right;">'."\n ";
- if ($text_mode != TEXT_MODE->{'normal'}) {
+ if ($text_mode == TEXT_MODE->{'normal'}) {
+ if ($show_words) {
+ print $fh '<a href="'.$_words_url.'">'.$words_link_text.'</a> | ';
+ }
+ }
+ else {
print $fh '<a href="'.$_viewer_url.'">Without</a> | ';
}
print $fh '<a href="'.$_info_url.'">Info</a> | ';
print $fh " </div>\n";
print $fh " </div>\n";
+ if (($text_mode == TEXT_MODE->{'words'}) && $show_words) {
+ print_comments($fh, $context, $settings, $words_data);
+ }
+
print_html_body_end($fh, $ong_state == STATE->{'inactive'});
print_html_end($fh);
return 1;
}
+sub print_comments {
+ (my $fh, my $context, my $settings, my $words_data) = @_;
+
+ my $password_ok = $context->{'password_ok'};
+ my $frame = int($context->{'frame'});
+ my $page = int($context->{'words_page'});
+ my $post_count = int($words_data->{'posts'});
+ my $id_start = $page * COMMENT_PAGE_LENGTH();
+ my $id_stop = $id_start + COMMENT_PAGE_LENGTH();
+ my $older = ($page > 0) ? ($page-1) : '';
+ my $newer;
+ my $password_query;
+ if ($id_stop >= $post_count) {
+ $id_stop = $post_count;
+ }
+ else {
+ $newer = $page+1;
+ }
+ my $links;
+
+ my $words_url = merge_url(
+ {'path' => CGI_VIEWER_PATH()},
+ {
+ 'path' => $frame,
+ 'query' => {'b' => TEXT_MODE->{'words'}},
+ }
+ );
+ my $older_url = merge_url(
+ $words_url,
+ {
+ 'query' => {'i' => $page-1},
+ 'fragment' => 'insw',
+ 'append_query' => 1
+ }
+ );
+ my $newer_url = merge_url(
+ $words_url,
+ {
+ 'query' => {'i' => $page+1},
+ 'fragment' => 'insw',
+ 'append_query' => 1
+ }
+ );
+
+ if ($password_ok) {
+ $password_query = url_query_encode({'p', $settings->{'password'}});
+ $older_url = merge_url($older_url, {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ $newer_url = merge_url($older_url, {'query' => $password_query, 'append_query' => 1, 'preserve_fragment' => 1});
+ }
+
+ my $_post_url = html_entity_encode_dec(CGI_WORDS_PATH(), 1);
+ my $_password = html_entity_encode_dec($settings->{'password'}, 1);
+ my $_older_url = html_entity_encode_dec($older_url, 1);
+ my $_newer_url = html_entity_encode_dec($newer_url, 1);
+
+ if (($older ne '') || ($newer ne '')) {
+ $links .= ' <div class="underlinks">'."\n";
+ $links .= ' ';
+ if ($older ne '') {
+ $links .= '<a href="'.$_older_url.'">Older</a>'
+ }
+ if (($older ne '') && ($newer ne '')) {
+ $links .= ' | ';
+ }
+ if ($newer ne '') {
+ $links .= '<a href="'.$_newer_url.'">Newer</a>';
+ }
+ $links .= "\n";
+ $links .= ' </div>'."\n";
+ }
+
+ print $fh ' <div class="space"></div>'."\n";
+ print $fh ' <div id="insw" class="ins">'."\n";
+
+ print $fh ' <div class="title" id="wordstitle">'."\n";
+ print $fh ' <h1 class="titletext" id="wordstitletext">Words</h1>'."\n";
+ print $fh ' </div>'."\n";
+
+ if ($links ne '') {
+ print $fh $links;
+ }
+
+ print $fh ' <div class="undertext" id="words">'."\n";
+
+ if ($post_count > 0) {
+ for (my $i=$id_start; $i<$id_stop; ++$i) {
+ my $ID = $words_data->{'content'}->[$i];
+ my $post_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $ID);
+ my %post_data = read_data_file($post_path);
+
+ my $post_time = int($post_data{'posttime'});
+ my $edit_time = int($post_data{'edittime'});
+
+ my $post_time_text;
+ my $edit_time_text;
+
+ if ($post_time != 0) {
+ my @time_tab = gmtime($post_time);
+ $post_time_text = sprintf(
+ '%04d.%02d.%02d %02d:%02d:%02d UTC',
+ $time_tab[5]+1900,
+ $time_tab[4]+1,
+ $time_tab[3],
+ $time_tab[2],
+ $time_tab[1],
+ $time_tab[0]
+ );
+ }
+ if (($edit_time !=0) && ($edit_time != $post_time)) {
+ my @time_tab = gmtime($edit_time);
+ $edit_time_text = sprintf(
+ '%04d.%02d.%02d %02d:%02d UTC',
+ $time_tab[5]+1900,
+ $time_tab[4]+1,
+ $time_tab[3],
+ $time_tab[2],
+ $time_tab[1]
+ );
+ }
+ my $quote_url = merge_url(
+ {'path' => CGI_WORDS_PATH()},
+ {
+ 'query' => {
+ 'f' => $frame,
+ 'quote' => $ID,
+ 'p' => ($password_ok ? $settings->{'password'} : '')
+ }
+ }
+ );
+ my $edit_url = merge_url(
+ {'path' => CGI_WORDS_PATH()},
+ {
+ 'query' => {
+ 'f' => $frame,
+ 'edit' => $ID,
+ 'key' => $post_data{'key'},
+ 'username' => $post_data{'name'},
+ 'p' => ($password_ok ? $settings->{'password'} : '')
+ }
+ }
+ );
+ my $remove_url = merge_url(
+ {'path' => CGI_WORDS_PATH()},
+ {
+ 'query' => {
+ 'f' => $frame,
+ 'remove' => $ID,
+ 'key' => $post_data{'key'},
+ 'username' => $post_data{'name'},
+ 'p' => ($password_ok ? $settings->{'password'} : '')
+ }
+ }
+ );
+
+ my $_ID = html_entity_encode_dec($ID, 1);
+ my $_name = html_entity_encode_dec($post_data{'name'}, 1);
+ my $_quote_url = html_entity_encode_dec($quote_url, 1);
+ my $_edit_url = html_entity_encode_dec($edit_url, 1);
+ my $_remove_url = html_entity_encode_dec($remove_url, 1);
+
+ print $fh ' <div id="'.$_ID.'"class="opomba">'."\n";
+ print $fh ' <div class="opomba_info">'."\n";
+ print $fh ' <a href="#'.$_ID.'" class="bi hu">'.$i.': '.$_name;
+ if ($post_time_text ne '') {
+ print $fh ' • '.$post_time_text;
+ }
+ if ($edit_time_text ne '') {
+ print $fh ' • '.$edit_time_text;
+ }
+ print $fh '</a>'."\n";
+ print $fh ' <div class="pr">'."\n";
+ print $fh ' <a href="'.$_quote_url.'" class="bi hu">quote</a> | <a href="'.$_edit_url.'" class="bi hu">edit</a> | <a href="'.$_remove_url.'" class="bi hu">remove</a>'."\n";
+ print $fh ' </div>'."\n";
+ print $fh ' </div>'."\n";
+ print $fh ' <div class="opomba_text">'."\n";
+ print $fh bb_to_html(
+ eval_bb(
+ $post_data{'content'},
+ 0,
+ $password_ok ? $settings->{'password'} : ''
+ )
+ )."\n";
+ print $fh ' </div>'."\n";
+ print $fh ' </div>'."\n";
+ print $fh ' <br>'."\n";
+ }
+ }
+
+ print $fh ' <form method="post" action="'.$_post_url.'">'."\n";
+ print $fh ' <b>Your words:</b>'."\n";
+ print $fh ' <textarea class="inta" name="words" rows="4"></textarea>'."\n";
+ print $fh ' <table cellpadding="0" cellspacing="0" border="0"><tr>'."\n";
+ print $fh ' <td><b>Your name: </b></td>'."\n";
+ print $fh ' <td><input class="intx" type="text" name="username" value=""></td>'."\n";
+ print $fh ' <td></td>'."\n";
+ print $fh ' </tr><tr>'."\n";
+ print $fh ' <td><b>Optional password: </b></td>'."\n";
+ print $fh ' <td><input class="intx" type="password" name="password" value=""></td>'."\n";
+ print $fh ' <td>(if you want to edit later)</td>'."\n";
+ print $fh ' </tr><tr>'."\n";
+ print $fh ' <td><b>Leave this empty: </b></td>'."\n";
+ print $fh ' <td><input class="intx" type="text" name="password2" value=""></td>'."\n";
+ print $fh ' <td>'."\n";
+ print $fh ' <input class="inbt" type="submit" name="post" value="Send">'."\n";
+ print $fh ' <input class="inbt" type="submit" name="preview" value="Preview">'."\n";
+ print $fh ' </td>'."\n";
+ print $fh ' </tr></table>'."\n";
+ print $fh ' <input type="hidden" name="f" value="'.$frame.'">'."\n";
+ if ($password_ok) {
+ print $fh ' <input type="hidden" name="p" value="'.$_password.'">'."\n";
+ }
+ print $fh ' </form>'."\n";
+ print $fh ' </div>'."\n";
+
+ if ($links ne '') {
+ print $fh $links;
+ }
+
+ print $fh ' </div>'."\n";
+}
+
sub write_index {
(
my $state,
my $r = 1;
my $ong_state = int($state->{'state'});
- unless (open ($fh, ">:encoding(UTF-8)", encode('locale_fs', WWW_INDEX_PATH()))) {
+ unless (open_encoded($fh, ">:encoding(UTF-8)", WWW_INDEX_PATH())) {
return 0;
}
my %frame_data = read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), 0));
my %next_frame_data= read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), 1));
my %default = read_data_file(DATA_DEFAULT_PATH());
+ my %words_data = read_data_file(
+ join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), 0),
+ '', # encoding
+ 0, # no header
+ 1, # header only
+ 1, # as list
+ );
%frame_data = merge_settings(\%default, \%frame_data);
%next_frame_data= merge_settings(\%default, \%next_frame_data);
$r = print_viewer_page(
$fh,
{
- 'launch' => 0,
- 'frame' => 0,
- 'access' => 1,
- 'password_ok' => 0,
+ 'launch' => 0,
+ 'frame' => 0,
+ 'access' => 1,
+ 'password_ok' => 0,
'timer_unlocked' => 3, # not relevant
- 'timer' => 0, # not relevant
- 'static' => 1,
- 'show_command' => 1
+ 'timer' => 0, # not relevant
+ 'static' => 1,
+ 'show_command' => 1,
+ 'text_mode' => TEXT_MODE->{'normal'},
+ 'words_page' => 0 # not relevant
},
$state,
$settings,
\%frame_data,
- \%next_frame_data
+ \%default, # prev
+ \%next_frame_data,
+ \%words_data
);
}
# no conditions met, pretend a normal Apache2 index
$r = print_viewer_page(
$fh,
{
- 'launch' => 1,
- 'frame' => 0,
- 'access' => 1,
- 'password_ok' => 0,
+ 'launch' => 1,
+ 'frame' => 0,
+ 'access' => 1,
+ 'password_ok' => 0,
'timer_unlocked' => 3,
- 'timer' => 0,
- 'static' => 1,
- 'show_command' => 1,
+ 'timer' => 0,
+ 'static' => 1,
+ 'show_command' => 1,
+ 'text_mode' => TEXT_MODE->{'normal'},
+ 'words_page' => 0 # not relevant
},
$state,
$settings,
\%frame_data,
- \%next_frame_data
+ \%default, # prev
+ \%next_frame_data,
+ {'posts' => 0} # words_data
);
return $r;
}
print $fh ' <img src="/icons/folder.gif" alt="[DIR]"> <a href="'.$_coin_url.'">coin/</a> '.$_coin_date.' - '.$_coin_server."\n";
}
elsif ($show_yb) {
- print $fh ' <img src="/icons/folder.gif" alt="[DIR]"> <a href="#">yyyyb/</a>'."\n";
+ print $fh ' <img src="/icons/folder.gif" alt="[DIR]"> <a href="'.$_2words_url.'">yyyyb/</a>'."\n";
}
if ($undertext ne '') {
print $fh ' '.$_undertext."\n";
print $fh ':<span id="ongs" class="'.$timer_color.'">'.$timer.'</span>]<br>'."\n";
if ($undertext ne '') {
- print $fh '>'.$_undertext.'<span class="inp">_</span>'."\n";
+ print $fh '><a href="'.$_2words_url.'">'.$_undertext.'</a><span class="inp">_</span>'."\n";
}
print $fh " </div>\n";
}
return $r
}
+sub write_static_viewer_page {
+ (
+ my $frame,
+ my $state_ref,
+ my $settings_ref,
+ my $default_ref,
+ my $frame_data_ref,
+ my $prev_frame_data_ref,
+ my $next_frame_data_ref,
+ my $words_data_ref
+ ) = @_;
+
+ my %state;
+ my %settings;
+ my %default;
+ my %frame_data;
+ my %prev_frame_data;
+ my %next_frame_data;
+ my %words_data;
+
+ my $file;
+
+ $frame = int($frame);
+ my $prev_frame = $frame -1;
+ my $next_frame = $frame +1;
+
+ %state = (ref ($state_ref)) ?
+ %$state_ref :
+ read_data_file(DATA_STATE_PATH());
+ my $ong_state = int($state{'state'});
+ my $last_frame = int($state{'last'});
+
+ unless ($ong_state > STATE->{'inactive'}) {
+ return 0;
+ }
+ unless (
+ ($frame >= 0) && (
+ ($frame < $last_frame) || (
+ ($frame <= $last_frame) &&
+ ($ong_state >= STATE->{'end'})
+ )
+ )
+ ) {
+ return 0;
+ }
+
+ %settings = (ref ($settings_ref)) ?
+ %$settings_ref :
+ read_data_file(DATA_SETTINGS_PATH());
+ %default = (ref ($default_ref)) ?
+ %$default_ref :
+ read_data_file(DATA_DEFAULT_PATH());
+
+ %frame_data = (ref ($frame_data_ref)) ?
+ %$frame_data_ref :
+ read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), $frame));
+
+ %prev_frame_data = (ref ($prev_frame_data_ref)) ?
+ %$prev_frame_data_ref : (
+ ($prev_frame >= 0) ?
+ read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), $prev_frame)) :
+ %default
+ );
+
+ %next_frame_data = (ref ($next_frame_data_ref)) ?
+ %$next_frame_data_ref : (
+ (($next_frame < $last_frame) || (
+ ($next_frame <= $last_frame) &&
+ ($next_frame >= STATE->{'end'})
+ )) ?
+ read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), $next_frame)) :
+ %default
+ );
+
+ %frame_data = merge_settings(\%default, \%frame_data);
+ %prev_frame_data = merge_settings(\%default, \%prev_frame_data);
+ %next_frame_data = merge_settings(\%default, \%next_frame_data);
+
+ %words_data = (ref ($words_data_ref)) ?
+ %$words_data_ref :
+ read_data_file(
+ join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $frame), # file
+ '', # encoding
+ 0, # no header
+ 1, # header only
+ 1, # as list; not relevant
+ );
+
+ if ($frame_data{'page'} ne '') {
+ $file = $frame_data{'page'}
+ }
+ else {
+ $file = sprintf(
+ $settings{'frame'},
+ $frame, 'htm'
+ );
+ }
+ $file = join_path(PATH_SEPARATOR(), WWW_PATH(), $file);
+
+ return print_viewer_page(
+ $file,
+ {
+ 'launch' => 0,
+ 'frame' => $frame,
+ 'access' => 1,
+ 'password_ok' => 0,
+ 'timer_unlocked'=> 3, # not relevant
+ 'timer' => 0, # not relevant
+ 'static' => 1,
+ 'show_command' => 1,
+ 'text_mode' => TEXT_MODE->{'normal'},
+ 'words_page' => 0, # not relevant
+ },
+ \%state,
+ \%settings,
+ \%frame_data,
+ \%prev_frame_data,
+ \%next_frame_data,
+ \%words_data
+ );
+}
+
+sub write_static_goto {
+
+}
-# ONG the frame + attachment & stiff. NOT update state file.
+# ONG the frame + attachment & stuff. NOT update state file.
sub ong {
(
my $ID, my $ongtime, my $timer, my $update, my $print,
$write_data = 1;
}
if ($write_data) {
- $r = write_data_file($frame_data_path, '', '', \%frame_data);
- }
- unless ($r) {
- return $r;
+ $r = write_data_file($frame_data_path, \%frame_data);
+ unless ($r) {
+ print STDERR "fail writing $frame_data_path\n";
+ if ($print) {
+ print "write frame data fail\n";
+ }
+ return $r;
+ }
}
$goto_list{'title-' .$frame} = $frame_full_data{'title'};
$goto_list{'ongtime-'.$frame} = $frame_full_data{'ongtime'};
- $r = write_data_file(DATA_LIST_PATH(), '', '', \%goto_list);
+ $r = write_data_file(DATA_LIST_PATH(), \%goto_list);
unless ($r) {
+ print STDERR "fail writing ".DATA_LIST_PATH()."\n";
+ if ($print) {
+ print "write GOTO list fail\n";
+ }
return $r;
}
}
if ($print) {
print $in_path.' -> '.$out_path;
}
- $r = copy($in_path, $out_path);
+ $r = copy_encoded($in_path, $out_path);
if ($print) {
print (($r) ? " OK\n" : " FAIL\n");
}
unless ($r) {
+ print STDERR "fail copy $in_path $out_path\n";
return $r
}
}