From 36e9b4b5fd8b9b0224455b8ba136a5340f63ecda Mon Sep 17 00:00:00 2001 From: Milan Date: Mon, 28 Dec 2020 14:20:37 +0100 Subject: [PATCH] ListenerAccess.pm: editor defined audio shares editors can share broadcast records for 7 days. --- lib/calcms/ListenerAccess.pm | 38 +++++++++++--------- website/agenda/planung/event.cgi | 59 ++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/lib/calcms/ListenerAccess.pm b/lib/calcms/ListenerAccess.pm index 1b06767..d109d8d 100644 --- a/lib/calcms/ListenerAccess.pm +++ b/lib/calcms/ListenerAccess.pm @@ -14,26 +14,28 @@ use Apache2::Const -compile => qw(FORBIDDEN OK); sub handler { my $r = shift; + my $DAYS = 24 * 60 * 60; + my $OK = Apache2::Const::OK; + my $FORBIDDEN = Apache2::Const::FORBIDDEN; + my $path = $ENV{LISTENER_DIR} . File::Basename::basename( $r->uri() ); my $file = readlink $path; - unless ($file) { - print STDERR "cannot read link for $path\n"; - return Apache2::Const::FORBIDDEN; + + # granted access by temporary symlinks only + return $FORBIDDEN unless ($file); + + # use link age for authorized downloads + if (File::Basename::basename($path) =~ /^shared\-/) { + my $age = time() - (lstat($path))[9]; + return ( $age > 7 * $DAYS ) ? $FORBIDDEN : $OK; } - $file = File::Basename::basename($file); - unless ( $file =~ /(\d\d\d\d)\-(\d\d)\-(\d\d) (\d\d)_(\d\d)/ ) { - printf STDERR "access: cannot find datetime pattern in file:'%s'\n", $file; - return Apache2::Const::FORBIDDEN; - } - - my $start_since = time() - Time::Local::timelocal( 0, $5, $4, $3, $2 - 1, $1 ); - $start_since /= 24 * 60 * 60; - if ( $start_since > 7 ) { - printf STDERR "access: file is not availabe anymore:'%s'\n", $file; - return Apache2::Const::FORBIDDEN; - } - return Apache2::Const::OK; + # use age from file name for public access + return $FORBIDDEN unless + File::Basename::basename($file) =~ /(\d\d\d\d)\-(\d\d)\-(\d\d) (\d\d)_(\d\d)/; + + my $age = time() - Time::Local::timelocal( 0, $5, $4, $3, $2 - 1, $1 ); + return ( $age > 7 * $DAYS ) ? $FORBIDDEN : $OK; } 1; @@ -41,10 +43,12 @@ __END__ # limit access up to 7 days after datetime given by filename. # The filename links to a file starting with "yyyy-mm-dd hh_mm" in file name. +# +# Access to links starting with "shared-" are allowed up to 7 days after creation. # # # PerlSetEnv PERL5LIB ${perl_lib}/calcms # PerlSetEnv LISTENER_DIR ${archive_dir}/${domain}/ # PerlAccessHandler ListenerAccess # -# \ No newline at end of file +# diff --git a/website/agenda/planung/event.cgi b/website/agenda/planung/event.cgi index f2a9859..1fe9bd9 100755 --- a/website/agenda/planung/event.cgi +++ b/website/agenda/planung/event.cgi @@ -9,6 +9,7 @@ use Data::Dumper; $Data::Dumper::Sortkeys = 1; use MIME::Base64(); use Encode::Locale(); +use File::Basename qw(basename); use params(); use config(); @@ -67,8 +68,9 @@ $request = uac::prepare_request( $request, $user_presets ); $params = $request->{params}->{checked}; -#show header -unless ( params::isJson() ) { +my $show_header = ! (params::isJson() or $params->{action} eq 'download_audio'); + +if ( $show_header ) { my $headerParams = uac::set_template_permissions( $request->{permissions}, $params ); $headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } ); template::process( $config, 'print', template::check( $config, 'default.html' ), @@ -80,7 +82,7 @@ print q{ -} unless (params::isJson); +} if $show_header; if ( defined $params->{action} ) { if ( ( $params->{action} eq 'show_new_event' ) @@ -106,6 +108,10 @@ if ( defined $params->{action} ) { if ( $params->{action} eq 'delete' ) { delete_event( $config, $request ) } if ( $params->{action} eq 'save' ) { save_event( $config, $request ) } if ( $params->{action} eq 'download' ) { download( $config, $request ) } + if ( $params->{action} eq 'download_audio' ) { + download_audio( $config, $request ); + return; + } } $config->{access}->{write} = 0; show_event( $config, $request ); @@ -710,11 +716,9 @@ sub create_event { my $event = $request->{params}->{checked}; my $action = $params->{action}; return eventOps::createEvent( $request, $event, $action ); - } -#TODO: replace permission check with download -sub download { +sub get_download_event{ my $config = shift; my $request = shift; @@ -758,6 +762,15 @@ sub download { $request2->{params}->{checked}->{published} = 'all'; my $events = events::get( $config, $request2 ); my $event = $events->[0]; + return $event; +} + +#TODO: replace permission check with download +sub download { + my $config = shift; + my $request = shift; + + my $event = get_download_event($config, $request); my $datetime = $event->{start_datetime}; if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { $datetime = $1 . '\ ' . $2 . '_' . $3; @@ -777,6 +790,7 @@ sub download { my $key = int( rand(99999999999999999) ); $key = MIME::Base64::encode_base64($key); $key =~ s/[^a-zA-Z0-9]//g; + $key = 'shared-'.$key; #decode filename $file = Encode::decode( "UTF-8", $file ); @@ -799,6 +813,36 @@ sub download { } } +sub download_audio { + my $config = shift; + my $request = shift; + + my $event = get_download_event($config, $request); + my $datetime = $event->{start_datetime}; + if ( $datetime =~ /(\d\d\d\d\-\d\d\-\d\d)[ T](\d\d)\:(\d\d)/ ) { + $datetime = $1 . '\ ' . $2 . '_' . $3; + } else { + print STDERR "event.cgi::download no valid datetime found $datetime\n"; + return; + } + my $archive_dir = $config->{locations}->{local_archive_dir}; + print STDERR "archive_dir: " . $archive_dir . "\n"; + print STDERR "event.cgi::download look for : $archive_dir/$datetime*.mp3\n"; + my @files = glob( $archive_dir . '/' . $datetime . '*.mp3' ); + if ( @files > 0 ) { + my $file = $files[0]; + $file = Encode::decode( "UTF-8", $file ); + print qq{Content-Disposition: attachment; filename="}.basename($file).qq{"\n}; + print qq{Content-Type: audio/mpeg\n\n}; + binmode STDOUT; + open my $fh, '<:raw', $file; + while (<$fh>){ + print $_; + } + close $fh; + } +} + sub check_params { my $config = shift; my $params = shift; @@ -849,7 +893,8 @@ sub check_params { } $checked->{action} = entry::element_of( $params->{action}, - [ 'save', 'delete', 'download', 'show_new_event', 'show_new_event_from_schedule', + [ 'save', 'delete', 'download', 'download_audio', 'show_new_event', + 'show_new_event_from_schedule', 'create_event', 'create_event_from_schedule', 'get_json' ] )//'';