1 ###RUN_PERL: #!/usr/bin/perl
4 # info.pl is generated from info.1.pl.
6 # The frame/story info interface
8 # Copyright (C) 2017, 2023, 2024 Balthasar SzczepaĆski
10 # This program is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU Affero General Public License as
12 # published by the Free Software Foundation, either version 3 of the
13 # License, or (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU Affero General Public License for more details.
20 # You should have received a copy of the GNU Affero General Public License
21 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # use Encode::Locale ('decode_argv');
26 use Encode ('encode', 'decode');
28 ###PERL_LIB: use lib /botm/lib/bsta
31 'read_data_file', 'write_data_file',
37 'fail_method', 'fail_content_type',
42 ###PERL_PATH_SEPARATOR: PATH_SEPARATOR = /
44 ###PERL_DATA_PATH: DATA_PATH = /botm/data/bsta
45 ###PERL_DATA_ATTACH_PATH: DATA_ATTACH_PATH = /botm/data/bsta/a
46 ###PERL_DATA_DEFAULT_PATH: DATA_DEFAULT_PATH = /botm/data/bsta/default
47 ###PERL_DATA_NOACCESS_PATH: DATA_NOACCESS_PATH = /botm/data/bsta/noaccess
48 ###PERL_DATA_SETTINGS_PATH: DATA_SETTINGS_PATH = /botm/data/bsta/settings
49 ###PERL_DATA_STATE_PATH: DATA_STATE_PATH = /botm/data/bsta/state
50 ###PERL_DATA_WORDS_PATH: DATA_WORDS_PATH = /botm/data/bsta/words/
52 binmode STDIN, ':encoding(UTF-8)';
53 binmode STDOUT, ':encoding(UTF-8)';
54 binmode STDERR, ':encoding(UTF-8)';
79 my $next_frame_data_path;
83 delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
84 ###PERL_SET_PATH: $ENV{'PATH'} = /usr/local/bin:/usr/bin:/bin;
86 if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
90 exit fail_method($ENV{'REQUEST_METHOD'}, 'GET, POST, HEAD');
93 %http = read_header_env(\%ENV);
94 %cgi = url_query_decode($ENV{'QUERY_STRING'});
96 if ($method eq 'POST') {
97 if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
98 my %cgi_post = url_query_decode( <STDIN> );
99 %cgi = merge_settings(\%cgi, \%cgi_post);
101 # multipart not supported
103 exit fail_content_type($method, $http{'content-type'});
107 if ($cgi{'f'} =~ /^.+$/) {
110 elsif ($cgi{'a'} =~ /^.+$/) {
111 $attachment = int($&);
113 elsif ($cgi{'i'} =~ /^.+$/) {
114 $attachment = int($&);
116 elsif ($cgi{'w'} =~ /^.+$/) {
119 elsif ($ENV{'PATH_INFO'} =~ /^\/a(.+)$/) {
120 $attachment = int($1);
122 elsif ($ENV{'PATH_INFO'} =~ /^\/w(.+)$/) {
125 elsif ($ENV{'PATH_INFO'} =~ /^\/f?(.+)$/) {
129 $password = get_password(\%cgi);
131 %settings = read_data_file(DATA_SETTINGS_PATH());
132 %default = read_data_file(DATA_DEFAULT_PATH());
133 %state = read_data_file(DATA_STATE_PATH());
135 $ong_state = int($state{'state'});
136 $last_frame = int($state{'last'});
138 $password_ok = ($password eq $settings{'password'});
140 # comment info, not frame
142 $info_data_path = join_path(PATH_SEPARATOR(), DATA_WORDS_PATH(), $words);
143 %info_data = read_data_file($info_data_path);
144 if ($words =~ /^[0-9]+$/) {
146 if ($info_data{'posts'} eq '') {
147 $info_data{'posts'} = 0;
151 $frame = ($info_data{'frame'} ne '') ? int($info_data{'frame'}) : -1;
152 unless ($password_ok) {
153 delete($info_data{'password'});
154 delete($info_data{'key'});
158 # attachment info, not frame
159 elsif ($attachment ne '') {
160 %info_data = read_data_file(DATA_ATTACH_PATH().$attachment);
161 $frame = ($info_data{'frame'} ne '') ? int($info_data{'frame'}) : -1;
164 elsif ($frame ne '') {
166 $frame = $last_frame + $frame +1;
168 $info_data_path = join_path(PATH_SEPARATOR(), DATA_PATH(), $frame);
169 $next_frame_data_path = join_path(PATH_SEPARATOR(), DATA_PATH(), $frame+1);
170 %info_data = read_data_file($info_data_path);
171 %next_frame_data = read_data_file($next_frame_data_path);
172 %info_data = merge_settings(\%default, \%info_data);
173 %next_frame_data = merge_settings(\%default, \%next_frame_data);
175 $timer = int($state{'nextong'}) - $time;
176 $ongtime = int($state{'ongtime'});
178 $ongtime = int($settings{'ongtime'})
180 $show_command = ($timer < ($ongtime * 3600 / 3));
182 # state info, not frame
184 unless ($password_ok) {
185 # just show if IP was saved, not its value
186 if ($state{'ip1'} ne '') {
189 if ($state{'ip2'} ne '') {
192 if ($state{'ip3'} ne '') {
196 print "Content-type: text/plain; charset=UTF-8\n\n";
197 if ($method eq 'HEAD') {
201 \*STDOUT, \%state, '',
211 ($ong_state >= STATE->{'waiting'}) &&
212 ($frame <= $last_frame) &&
220 ($attachment eq '') &&
221 ($info_data{'command'} eq '') && (
223 ($frame < $last_frame) || (
224 ($ong_state >= STATE->{'ready'}) &&
229 $info_data{'command'} = $next_frame_data{'title'};
234 if (($attachment ne '') || ($words ne '')) {
238 %info_data = read_data_file(DATA_NOACCESS_PATH());
239 %info_data = merge_settings(\%default, \%info_data);
243 ($info_data{'frame'} eq '') &&
244 ($attachment eq '') &&
247 $info_data{'frame'} = sprintf($settings{'frame'}, $frame, $info_data{'ext'});
250 print "Content-type: text/plain; charset=UTF-8\n";
252 print "Status: 403 Forbidden\n";
255 if($method eq 'HEAD') {
259 \*STDOUT, \%info_data, '',