From 0edd03b1678a94f221af2da823c527e1b5c08b59 Mon Sep 17 00:00:00 2001 From: b Date: Sat, 30 Dec 2023 13:15:47 +0000 Subject: [PATCH] launch index bugfix; reworked attachment --- 2words.1.pl | 16 ++---- attach.1.pl | 151 ++++++++++++++++++++++++++------------------------ botm-common | 2 +- bsta_lib.1.pm | 64 ++++++++++++++------- frame.1.pl | 6 +- viewer.1.pl | 7 +-- 6 files changed, 134 insertions(+), 112 deletions(-) diff --git a/2words.1.pl b/2words.1.pl index b001298..ce6d445 100644 --- a/2words.1.pl +++ b/2words.1.pl @@ -36,6 +36,7 @@ use botm_common ( ); use bsta_lib ( 'STATE', 'INTF_STATE', + 'get_id', 'fail_method', 'fail_content_type', 'print_html_start', 'print_html_end', 'print_html_head_start', 'print_html_head_end', @@ -121,10 +122,8 @@ else{ %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( ); - foreach my $ind (keys %cgi_post) { - $cgi{$ind} = $cgi_post{$ind}; - } + my %cgi_post = url_query_decode( ); + %cgi = merge_settings(\%cgi, \%cgi_post); } # multipart not supported else{ @@ -132,14 +131,9 @@ if ($method eq 'POST') { } } $IP = get_remote_addr(); -if ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) { - $page=int($1); -} -else { - $page=0; -} +$page = get_id(\%cgi); if ($cgi{'words'} ne '') { - $words=$cgi{'words'}; + $words = $cgi{'words'}; } %settings = read_data_file(DATA_SETTINGS_PATH()); diff --git a/attach.1.pl b/attach.1.pl index 91fed4c..18caf8a 100644 --- a/attach.1.pl +++ b/attach.1.pl @@ -5,7 +5,7 @@ # # The attachment interface # -# Copyright (C) 2016, 2023 Balthasar Szczepañski +# Copyright (C) 2016, 2023 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 @@ -21,133 +21,140 @@ # along with this program. If not, see . use strict; -#use warnings; -###PERL_LIB: use lib /botm/lib/bsta +use utf8; +# use Encode::Locale ('decode_argv'); +use Encode ('encode', 'decode'); -use bsta_lib qw(failpage gethttpheader getcgi readdatafile); +###PERL_LIB: use lib /botm/lib/bsta +use botm_common ( + 'read_header_env', + 'url_query_decode', + 'read_data_file', + 'join_path' +); +use bsta_lib ( + 'STATE', + 'merge_settings', + 'get_id', 'get_password', + 'fail_attachment', 'fail_500' +); + +###PERL_PATH_SEPARATOR: PATH_SEPARATOR = / ###PERL_DATA_PATH: DATA_PATH = /botm/data/bsta ###PERL_DATA_SETTINGS_PATH: DATA_SETTINGS_PATH = /botm/data/bsta/settings ###PERL_DATA_STATE_PATH: DATA_STATE_PATH = /botm/data/bsta/state +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 %state; -my %filedata; - -my $time = time(); -srand ($time-$$); +my %file_data; my $method; my $ID; my $frame; my $password; -my $passwordOK; +my $password_ok; my $IP; my $buffer; -my @fileinfo; -my $file; -my $filepath; +my $fh; +my $file_path; my $direct; 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; + $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( ); - foreach my $ind (keys %cgipost) { - $cgi{$ind}=$cgipost{$ind}; - } + my %cgi_post = url_query_decode( ); + %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'}); } } # print "content-type: text/plain\n\n"; -if ($cgi{'i'} =~ /^(.+)$/) { - $ID=int($1); -} -elsif ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) { - $ID=int($1); -} -else { - $ID = 0; -} +$ID = get_id( \%cgi); +$password = get_password(\%cgi); -if ($cgi{'p'} =~ /^(.+)$/) { - $password=$1; -} -else { - $password=''; -} +%settings = read_data_file(DATA_SETTINGS_PATH); +%state = read_data_file(DATA_STATE_PATH); +%file_data = read_data_file(join_path(PATH_SEPARATOR(), DATA_PATH(), 'a'.$ID)); +$frame = ($file_data{'frame'} ne '') ? int($file_data{'frame'}) : -1; -%settings=readdatafile(DATA_SETTINGS_PATH); -%state=readdatafile(DATA_STATE_PATH); -%filedata=readdatafile(DATA_PATH.'a'.$ID); -if ($filedata{'frame'} ne '') { - $frame=int($filedata{'frame'}); -} -else { - $frame = -1; -} +$password_ok = ($password eq $settings{'password'}); -if($password eq $settings{'password'}){ - $passwordOK = 1; -} -else{ - $passwordOK = 0; +unless ( + ($file_data{'filename'} ne '') && ( + $password_ok || ( + (int($state{'state'}) >= STATE->{'waiting'}) && + ($frame <= int($state{'last'})) && + ($frame >=0) + ) + ) +) { + exit fail_attachment($method, $ID); } -if ($filedata{'filename'} ne '' && ($passwordOK || (int($state{'state'}) >= 1 && $frame <= int($state{'last'}) && $frame >=0))) { -} -else { - exit failpage("Status: 404 Not Found\n","404 Not Found"," Attachment ".$ID." not found."); -} - -if ($filedata{'content'} ne '') { - $direct=1; +if ($file_data{'content'} ne '') { + $direct = 1; } else { $direct = 0; - $filepath=DATA_PATH.$filedata{'filename'}; - open($file,'<',$filepath) or exit failpage("Status: 404 Not Found\n","404 Not Found"," Attachment ".$ID." not found."); - unless(binmode($file)) { - close($file); - return failpage("Status: 500 Internal Server Error\n","500 Internal Server Error"," Can't switch to binary mode."); + $file_path = join_path(PATH_SEPARATOR(), DATA_PATH(), $file_data{'filename'}); + unless (open($fh,'<', encode('locale_fs', $file_path))) { + exit fail_attachment($method, $ID); } - if (my @fileinfo = stat($filepath)){ - print 'Content-length: '.$fileinfo[7]."\n"; + unless(binmode($fh)) { + close($fh); + exit fail_500("Can't switch file to binary mode."); + } + if (my @file_info = stat($file_path)) { + print 'Content-length: '.$file_info[7]."\n"; + } +} +print 'Content-type: '.$file_data{'content-type'}."\n"; +print 'Content-disposition: attachment; filename="'.$file_data{'filename'}.'"'."\n"; +unless ($direct) { + unless (binmode STDOUT) { + close($fh); + exit fail_500("Can't switch output to binary mode."); } } -print 'Content-type: '.$filedata{'content-type'}."\n"; -print 'Content-disposition: attachment; filename="'.$filedata{'filename'}.'"'."\n"; print "\n"; + if($method ne 'HEAD'){ if($direct) { - print $filedata{'content'}; + print $file_data{'content'}; } else { - while (read ($file,$buffer,1024)) { + while (read ($fh, $buffer, 1024)) { print (STDOUT $buffer); } } } -if (!$direct) { - close($file); +unless ($direct) { + close($fh); } - diff --git a/botm-common b/botm-common index 9a09107..3231e70 160000 --- a/botm-common +++ b/botm-common @@ -1 +1 @@ -Subproject commit 9a09107fdff2fa2ca6747de5185df3e442e21666 +Subproject commit 3231e70f7ba581a5ac018ca4ec2e5f9db100a19a diff --git a/bsta_lib.1.pm b/bsta_lib.1.pm index d0e3df7..db60e49 100644 --- a/bsta_lib.1.pm +++ b/bsta_lib.1.pm @@ -37,9 +37,10 @@ our @ISA = qw(Exporter); our @EXPORT = (); our @EXPORT_OK = ( 'STATE', 'TEXT_MODE', 'INTF_STATE', - 'failpage', 'fail_method', 'fail_content_type', 'fail_open_file', 'fail_500', + 'failpage', + 'fail_method', 'fail_content_type', 'fail_open_file', 'fail_attachment', 'fail_500', 'redirect', - 'get_remote_addr', 'get_frame', 'get_password', + 'get_remote_addr', 'get_id', 'get_frame', 'get_password', 'merge_settings', 'print_html_start', 'print_html_end', 'print_html_head_start', 'print_html_head_end', @@ -271,6 +272,18 @@ sub fail_open_file ); } +sub fail_attachment +{ + (my $method, my $ID) = @_; + + return failpage( + "Status: 404 Not Found\n", + "404 Not Found", + "Attachment $ID not found.", + $method + ); +} + sub fail_500 { (my $method, my $text) = @_; @@ -330,11 +343,14 @@ sub get_remote_addr { } } -# function to obtain frame number -sub get_frame { - (my $cgi) = @_; +# functions to get ID/number etc. +sub get_id { + (my $cgi, my $cgi_name) = @_; + if ($cgi_name eq '') { + $cgi_name = 'i'; + } - if ($cgi->{'f'} =~ /^.+$/) { + if ($cgi->{$cgi_name} =~ /^.+$/) { return int($&); } elsif ($ENV{'PATH_INFO'} =~ /^\/(.+)$/) { @@ -345,6 +361,12 @@ sub get_frame { } } +# function to obtain frame number +sub get_frame { + (my $cgi) = @_; + return get_id($cgi, 'f'); +} + # function to obtain password sub get_password { (my $cgi) = @_; @@ -923,7 +945,16 @@ sub print_viewer_page { ) = @_; my $fh; - my $frame = int($context->{'frame'}); + my $launch = $context->{'launch'}; + my $access = $context->{'access'}; + my $password_ok = $context->{'password_ok'}; + my $static = $context->{'static'}; + + my $frame = int($context->{'frame'}); + my $text_mode = int($context->{'text_mode'}); + my $timer_unlocked = int($context->{'timer_unlocked'}); + my $timer = int($context->{'timer'}); + # my $prev_frame = $frame - 1; my $next_frame = $frame + 1; @@ -933,14 +964,6 @@ sub print_viewer_page { $frame_data->{'command'} : $next_frame_data->{'title'}; - my $access = $context->{'access'}; - my $password_ok = $context->{'password_ok'}; - my $static = $context->{'static'}; - - my $text_mode = int($context->{'text_mode'}); - my $timer_unlocked = int($context->{'timer_unlocked'}); - my $timer = int($context->{'timer'}); - my $last_frame = int($state->{'last'}); my $ong_state = int($state->{'state'}); @@ -972,7 +995,7 @@ sub print_viewer_page { } my $prev_available = (($frame > 0) && $access); - my $next_available = ($password_ok || ($next_frame <= $last_frame)); + my $next_available = ($launch || $password_ok || ($next_frame <= $last_frame)); my $prefetch_next = ( $password_ok || ($next_frame < $last_frame) || ( # avoid unseen trigger! @@ -982,9 +1005,7 @@ sub print_viewer_page { ); my $show_timer = ( ( - $access && - ($ong_state == STATE->{'inactive'}) && - ($frame == 0) + $access && $launch ) || ( ($frame == $last_frame) && ( ($ong_state == STATE->{'waiting'}) || @@ -993,6 +1014,7 @@ sub print_viewer_page { ) ); my $show_command = ( + $launch || $password_ok || (!$access) || ($frame < $last_frame) || ( @@ -1318,6 +1340,7 @@ sub write_index { $r = print_viewer_page( $fh, { + 'launch' => 0, 'frame' => 0, 'access' => 1, 'password_ok' => 0, @@ -1396,13 +1419,14 @@ sub write_index { $r = print_viewer_page( $fh, { + 'launch' => 1, 'frame' => 0, 'access' => 1, 'password_ok' => 0, 'timer_unlocked' => 3, 'timer' => 0, 'static' => 1, - 'show_command' => 1 + 'show_command' => 1, }, $state, $settings, diff --git a/frame.1.pl b/frame.1.pl index b175644..c6f87ae 100644 --- a/frame.1.pl +++ b/frame.1.pl @@ -99,10 +99,8 @@ else{ if ($method eq 'POST') { if ($http{'content-type'} eq 'application/x-www-form-urlencoded') { - my %cgi_post=url_query_decode( ); - foreach my $ind (keys %cgi_post) { - $cgi{$ind} = $cgi_post{$ind}; - } + my %cgi_post = url_query_decode( ); + %cgi = merge_settings(\%cgi, \%cgi_post); } # multipart not supported else{ diff --git a/viewer.1.pl b/viewer.1.pl index 9a21dd8..d535fe4 100644 --- a/viewer.1.pl +++ b/viewer.1.pl @@ -100,10 +100,8 @@ else{ %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( ); - foreach my $ind (keys %cgi_post) { - $cgi{$ind} = $cgi_post{$ind}; - } + my %cgi_post = url_query_decode( ); + %cgi = merge_settings(\%cgi, \%cgi_post); } # multipart not supported else{ @@ -301,6 +299,7 @@ if($method eq 'HEAD') { print_viewer_page ( \*STDOUT, { + 'launch' => 0, 'frame' => $frame, 'access' => $access, 'password_ok' => $password_ok, -- 2.30.2