ScriptAlias ###CONF_CGI_GOTO; ###CONF_BIN_GOTO;
ScriptAlias ###CONF_CGI_INFO; ###CONF_BIN_INFO;
ScriptAlias ###CONF_CGI_VIEWER; ###CONF_BIN_VIEWER;
+ScriptAlias ###CONF_CGI_WORDS; ###CONF_BIN_WORDS;
<Directory ###CONF_BIN;>
Require all granted
border-color: #bb6622;
}
-div.comment
+div.opomba
{
text-align: left;
border: solid #0057af 4px;
background-color: #0057af;
}
-div.comment:hover
+div.opomba:hover
{
border-color: #bb6622;
background-color: #bb6622;
}
-div.commentinfo
+div.opomba_info
{
color: #ffffff!important;
/* font-weight: bold; */
}
-div.commenttext
+div.opomba_text
{
background-color: #ffffff;
color: #000000;
font-family: monospace;
}
+div.underlinks
+{
+ text-align: left;
+ padding: 8px;
+ margin: 0px;
+ border: 0px;
+ font-family: monospace;
+}
+
span.inp
{
animation: inp 2380ms step-start infinite;
###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_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,
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 $words_page = int($context->{'words_page'});
# my $prev_frame = $frame - 1;
my $next_frame = $frame + 1;
) :
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'=>{
+ {
+ 'query'=>{
'b' => TEXT_MODE->{'words'}
- }}
+ },
+ 'fragment'=>'insw'
+ }
);
my $frame_file;
my $frame_url;
print $fh " </div>\n";
if ($text_mode == TEXT_MODE->{'words'}) {
- # TODO: HERE PRINT COMMENTS
+ print_comments($fh, $context, $settings, $words_data);
}
print_html_body_end($fh, $ong_state == STATE->{'inactive'});
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 $_post_url = html_entity_encode_dec(CGI_WORDS_PATH(), 1);
+ my $_password = html_entity_encode_dec($settings->{'password'}, 1);
+
+ 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";
+
+ print $fh ' <div class="undertext" id="words">'."\n";
+
+ if ($post_count > 0) {
+ my $start = $page * COMMENT_PAGE_LENGTH();
+ my $stop = $start + COMMENT_PAGE_LENGTH();
+ if ($stop > $post_count) {
+ $stop = $post_count;
+ }
+ for (my $i=$start; $i<$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 UTC',
+ $time_tab[5]+1900,
+ $time_tab[4]+1,
+ $time_tab[3],
+ $time_tab[2],
+ $time_tab[1]
+ );
+ }
+ 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 $_ID = html_entity_encode_dec($ID, 1);
+ my $_name = html_entity_encode_dec($post_data{'name'}, 1);
+
+ print $fh ' <div id="'.$_ID.'"class="opomba">'."\n";
+ print $fh ' <div class="opomba_info">'."\n";
+ print $fh ' '.$i.': '.$_name;
+ if ($post_time_text ne '') {
+ print $fh ' • '.$post_time_text;
+ }
+ if ($edit_time_text ne '') {
+ print $fh ' • '.$edit_time_text;
+ }
+ print $fh ' <div class="pr">'."\n";
+ print $fh ' edit | remove'."\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)."\n";
+ print $fh ' </div>'."\n";
+ print $fh ' </div>'."\n";
+ print $fh ' <br>'."\n";
+ }
+ }
+
+ print $fh ' <form method="get" 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><input class="inbt" type="submit" name="post" value="Send"></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";
+
+ print $fh ' </div>'."\n";
+}
+
sub write_index {
(
my $state,
'%02d.%02d.%02d %02d:%02d',
$time_tab[3],
$time_tab[4]+1,
- $time_tab[5]-100,
+ $time_tab[5]-100, # TODO: %100 ?
$time_tab[2],
$time_tab[1]
);
goto.1.pl\
info.1.pl\
oldlogs.1.pl\
+opomba.1.pl\
ong.1.pl\
reset.1.pl\
update.1.pl\
goto.pl\
info.pl\
oldlogs.pl\
+opomba.pl\
ong.pl\
reset.pl\
update.pl\
frame\
goto\
info\
+opomba\
viewer
EXEC=\
goto.pl\
info.pl\
oldlogs.pl\
+opomba.pl\
ong.pl\
reset.pl\
update.pl\
frame\
goto\
info\
+opomba\
viewer
BIN=\
goto.1.pl\
info.1.pl\
oldlogs.1.pl\
+opomba.1.pl\
ong.1.pl\
reset.1.pl\
update.1.pl\
goto.pl\
info.pl\
oldlogs.pl\
+opomba.pl\
ong.pl\
reset.pl\
update.pl\
frame\
goto\
info\
+opomba\
viewer
EXEC=\
goto.pl\
info.pl\
oldlogs.pl\
+opomba.pl\
ong.pl\
reset.pl\
update.pl\
frame\
goto\
info\
+opomba\
viewer
BIN=\
--- /dev/null
+###RUN_PERL: #!/usr/bin/perl
+
+# /bsta/w
+# opomba is generated from opomba.1.pl.
+#
+# The comment posting interface
+#
+# Copyright (C) 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 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/>.
+
+use strict;
+use utf8;
+# use Encode::Locale ('decode_argv');
+use Encode ('encode', 'decode');
+
+###PERL_LIB: use lib /botm/lib/bsta
+use botm_common (
+ 'read_header_env', 'url_query_decode',
+ 'read_data_file', 'write_data_file',
+ 'html_entity_encode_dec',
+ 'open_encoded',
+ 'join_path'
+);
+use bsta_lib (
+ 'TEXT_MODE',
+ 'get_password',
+ 'fail_method', 'fail_content_type',
+ 'redirect',
+ 'print_html_start', 'print_html_end',
+ 'print_html_head_start', 'print_html_head_end',
+ 'print_html_body_start', 'print_html_body_end'
+);
+
+###PERL_PATH_SEPARATOR: PATH_SEPARATOR = /
+
+###PERL_CGI_VIEWER_PATH: CGI_VIEWER_PATH = /bsta/v
+
+###PERL_DATA_SETTINGS_PATH: DATA_SETTINGS_PATH = /botm/data/bsta/settings
+###PERL_DATA_WORDS_PATH: DATA_WORDS_PATH = /botm/data/bsta/words/
+
+###PERL_WEBSITE_NAME: WEBSITE_NAME = Bicycles on the Moon
+
+###PERL_COMMENT_PAGE_LENGTH:COMMENT_PAGE_LENGTH= 16
+
+binmode STDIN, ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+binmode STDERR, ':encoding(UTF-8)';
+# decode_argv();
+
+my $time = time();
+srand ($time-$$);
+
+my %http;
+my %cgi;
+my %settings;
+my %words_data;
+my %post_data;
+
+my @post_list;
+
+my $method;
+my $frame;
+my $ID;
+my $password;
+my $password_ok;
+my $edit = 0;
+my $remove = 0;
+my $post = 0;
+my $quote;
+my $words_data_path;
+my $post_data_path;
+my $index;
+my $page;
+my $fh;
+my $r;
+
+
+delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
+###PERL_SET_PATH: $ENV{'PATH'} = /usr/local/bin:/usr/bin:/bin;
+
+if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
+ $method = $1;
+}
+else{
+ exit fail_method($ENV{'REQUEST_METHOD'}, 'GET, POST, HEAD');
+}
+
+%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 %cgi_post = url_query_decode( <STDIN> );
+ %cgi = merge_settings(\%cgi, \%cgi_post);
+ }
+ # multipart not supported
+ else{
+ exit fail_content_type($method, $http{'content-type'});
+ }
+}
+
+if ($ENV{'PATH_INFO'} =~ /^\/([0-9]+)$/) {
+ $frame = int($1);
+}
+elsif ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) {
+ $ID = $1;
+}
+if ($cgi{'f'} =~ /^.+$/) {
+ $frame = int($&);
+}
+if ($cgi{'i'} =~ /^.+$/) {
+ $ID = $&;
+}
+$password = get_password(\%cgi);
+
+%settings = read_data_file(DATA_SETTINGS_PATH());
+
+$password_ok = ($password eq $settings{'password'});
+
+if ($cgi{'post'} ne '') {
+ $post = 1;
+}
+elsif ($cgi{'edit'} ne '') {
+ $edit = 1;
+ if ($ID eq '') {
+ $ID = $cgi{'edit'};
+ }
+}
+elsif ($cgi{'remove'} ne '') {
+ $remove = 1;
+ if ($ID eq '') {
+ $ID = $cgi{'remove'};
+ }
+}
+else {
+ $edit = 1;
+ if ($cgi{'quote'} ne '') {
+ $quote = $cgi{'quote'};
+ }
+}
+
+if ($ID ne '') {
+ $post_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $ID);
+ %post_data = read_data_file($post_data_path);
+ if ($post_data{'frame'} ne '') {
+ $frame = int($post_data{'frame'});
+ }
+}
+
+if ($frame eq '') {
+ exit output(0, '', 'Frame ID not specified.');
+}
+
+$words_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $frame);
+
+unless (open_encoded($fh, "+<:encoding(UTF-8)", $words_data_path)) {
+ exit output(0, '500 Internal Server Error', 'Failed opening data file.');
+}
+unless (flock($fh, 2)) {
+ exit output(0, '500 Internal Server Error', 'Failed locking data file.');
+}
+
+%words_data = read_data_file(
+ $fh, # file
+ '', # encoding
+ 0, # no header
+ 0, # header only
+ 1 # as list
+);
+
+@post_list = @{$words_data{'content'}};
+
+for (my $i=0; $i< scalar(@post_list); $i +=1) {
+ if ($post_list[$i] eq $ID) {
+ $index = $i;
+ $page = int($index / COMMENT_PAGE_LENGTH());
+ last;
+ }
+}
+
+if ($remove) {
+ unless ($index ne '') {
+ close($fh);
+ exit output(0, '404 Not Found', 'Nothing to remove.');
+ }
+ unless ($cgi{'key'} eq $post_data{'key'}) {
+ close($fh);
+ exit output(0, '403 Forbidden', 'Invalid request.');
+ }
+
+ if (($cgi{'username'} eq '') && ($cgi{'password'} eq ''))
+ {
+ close($fh);
+ exit output(0, '', '', 0, 1);
+ }
+
+ unless ($cgi{'username'} ne '') {
+ close($fh);
+ exit output(0, '403 Forbidden', 'Missing user name.', 0, 1);
+ }
+ unless ($cgi{'username'} eq $post_data{'name'}) {
+ close($fh);
+ exit output(0, '403 Forbidden', 'Wrong user name.', 0, 1);
+ }
+ unless ($cgi{'password'} ne '') {
+ close($fh);
+ exit output(0, '403 Forbidden', 'Missing password.', 0, 1);
+ }
+ unless (
+ ($cgi{'password'} eq $post_data{'password'}) || (
+ ($cgi{'password'} eq $settings{'password'}) &&
+ $password_ok
+ )
+ ) {
+ close($fh);
+ exit output(0, '403 Forbidden', 'Wrong password.', 0, 1);
+ }
+
+ # all conditions fulfilled
+
+ splice @post_list, $index, 1;
+ $words_data{'posts'} = scalar(@post_list);
+ $words_data{'content'} = \@post_list;
+
+ $r = write_data_file($fh, '', '', \%words_data);
+ unless($r) {
+ close($fh);
+ exit output(0, '500 Internal Server Error', 'Failed writing data file.');
+ }
+ $ID = 'insw';
+ exit output(1);
+}
+
+close($fh);
+
+exit output(0, '', '???');
+
+sub output {
+ (
+ my $posted, my $status, my $message,
+ my $edit, my $remove,
+ ) = @_;
+
+ if ($posted) {
+ my $redirect_url = merge_url(
+ {'path' => CGI_VIEWER_PATH()},
+ {
+ 'path' => $frame,
+ 'query' => {
+ 'b' => TEXT_MODE->{'words'},
+ 'i' => $page,
+ 'p' => ($password_ok ? $settings{'password'} : '')
+ },
+ 'fragment' => $ID
+ }
+ );
+ return redirect ($method, $redirect_url, 303);
+ }
+
+ print "Content-type: text/html\n";
+ if ($status ne '') {
+ print 'Status: '.$status."\n";
+ }
+ print "\n";
+ if ($method eq 'HEAD') {
+ return;
+ }
+
+ my $_message = html_entity_encode_dec($message, 1);
+ my $_story = html_entity_encode_dec($settings{'story'}, 1);
+ my $_website_name = html_entity_encode_dec(WEBSITE_NAME(), 1);
+
+ print_html_start(\*STDOUT);
+ print_html_head_start(\*STDOUT);
+
+ print ' <title>Words • '.$_story.' • '.$_website_name.'</title>';
+
+ print_html_head_end(\*STDOUT);
+ print_html_body_start(\*STDOUT);
+
+ print ' <div id="inst" class="ins">'."\n";
+
+ print ' <div id="title">'."\n";
+ print ' <h1 id="titletext">Words</h1>'."\n";
+ print ' </div>'."\n";
+
+ print ' </div>'."\n";
+
+ if ($message ne '') {
+ print ' <div id="insb" class="ins">'."\n";
+
+ print ' <div id="command">'."\n";
+ print ' <span class="br">'.$_message.'</span>'."\n";
+ print ' </div>'."\n";
+
+ print ' </div>'."\n";
+ }
+
+ if ($edit) {
+ print "EDIT\n";
+ }
+ elsif ($remove) {
+ print "REMOVE\n";
+ }
+
+ print_html_body_end(\*STDOUT); # , $ong_state == STATE->{'inactive'}
+ print_html_end(\*STDOUT);
+}
+
+
+
+
+
+
+
firstpage_length: 4
page_length : 16
+comment_page_length: 16
+
story_credits: "BSTA" by Balthasar Szczepański
intf_credits: Online interface © Balthasar Szczepański; AGPL 3 license
source_url: http://bicyclesonthemoon.info/git-projects/?p=ott/bsta
firstpage_length: 4
page_length : 16
+comment_page_length: 16
+
story_credits: "BSTA" by Balthasar Szczepański
intf_credits: Online interface © Balthasar Szczepański; AGPL 3 license
source_url: http://bicyclesonthemoon.info/git-projects/?p=ott/bsta
firstpage_length: 4
page_length : 16
+comment_page_length: 16
+
story_credits: "BSTA" by Balthasar Szczepański
intf_credits: Online interface © Balthasar Szczepański; AGPL 3 license
source_url: http://bicyclesonthemoon.info/git-projects/?p=ott/bsta
_bin_ong_path = @_PATH( $bin_path, ong.pl )
_bin_reset_path = @_PATH( $bin_path, reset.pl)
_bin_viewer_path = @_PATH( $bin_path, viewer )
+_bin_words_path = @_PATH( $bin_path, opomba )
_cgi_path = @_PATH( $cgi_path, )
_cgi_2words_path = @_PATH( $cgi_path, 2words )
_cgi_logo_path = @_PATH( $cgi_path, botmlogo.png)
_cgi_timer_path = @_PATH( $cgi_path, timer.js )
_cgi_viewer_path = @_PATH( $cgi_path, v )
+_cgi_words_path = @_PATH( $cgi_path, w )
_data_path = @_PATH( $data_path, )
_data_attach_path = @_PATH( $data_path, a )
CONF_BIN_GOTO = $_bin_goto_path
CONF_BIN_INFO = $_bin_info_path
CONF_BIN_VIEWER = $_bin_viewer_path
+CONF_BIN_WORDS = $_bin_words_path
CONF_CGI_2WORDS = $_cgi_2words_path
CONF_CGI_ATTACH = $_cgi_attach_path
CONF_CGI_GOTO = $_cgi_goto_path
CONF_CGI_INFO = $_cgi_info_path
CONF_CGI_VIEWER = $_cgi_viewer_path
+CONF_CGI_WORDS = $_cgi_words_path
CRON_ONG = $_bin_ong_path
PERL_CGI_LOGO_PATH = @_PERL_CONSTANT_STR( CGI_LOGO_PATH , $_cgi_logo_path )
PERL_CGI_TIMER_PATH = @_PERL_CONSTANT_STR( CGI_TIMER_PATH , $_cgi_timer_path )
PERL_CGI_VIEWER_PATH = @_PERL_CONSTANT_STR( CGI_VIEWER_PATH, $_cgi_viewer_path)
+PERL_CGI_WORDS_PATH = @_PERL_CONSTANT_STR( CGI_WORDS_PATH, $_cgi_words_path)
PERL_DATA_PATH = @_PERL_CONSTANT_STR( DATA_PATH , $_data_path )
PERL_DATA_ATTACH_PATH = @_PERL_CONSTANT_STR( DATA_ATTACH_PATH , $_data_attach_path )
PERL_PAGE_LENGTH = @_PERL_CONSTANT( PAGE_LENGTH , $page_length)
PERL_FIRSTPAGE_LENGTH = @_PERL_CONSTANT( FIRSTPAGE_LENGTH, $firstpage_length)
+PERL_COMMENT_PAGE_LENGTH= @_PERL_CONSTANT( COMMENT_PAGE_LENGTH, $comment_page_length)
RUN_PERL = @_SHEBANG($perl)
my $access;
my $timer;
my $timer_unlocked;
-my $state_file;
+my $fh;
my $show_command;
my $ongtime;
my $text_mode;
$password_ok = ($password eq $settings{'password'});
# state & activation logic
-if (open_encoded($state_file, "+<:encoding(UTF-8)", DATA_STATE_PATH())) {
- if (flock($state_file, 2)) {
+if (open_encoded($fh, "+<:encoding(UTF-8)", DATA_STATE_PATH())) {
+ if (flock($fh, 2)) {
- %state = read_data_file($state_file);
+ %state = read_data_file($fh);
if ($frame < 0) {
$frame = int($state{'last'}) + $frame +1;
else {
$new_state{'state'} = STATE->{'ready'};
}
- write_data_file($state_file, '', '', \%new_state);
+ write_data_file($fh, '', '', \%new_state);
}
}
elsif (
$r = write_index(\%state, \%settings);
}
if ($r) {
- $r = write_data_file($state_file, '','', \%state);
+ $r = write_data_file($fh, '','', \%state);
}
unless ($r) {
# FAILED ONG! Story as if it was inactive!
# FAILED GET STATE! Story as if it was inactive!
$state{'state'} = STATE->{'inactive'};
}
- close ($state_file);
+ close ($fh);
}
else {
$state{'state'} = STATE->{'inactive'};