The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

OpenInteract2::File - Safe filesystem operations for OpenInteract

SYNOPSIS

 use OpenInteract2::File;
 
 my $filename = OpenInteract2::File->create_filename( 'conf/server.ini' );
 my $filename = OpenInteract2::File->create_filename( 'uploads/myfile.exe' );
 
 # These two save to the same file
 
 my $filename = OpenInteract2::File->save_file( $fh, 'myfile.exe' );
 my $filename = OpenInteract2::File->save_file( $fh, 'uploads/myfile.exe', 'true' );
 
 # This one wants to write to the same file but doesn't pass a true
 # value for overwriting, so it writes to 'uploads/myfile_x1.exe'
 
 my $filename = OpenInteract2::File->save_file( $fh, 'uploads/myfile.exe' );
 
 # See if a particular file already exists
 
 if ( OpenInteract2::File->check_filename( 'uploads/myfile.exe' ) ) {
     print "That file already exists!";
 }
 
 # Get the MIME type of content...
 
 # ...read in from a file
 my $type = OpenInteract2::File->get_mime_type({ content => $content });
 
 # ...in a filehandle
 my $type = OpenInteract2::File->get_mime_type({ filehandle => $fh });
 
 # ...specified by a filename
 my $type = OpenInteract2::File->get_mime_type({ filename => 'uploads

DESCRIPTION

We want to ensure that OpenInteract does not write to any file outside its configured website_directory. We also want to make it easy to find files inside a site. This module accomplishes both, and in an OS-independent manner.

METHODS

Class Methods

create_filename( $filename )

Creates a "safe" filename for $filename. Generally, this means that if there is a directory specified in $filename, the method ensures that it is under the configured 'website_dir'. If the leading directory is not found at the top level of the website directory, we assume that you want to save it to a subdirectory under the upload directory (typically 'upload') and create the path as necessary.

The goal is that we never, ever want to save a file outside the configured 'website_dir'. If this is a problem for your use, simply read or save the file yourself or save the file using the save_file() method and use the return value to rename it to your desired location.

Here are some examples from the test suite:

 Website root: /home/httpd/mysite

 Given                   Result
 ======================================================================
 myfile.txt              /home/httpd/mysite/uploads/myfile.txt
 otherdir/myfile.txt     /home/httpd/mysite/uploads/otherdir/myfile.txt
 html/myfile.txt         /home/httpd/mysite/html/myfile.txt
 html/images/sharpie.gif /home/httpd/mysite/html/images/sharpie.gif
 /dingdong/myfile.txt    /home/httpd/mysite/uploads/dingdong/myfile.txt

check_filename( $filename )

Retrieves a full path to $filename, or undef if the file does not exist. The $filename is assumed to be under the website directory and is checked according to the rules in create_filename().

Note that you cannot rely on this method to ensure a file will be named the same with a successive call to save_file(). For instance, in the following snippet $filename is not guaranteed to be named .../uploads/myfile.exe:

 if ( OpenInteract2::File->check_filename( 'uploads/myfile.exe' ) ) {
     my $filename = OpenInteract2::File->save_file( $fh, 'uploads/myfile.exe' );
 }

Why not? Another process could have written the file 'uploads/myfile.exe' in between the call to check_filename() and the call to save_file(). Therefore you should always check the return value.

Returns: true if $filename exists under the website directory, false if not.

save_file( $filehandle, $filename[, $do_overwrite ] )

Saves $filehandle to $filename, ensuring first that $filename is 'safe' as determined by create_filename(). If a true value for $do_overwrite is passed then we will overwrite any existing file by the same name. Otherwise we try to create versions of the same name until one is found that will work properly.

 my $file_a = OpenInteract2::File->save_file( $fh, 'logo.gif' ); # saves to 'uploads/logo.gif'
 my $file_b = OpenInteract2::File->save_file( $fh, 'logo.gif' ); # saves to 'uploads/logo_x1.gif'
 my $file_c = OpenInteract2::File->save_file( $fh, 'logo.gif' ); # saves to 'uploads/logo_x2.gif'

Returns: The full path to the file saved

get_mime_type( \%params )

Get the MIME type for the item which can be specified in \%params by:

  • filename: A file to check for its type. This first checks the file extension to see if it is known, if the extension is not known it uses the File::MMagic module to check the type. (Let the author know if you would like to be able to manipulate the extension-to-type mappings.)

  • content: Raw bytes to analyze for content type. This always uses the File::MMagic module.

  • filehandle: Filehandle to analyze for content type. This always uses the File::MMagic module.

If none of these parameters are specified an exception is thrown.

Returns: a valid MIME type if one can be discerned.

SEE ALSO

File::MMagic

COPYRIGHT

Copyright (c) 2002-2004 Chris Winters. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHORS

Chris Winters <chris@cwinters.com>