diff --git a/lib/RenderApp/Controller/StaticFiles.pm b/lib/RenderApp/Controller/StaticFiles.pm index 7c1149185..415d83c59 100644 --- a/lib/RenderApp/Controller/StaticFiles.pm +++ b/lib/RenderApp/Controller/StaticFiles.pm @@ -1,11 +1,25 @@ package RenderApp::Controller::StaticFiles; use Mojo::Base 'Mojolicious::Controller', -signatures; -use Mojo::File qw(path); +use Mojo::File qw(path); +use File::Spec::Functions qw(canonpath); -sub reply_with_file_if_readable ($c, $file) { - if (-r $file) { - return $c->reply->file($file); +sub path_is_subdir ($path, $dir) { + return 0 unless $path =~ /^\//; + + $path = canonpath($path); + return 0 if $path =~ m#(^\.\.$|^\.\./|/\.\./|/\.\.$)#; + + $dir = canonpath($dir); + return 0 unless $path =~ m|^$dir|; + + return 1; +} + +sub reply_with_file_if_readable ($c, $directory, $file) { + my $filePath = $directory->child($file); + if (-r $filePath && path_is_subdir($filePath, $directory)) { + return $c->reply->file($filePath); } else { return $c->render(data => 'File not found', status => 404); } @@ -13,23 +27,23 @@ sub reply_with_file_if_readable ($c, $file) { # Route requests for pg_files/CAPA_Graphics to render root Contrib/CAPA/CAPA_Graphics sub CAPA_graphics_file ($c) { - return $c->reply_with_file_if_readable($c->app->home->child('Contrib/CAPA/CAPA_Graphics', $c->stash('static'))); + return $c->reply_with_file_if_readable($c->app->home->child('Contrib/CAPA/CAPA_Graphics'), $c->stash('static')); } # Route requests for pg_files to the render root tmp. The # only requests should be for files in the temporary directory. # FIXME: Perhaps this directory should be configurable. sub temp_file ($c) { - $c->reply_with_file_if_readable($c->app->home->child('tmp', $c->stash('static'))); + return $c->reply_with_file_if_readable($c->app->home->child('tmp'), $c->stash('static')); } # Route request to pg_files to lib/PG/htdocs. sub pg_file ($c) { - $c->reply_with_file_if_readable(path($ENV{PG_ROOT}, 'htdocs', $c->stash('static'))); + return $c->reply_with_file_if_readable(path($ENV{PG_ROOT}, 'htdocs'), $c->stash('static')); } sub public_file ($c) { - $c->reply_with_file_if_readable($c->app->home->child('public', $c->stash('static'))); + return $c->reply_with_file_if_readable($c->app->home->child('public'), $c->stash('static')); } 1;