1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-11 09:04:38 +02:00

Allow various media file uploads (flv, f4v, mov, avi), code (almost) auto-formatted

This commit is contained in:
secretr
2009-10-16 21:15:56 +00:00
parent d1758cce36
commit a251ab6bab

View File

@@ -1,53 +1,53 @@
<?php <?php
/* /*
+---------------------------------------------------------------+ * e107 website system
| e107 website system *
| /classes/upload_class.php * Copyright (C) 2001-2008 e107 Inc (e107.org)
| * Released under the terms and conditions of the
| <20>Steve Dunstan 2001-2002 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
| http://e107.org *
| jalist@e107.org * File Upload Handler
| *
| Released under the terms and conditions of the * $Source: /cvs_backup/e107_0.8/e107_handlers/upload_handler.php,v $
| GNU General Public License (http://gnu.org). * $Revision: 1.21 $
| * $Date: 2009-10-16 21:15:56 $
| $Source: /cvs_backup/e107_0.8/e107_handlers/upload_handler.php,v $ * $Author: secretr $
| $Revision: 1.20 $
| $Date: 2009-10-13 20:50:39 $
| $Author: e107steved $
+---------------------------------------------------------------+
*/ */
if (!defined('e107_INIT')) { exit; } if (!defined('e107_INIT'))
{
exit;
}
include_lan(e_LANGUAGEDIR.e_LANGUAGE."/lan_upload_handler.php"); include_lan(e_LANGUAGEDIR.e_LANGUAGE."/lan_upload_handler.php");
//define("UH_DEBUG",TRUE); //define("UH_DEBUG",TRUE);
define("UH_DEBUG", FALSE); define("UH_DEBUG", FALSE);
define('e_UPLOAD_TEMP_DIR', e_FILE.'temp/'); // Temporary directory define('e_UPLOAD_TEMP_DIR', e_FILE.'temp/'); // Temporary directory
define('e_READ_FILETYPES', 'filetypes.xml'); // Upload permissions define('e_READ_FILETYPES', 'filetypes.xml'); // Upload permissions
define('e_SAVE_FILETYPES', 'filetypes_.xml'); define('e_SAVE_FILETYPES', 'filetypes_.xml');
/* /*
File upload handler - this is the preferred interface for new code File upload handler - this is the preferred interface for new code
------------------- -------------------
function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = array()) function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = array())
Parameters: Parameters:
$uploaddir - target directory (checked that it exists, but path not otherwise changed) $uploaddir - target directory (checked that it exists, but path not otherwise changed)
$fileinfo - determines any special handling of file name (combines previous $fileinfo and $avatar parameters): $fileinfo - determines any special handling of file name (combines previous $fileinfo and $avatar parameters):
FALSE - default option; no processing FALSE - default option; no processing
"attachment+extra_text" - indicates an attachment (related to forum post or PM), and specifies some optional text which is "attachment+extra_text" - indicates an attachment (related to forum post or PM), and specifies some optional text which is
incorporated into the final file name (the original $fileinfo parameter). incorporated into the final file name (the original $fileinfo parameter).
$file_name = time()."_".USERID."_".'extra_text'.$name; $file_name = time()."_".USERID."_".'extra_text'.$name;
"prefix+extra_text" - indicates an attachment or file, and specifies some optional text which is prefixed to the file name "prefix+extra_text" - indicates an attachment or file, and specifies some optional text which is prefixed to the file name
"unique" - if the proposed destination file doesn't exist, saved under given name "unique"
- if the proposed destination file doesn't exist, saved under given name
- if the proposed destination file does exist, prepends time() to the file name to make it unique - if the proposed destination file does exist, prepends time() to the file name to make it unique
'avatar' - indicates an avatar is being uploaded (not used - options must be set elsewhere) 'avatar'
- indicates an avatar is being uploaded (not used - options must be set elsewhere)
$options - an array of supplementary options, all of which will be given appropriate defaults if not defined: $options - an array of supplementary options, all of which will be given appropriate defaults if not defined:
'filetypes' - name of file containing list of valid file types 'filetypes' - name of file containing list of valid file types
- Always looks in the admin directory - Always looks in the admin directory
@@ -70,9 +70,9 @@ Parameters:
'overwrite' - if TRUE, existing file of the same name is overwritten; otherwise returns 'duplicate file' error (default FALSE) 'overwrite' - if TRUE, existing file of the same name is overwritten; otherwise returns 'duplicate file' error (default FALSE)
'save_to_db' - storage type - if set and TRUE, uploaded files are saved in the database (rhater than as flat files) (default FALSE) 'save_to_db' - storage type - if set and TRUE, uploaded files are saved in the database (rhater than as flat files) (default FALSE)
Returns FALSE if the upload directory doesn't exist, or various other errors occurred which restrict the amount of meaningful information. Returns FALSE if the upload directory doesn't exist, or various other errors occurred which restrict the amount of meaningful information.
Returns an array, with one set of entries per uploaded file, regardless of whether saved or discarded (not all fields always present) - $c is array index: Returns an array, with one set of entries per uploaded file, regardless of whether saved or
discarded (not all fields always present) - $c is array index:
$uploaded[$c]['name'] - file name - as saved to disc or in database $uploaded[$c]['name'] - file name - as saved to disc or in database
$uploaded[$c]['rawname'] - original file name, prior to any addition of identifiers etc (useful for display purposes) $uploaded[$c]['rawname'] - original file name, prior to any addition of identifiers etc (useful for display purposes)
$uploaded[$c]['type'] - mime type (if set - as returned by browser) $uploaded[$c]['type'] - mime type (if set - as returned by browser)
@@ -82,12 +82,11 @@ Returns an array, with one set of entries per uploaded file, regardless of wheth
$uploaded[$c]['message'] - text of displayed message relating to file $uploaded[$c]['message'] - text of displayed message relating to file
$uploaded[$c]['line'] - only if an error occurred, has line number (from __LINE__) $uploaded[$c]['line'] - only if an error occurred, has line number (from __LINE__)
$uploaded[$c]['file'] - only if an error occurred, has file name (from __FILE__) $uploaded[$c]['file'] - only if an error occurred, has file name (from __FILE__)
On exit, uploaded files should all have been removed from the temporary directory. On exit, uploaded files should all have been removed from the temporary directory.
No messages displayed - its caller's responsibility to handle errors and display info to user (or can use handle_upload_messages() from this module) No messages displayed - its caller's responsibility to handle errors and display info to
user (or can use handle_upload_messages() from this module)
Details of uploaded files are in $_FILES['file_userfile'] (or other array name as set) on entry. Details of uploaded files are in $_FILES['file_userfile'] (or other array name as set) on entry.
Elements passed (from PHP) relating to each file: Elements passed (from PHP) relating to each file:
['name'] - the original name ['name'] - the original name
['type'] - mime type (if provided - not checked by PHP) ['type'] - mime type (if provided - not checked by PHP)
@@ -95,8 +94,8 @@ Elements passed (from PHP) relating to each file:
['tmp_name'] - temporary file name on server ['tmp_name'] - temporary file name on server
['error'] - error code. 0 = 'good'. 1..4 main others, although up to 8 defined for later PHP versions ['error'] - error code. 0 = 'good'. 1..4 main others, although up to 8 defined for later PHP versions
Files stored in server's temporary directory, unless another set Files stored in server's temporary directory, unless another set
*/ */
function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
{ {
global $pref,$sql,$tp; global $pref,$sql,$tp;
@@ -112,27 +111,28 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
$ul_temp_dir = ''; $ul_temp_dir = '';
} }
if (UH_DEBUG) $admin_log->e_log_event(10,debug_backtrace(),"DEBUG","Upload Handler test","Process uploads to {$uploaddir}, fileinfo ".$fileinfo,FALSE,LOG_TO_ROLLING); if (UH_DEBUG)
$admin_log->
e_log_event(10, debug_backtrace(), "DEBUG", "Upload Handler test", "Process uploads to {$uploaddir}, fileinfo ".$fileinfo, FALSE, LOG_TO_ROLLING);
// $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Intermediate directory: {$ul_temp_dir} ",FALSE,LOG_TO_ROLLING); // $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Intermediate directory: {$ul_temp_dir} ",FALSE,LOG_TO_ROLLING);
$overwrite = varset($options['overwrite'], FALSE); $overwrite = varset($options['overwrite'], FALSE);
$save_to_db = varset($options['save_to_db'], FALSE); $save_to_db = varset($options['save_to_db'], FALSE);
$uploaddir = realpath($uploaddir); // Mostly to get rid of the grot that might be passed in from legacy code. Also strips any trailing '/' $uploaddir = realpath($uploaddir); // Mostly to get rid of the grot that might be passed in from legacy code. Also strips any trailing '/'
if (!is_dir($uploaddir)) if (!is_dir($uploaddir))
{ {
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Invalid directory: ".$uploaddir,FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Invalid directory: ".$uploaddir, FALSE, FALSE);
return FALSE; // Need a valid directory return FALSE; // Need a valid directory
} }
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Destination directory: ".$uploaddir,FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Destination directory: ".$uploaddir, FALSE, FALSE);
$final_chmod = varset($options['final_chmod'], 0644); $final_chmod = varset($options['final_chmod'], 0644);
if (isset($options['file_array_name'])) if (isset($options['file_array_name']))
{ {
$files = $_FILES[$options['file_array_name']]; $files = $_FILES[$options['file_array_name']];
@@ -142,29 +142,28 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
$files = $_FILES['file_userfile']; $files = $_FILES['file_userfile'];
} }
$max_file_count = varset($options['max_file_count'], 0); $max_file_count = varset($options['max_file_count'], 0);
if (!is_array($files)) if (!is_array($files))
{ {
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","No files uploaded",FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "No files uploaded", FALSE, FALSE);
return FALSE; return FALSE;
} }
$uploaded = array(
$uploaded = array(); );
$max_upload_size = calc_max_upload_size(varset($options['max_upload_size'], -1)); // Find overriding maximum upload size $max_upload_size = calc_max_upload_size(varset($options['max_upload_size'], -1)); // Find overriding maximum upload size
$allowed_filetypes = get_filetypes(varset($options['file_mask'], ''), varset($options['filetypes'], '')); $allowed_filetypes = get_filetypes(varset($options['file_mask'], ''), varset($options['filetypes'], ''));
$max_upload_size = set_max_size($allowed_filetypes, $max_upload_size); $max_upload_size = set_max_size($allowed_filetypes, $max_upload_size);
// That's the basics set up - we can start processing files now // That's the basics set up - we can start processing files now
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Start individual files: ".count($files['name'])." Max upload: ".$max_upload_size,FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Start individual files: ".count($files['name'])." Max upload: ".$max_upload_size, FALSE, FALSE);
$c = 0; $c = 0;
foreach ($files['name'] as $key=>$name) foreach ($files['name'] as $key=>$name)
@@ -176,9 +175,12 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
$raw_name = $name; // Save 'proper' file name - useful for display $raw_name = $name; // Save 'proper' file name - useful for display
$file_ext = trim(strtolower(substr(strrchr($name, "."), 1))); // File extension $file_ext = trim(strtolower(substr(strrchr($name, "."), 1))); // File extension
if (!trim($files['type'][$key])) $files['type'][$key] = 'Unknowm mime-type'; if (!trim($files['type'][$key]))
$files['type'][$key] = 'Unknowm mime-type';
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Process file {$name}, size ".$files['size'][$key],FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Process file {$name}, size ".$files['size'][$key], FALSE, FALSE);
if ($max_file_count && ($c > $max_file_count)) if ($max_file_count && ($c > $max_file_count))
{ {
@@ -208,7 +210,8 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
if (!$first_error) if (!$first_error)
{ {
$uploadfile = $files['tmp_name'][$key]; // Name in temporary directory $uploadfile = $files['tmp_name'][$key]; // Name in temporary directory
if (!$uploadfile) $first_error = 253; if (!$uploadfile)
$first_error = 253;
} }
if (!$first_error) if (!$first_error)
@@ -233,7 +236,8 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
$destination_file = $uploaddir."/".$name; $destination_file = $uploaddir."/".$name;
} }
if (file_exists($destination_file) && !$overwrite) $first_error = 250; // Invent our own error number - duplicate file if (file_exists($destination_file) && !$overwrite)
$first_error = 250; // Invent our own error number - duplicate file
} }
if (!$first_error) if (!$first_error)
@@ -245,7 +249,9 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
{ // Need to move file to our own temporary directory { // Need to move file to our own temporary directory
$tempfilename = $uploadfile; $tempfilename = $uploadfile;
$uploadfile = $ul_temp_dir.basename($uploadfile); $uploadfile = $ul_temp_dir.basename($uploadfile);
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Move {$tempfilename} to {$uploadfile} ",FALSE,LOG_TO_ROLLING); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Move {$tempfilename} to {$uploadfile} ", FALSE, LOG_TO_ROLLING);
@move_uploaded_file($tempfilename, $uploadfile); // This should work on all hosts @move_uploaded_file($tempfilename, $uploadfile); // This should work on all hosts
} }
$tpos = (($file_status = vet_file($uploadfile, $name, $allowed_filetypes, varset($options['extra_file_types'], FALSE))) === TRUE); $tpos = (($file_status = vet_file($uploadfile, $name, $allowed_filetypes, varset($options['extra_file_types'], FALSE))) === TRUE);
@@ -257,7 +263,6 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
} }
} }
if (!$first_error) if (!$first_error)
{ // All tests passed - can store it somewhere { // All tests passed - can store it somewhere
$uploaded[$c]['name'] = $name; $uploaded[$c]['name'] = $name;
@@ -266,15 +271,17 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
$uploaded[$c]['size'] = 0; $uploaded[$c]['size'] = 0;
$uploaded[$c]['index'] = $key; // Store the actual index from the file_userfile array $uploaded[$c]['index'] = $key; // Store the actual index from the file_userfile array
if ($save_to_db) if ($save_to_db)
{ // Store binary files in the database if selected. Maximum two files this way { // Store binary files in the database if selected. Maximum two files this way
// This is really legacy stuff - not seriously changed from the original apart from using the newer file vetting routines // This is really legacy stuff - not seriously changed from the original apart from using the newer file vetting routines
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Save to DB {$c}: ".$uploaded[$c]['name'],FALSE,LOG_TO_ROLLING); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Save to DB {$c}: ".$uploaded[$c]['name'], FALSE, LOG_TO_ROLLING);
set_magic_quotes_runtime(0); set_magic_quotes_runtime(0);
$data = mysql_real_escape_string(fread(fopen($files['tmp_name'][$c], "rb"), filesize($uploadfile))); $data = mysql_real_escape_string(fread(fopen($files['tmp_name'][$c], "rb"), filesize($uploadfile)));
set_magic_quotes_runtime(get_magic_quotes_gpc()); set_magic_quotes_runtime(get_magic_quotes_gpc());
if ($sql->db_Insert("rbinary", "0, '".$tp -> toDB($name, true)."', '".$tp -> toDB($files['type'][$c], true)."', '{$data}' ")) if ($sql->
db_Insert("rbinary", "0, '".$tp->toDB($name, true)."', '".$tp->toDB($files['type'][$c], true)."', '{$data}' "))
{ {
$uploaded[$c]['name'] = "Binary ".mysql_insert_id()."/".$name; $uploaded[$c]['name'] = "Binary ".mysql_insert_id()."/".$name;
$uploaded[$c]['size'] = $files['size'][$c]; $uploaded[$c]['size'] = $files['size'][$c];
@@ -291,10 +298,14 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
if ((!$ul_temp_dir && @move_uploaded_file($uploadfile, $destination_file)) || ($ul_temp_dir && @rename($uploadfile, $destination_file))) // This should work on all hosts if ((!$ul_temp_dir && @move_uploaded_file($uploadfile, $destination_file)) || ($ul_temp_dir && @rename($uploadfile, $destination_file))) // This should work on all hosts
{ {
@chmod($destination_file, $final_chmod); @chmod($destination_file, $final_chmod);
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Final chmod() file {$destination_file} to {$final_chmod} ",FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Final chmod() file {$destination_file} to {$final_chmod} ", FALSE, FALSE);
$uploaded[$c]['size'] = $files['size'][$key]; $uploaded[$c]['size'] = $files['size'][$key];
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Saved file {$c} OK: ".$uploaded[$c]['name'],FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Saved file {$c} OK: ".$uploaded[$c]['name'], FALSE, FALSE);
} }
else else
{ {
@@ -363,26 +374,27 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL)
$uploaded[$c]['message'] = LANUPLOAD_11." '".$name."' <br />".LANUPLOAD_12.": ".$error; $uploaded[$c]['message'] = LANUPLOAD_11." '".$name."' <br />".LANUPLOAD_12.": ".$error;
$uploaded[$c]['line'] = __LINE__; $uploaded[$c]['line'] = __LINE__;
$uploaded[$c]['file'] = __FILE__; $uploaded[$c]['file'] = __FILE__;
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Main routine error {$first_error} file {$c}: ".$uploaded[$c]['message'],FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Main routine error {$first_error} file {$c}: ".$uploaded[$c]['message'], FALSE, FALSE);
// If we need to abort on first error, do so here - could check for specific error codes // If we need to abort on first error, do so here - could check for specific error codes
} }
if (is_file($uploadfile)) @unlink($uploadfile); // Don't leave the file on the server if error (although should be auto-deleted) if (is_file($uploadfile))
@unlink($uploadfile); // Don't leave the file on the server if error (although should be auto-deleted)
$c++; $c++;
} }
} }
return $uploaded; return $uploaded;
} }
/* /*
Utility routine to handle the messages returned by process_uploaded_files(). Utility routine to handle the messages returned by process_uploaded_files().
$upload_array is the list of uploaded files $upload_array is the list of uploaded files
$errors_only - if TRUE, no message is shown for a successful upload. $errors_only - if TRUE, no message is shown for a successful upload.
$use_handler - if TRUE, message_handler is used to display the message. $use_handler - if TRUE, message_handler is used to display the message.
Returns - a list of all accumulated messages. (Non-destructive call, so can be called several times with different options). Returns - a list of all accumulated messages. (Non-destructive call, so can be called several times with different options).
*/ */
function handle_upload_messages(&$upload_array, $errors_only = TRUE, $use_handler = FALSE) function handle_upload_messages(&$upload_array, $errors_only = TRUE, $use_handler = FALSE)
{ {
// Display error messages, accumulate FMESSAGE // Display error messages, accumulate FMESSAGE
@@ -403,9 +415,6 @@ function handle_upload_messages(&$upload_array, $errors_only = TRUE, $use_handle
return implode("<br />", $f_message); return implode("<br />", $f_message);
} }
/* /*
==================================================================== ====================================================================
LEGACY FILE UPLOAD HANDLER LEGACY FILE UPLOAD HANDLER
@@ -413,41 +422,40 @@ function handle_upload_messages(&$upload_array, $errors_only = TRUE, $use_handle
This is the 'legacy' interface, which handles various special cases etc. This is the 'legacy' interface, which handles various special cases etc.
It was the only option in E107 0.7.8 and earlier, and is still used in some places in core. It was the only option in E107 0.7.8 and earlier, and is still used in some places in core.
It also attempts to return in the same way as the original, especially when any errors occur It also attempts to return in the same way as the original, especially when any errors occur
Parameters for file_upload(): Parameters for file_upload():
$uploaddir - target directory for file. Defaults to e_FILE/public $uploaddir - target directory for file. Defaults to e_FILE/public
$avatar - sets the 'type' or destination of the file: $avatar - sets the 'type' or destination of the file:
FALSE - its a 'general' file FALSE - its a 'general' file
'attachment' - indicates an attachment (related to forum post or PM) 'attachment' - indicates an attachment (related to forum post or PM)
'unique' - indicates that file name must be unique - new name given (prefixed with time()_ ) 'unique' - indicates that file name must be unique - new name given (prefixed with time()_ )
'avatar' - indicates an avatar is being uploaded 'avatar' - indicates an avatar is being uploaded
$fileinfo - included within the name of the saved file with attachments - can be an identifier of some sort $fileinfo - included within the name of the saved file with attachments - can be an identifier of some sort
(Forum adds 'FT{$tid}_' - where $tid is the thread ID. (Forum adds 'FT{$tid}_' - where $tid is the thread ID.
$overwrite - if true, an uploaded file can overwrite an existing file of the same name (not used in 0.7 core) $overwrite - if true, an uploaded file can overwrite an existing file of the same name (not used in 0.7 core)
Preference used: Preference used:
$pref['upload_storagetype'] = 1 for files, 2 for database $pref['upload_storagetype'] = 1 for files, 2 for database
On exit, F_MESSAGE is defined with the success/failure message(s) that have been displayed - one file per line On exit, F_MESSAGE is defined with the success/failure message(s) that have been displayed - one file per line
For backward compatibility, returns FALSE if only one file uploaded and an error; otherwise returns an array with per-file error codes as appropriate. For backward compatibility, returns FALSE if only one file uploaded and an error; otherwise returns an array with per-file error codes as appropriate.
*/ */
function file_upload($uploaddir, $avatar = FALSE, $fileinfo = "", $overwrite = "") function file_upload($uploaddir, $avatar = FALSE, $fileinfo = "", $overwrite = "")
{ {
global $admin_log; global $admin_log;
$options = array('extra_file_types' => TRUE); // As default, allow any filetype enabled in filetypes.php $options = array(
'extra_file_types'=>TRUE
); // As default, allow any filetype enabled in filetypes.php
if (!$uploaddir)
if (!$uploaddir) {$uploaddir = e_FILE."public/";} {
$uploaddir = e_FILE."public/";
}
// Compute storage type - 1 is file, 2 is DB // Compute storage type - 1 is file, 2 is DB
$upload_storagetype = varset($pref['upload_storagetype'], 1); $upload_storagetype = varset($pref['upload_storagetype'], 1);
if($uploaddir == e_THEME) {$upload_storagetype = 1;} if ($uploaddir == e_THEME)
{
$upload_storagetype = 1;
}
$options['save_to_db'] = ($upload_storagetype == "2" && $avatar == FALSE); $options['save_to_db'] = ($upload_storagetype == "2" && $avatar == FALSE);
if (strpos($avatar, '=') !== FALSE) if (strpos($avatar, '=') !== FALSE)
@@ -469,40 +477,41 @@ function file_upload($uploaddir, $avatar = FALSE, $fileinfo = "", $overwrite = "
break; break;
} }
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Legacy call, directory ".$uploaddir,FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Legacy call, directory ".$uploaddir, FALSE, FALSE);
$ret = process_uploaded_files(getcwd()."/".$uploaddir, $avatar, $options); // Well, that's the way it was done before
$ret = process_uploaded_files(getcwd()."/".$uploaddir, // Well, that's the way it was done before
$avatar,$options);
if ($ret === FALSE) if ($ret === FALSE)
{ {
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Legacy return FALSE",FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Legacy return FALSE", FALSE, FALSE);
return FALSE; return FALSE;
} }
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Legacy return with ".count($ret)." files",FALSE,FALSE); if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Legacy return with ".count($ret)." files", FALSE, FALSE);
$messages = handle_upload_messages($ret, FALSE, TRUE); // Show all the error and acknowledgment messages $messages = handle_upload_messages($ret, FALSE, TRUE); // Show all the error and acknowledgment messages
define(F_MESSAGE, $messages); define(F_MESSAGE, $messages);
if (count($ret) == 1) if (count($ret) == 1)
{ {
if ($ret[0]['error'] != 0) return FALSE; // Special case if errors if ($ret[0]['error'] != 0)
return FALSE; // Special case if errors
} }
return $ret; return $ret;
} }
/* /*
==================================================================== ====================================================================
VETTING AND UTILITY ROUTINES VETTING AND UTILITY ROUTINES
==================================================================== ====================================================================
// Check uploaded file to try and identify dodgy content. // Check uploaded file to try and identify dodgy content.
// Return TRUE if appears OK. // Return TRUE if appears OK.
// Return a numeric reason code 1..9 if unacceptable // Return a numeric reason code 1..9 if unacceptable
// $filename is the full path+name to the uploaded file on the server // $filename is the full path+name to the uploaded file on the server
// $target_name is the intended name of the file once transferred // $target_name is the intended name of the file once transferred
// $allowed_filetypes is an array of permitted file extensions, in lower case, no leading '.' // $allowed_filetypes is an array of permitted file extensions, in lower case, no leading '.'
@@ -511,28 +520,35 @@ function file_upload($uploaddir, $avatar = FALSE, $fileinfo = "", $overwrite = "
// if $unknown is TRUE, accepts totally unknown file extensions. // if $unknown is TRUE, accepts totally unknown file extensions.
// otherwise $unknown is a comma-separated list of additional permitted file extensions // otherwise $unknown is a comma-separated list of additional permitted file extensions
*/ */
function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = FALSE) function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = FALSE)
{ {
// 1. Start by checking against filetypes - that's the easy one! // 1. Start by checking against filetypes - that's the easy one!
$file_ext = strtolower(substr(strrchr($target_name, "."), 1)); $file_ext = strtolower(substr(strrchr($target_name, "."), 1));
if (!isset($allowed_filetypes[$file_ext])) if (!isset($allowed_filetypes[$file_ext]))
{ {
if (is_bool($unknown)) return 1; // Reject out of hand if no possible alternative extensions if (is_bool($unknown))
return 1; // Reject out of hand if no possible alternative extensions
// Otherwise, it could be in the supplementary list // Otherwise, it could be in the supplementary list
$tmp = explode(',', $unknown); $tmp = explode(',', $unknown);
for ($i = 0; $i < count($tmp); $i++) { $tmp[$i] = strtolower(trim(str_replace('.', '', $tmp[$i]))); } for ($i = 0; $i < count($tmp); $i++)
if (!in_array($file_ext, $tmp)) return 6; {
$tmp[$i] = strtolower(trim(str_replace('.', '', $tmp[$i])));
}
if (!in_array($file_ext, $tmp))
return 6;
} }
// 2. For all files, read the first little bit to check for any flags etc // 2. For all files, read the first little bit to check for any flags etc
$res = fopen($filename, 'rb'); $res = fopen($filename, 'rb');
$tstr = fread($res, 100); $tstr = fread($res, 100);
fclose($res); fclose($res);
if ($tstr === FALSE) return 2; // If can't read file, not much use carrying on! if ($tstr === FALSE)
if (stristr($tstr,'<?php') !== FALSE) return 3; // Pretty certain exploit return 2; // If can't read file, not much use carrying on!
if (stristr($tstr,'<?') !== FALSE) return 7; // Possible exploit - maybe allowable? if (stristr($tstr, '<?php') !== FALSE)
return 3; // Pretty certain exploit
if (stristr($tstr, '<?') !== FALSE)
return 7; // Possible exploit - maybe allowable?
// 3. Now do what we can based on file extension // 3. Now do what we can based on file extension
switch ($file_ext) switch ($file_ext)
@@ -544,8 +560,10 @@ function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = F
case 'pjpeg': case 'pjpeg':
case 'bmp': case 'bmp':
$ret = getimagesize($filename); $ret = getimagesize($filename);
if (!is_array($ret)) return 4; // getimagesize didn't like something if (!is_array($ret))
if (($ret[0] == 0) || ($ret[1] == 0)) return 5; // Zero size picture or bad file format return 4; // getimagesize didn't like something
if (($ret[0] == 0) || ($ret[1] == 0))
return 5; // Zero size picture or bad file format
break; break;
case 'zip': case 'zip':
@@ -559,6 +577,10 @@ function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = F
case 'csv': case 'csv':
case 'wmv': case 'wmv':
case 'swf': case 'swf':
case 'flv': //Flash stream
case 'f4v': //Flash stream
case 'mov': //media
case 'avi': //media
break; // Just accept these break; // Just accept these
case 'php': case 'php':
@@ -569,20 +591,21 @@ function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = F
return 9; // Never accept these! Whatever the user thinks! return 9; // Never accept these! Whatever the user thinks!
default: default:
if (is_bool($unknown)) return ($unknown ? TRUE : 8); if (is_bool($unknown))
return ($unknown ? TRUE : 8);
} }
return TRUE; // Accepted here return TRUE; // Accepted here
} }
// Get array of file types (file extensions) which are permitted - reads a definition file. // Get array of file types (file extensions) which are permitted - reads a definition file.
// Key is the file type. // Key is the file type.
// If $file_mask is a comma-separated list of file types, only those types which are in both the definition file and in $file_mask are added // If $file_mask is a comma-separated list of file types, only those types which are in both the definition file and in $file_mask are added
function get_allowed_filetypes($def_file = FALSE, $file_mask = '') function get_allowed_filetypes($def_file = FALSE, $file_mask = '')
{ {
$ret = array(); $ret = array(
if ($def_file === FALSE) return $ret; );
if ($def_file === FALSE)
return $ret;
if ($file_mask) if ($file_mask)
{ {
@@ -613,8 +636,6 @@ function get_allowed_filetypes($def_file = FALSE, $file_mask = '')
return $ret; return $ret;
} }
// Parse a file size string (e.g. 16M) and compute the simple numeric value. // Parse a file size string (e.g. 16M) and compute the simple numeric value.
// If $action is empty, return this value. // If $action is empty, return this value.
// If $source evaluates to zero, return the compare value instead // If $source evaluates to zero, return the compare value instead
@@ -623,9 +644,11 @@ function get_allowed_filetypes($def_file = FALSE, $file_mask = '')
function file_size_decode($source, $compare = 0, $action = '') function file_size_decode($source, $compare = 0, $action = '')
{ {
$source = trim($source); $source = trim($source);
if (strtolower(substr($source,-1,1)) == 'b') $source = substr($source,0,-1); // Trim a trailing byte indicator if (strtolower(substr($source, -1, 1)) == 'b')
$source = substr($source, 0, -1); // Trim a trailing byte indicator
$mult = 1; $mult = 1;
if (strlen($source) && (strtoupper(substr($source,-1,1)) == 'B')) $source = substr($source,0,-1); if (strlen($source) && (strtoupper(substr($source, -1, 1)) == 'B'))
$source = substr($source, 0, -1);
if (!$source || is_numeric($source)) if (!$source || is_numeric($source))
{ {
$val = $source; $val = $source;
@@ -647,24 +670,28 @@ function file_size_decode($source, $compare = 0, $action = '')
break; break;
} }
} }
if ($val == 0) return $compare; if ($val == 0)
return $compare;
switch ($action) switch ($action)
{ {
case 'lt' : return min($val, $compare); case 'lt':
case 'gt' : return max($val, $compare); return min($val, $compare);
default : return $val; case 'gt':
return max($val, $compare);
default:
return $val;
} }
return 0; return 0;
} }
// Similar to get_allowed_filetypes(), but expects an XML file // Similar to get_allowed_filetypes(), but expects an XML file
// Returns an array where key is the file extension; value is max upload size // Returns an array where key is the file extension; value is max upload size
function get_XML_filetypes($def_file = FALSE, $file_mask = '') function get_XML_filetypes($def_file = FALSE, $file_mask = '')
{ {
$ret = array(); $ret = array(
if ($def_file === FALSE) return $ret; );
if ($def_file === FALSE)
return $ret;
if ($file_mask) if ($file_mask)
{ {
@@ -687,14 +714,18 @@ function get_XML_filetypes($def_file = FALSE, $file_mask = '')
} }
if (count($temp_vars['class']) == 1) if (count($temp_vars['class']) == 1)
{ {
$temp_vars['class'] = array($temp_vars['class']); $temp_vars['class'] = array(
$temp_vars['class']
);
} }
foreach ($temp_vars['class'] as $v1) foreach ($temp_vars['class'] as $v1)
{ {
$v = $v1['@attributes']; $v = $v1['@attributes'];
if (check_class($v['name'])) if (check_class($v['name']))
{ {
$current_perms[$v['name']] = array('type' => $v['type'],'maxupload' => $v['maxupload']); $current_perms[$v['name']] = array(
'type'=>$v['type'], 'maxupload'=>$v['maxupload']
);
$a_filetypes = explode(',', $v['type']); $a_filetypes = explode(',', $v['type']);
foreach ($a_filetypes as $ftype) foreach ($a_filetypes as $ftype)
{ {
@@ -720,7 +751,6 @@ function get_XML_filetypes($def_file = FALSE, $file_mask = '')
return $ret; return $ret;
} }
// Calculate 'global' maximum upload size - the maximum before extension-specific restrictions taken into account // Calculate 'global' maximum upload size - the maximum before extension-specific restrictions taken into account
function calc_max_upload_size($max_up = -1) function calc_max_upload_size($max_up = -1)
{ {
@@ -728,8 +758,8 @@ function calc_max_upload_size($max_up = -1)
// Work out maximum allowable file size // Work out maximum allowable file size
if (UH_DEBUG) if (UH_DEBUG)
{ {
$admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test", $admin_log->
"File size limits - user set: ".$pref['upload_maxfilesize']." Post_max_size: ".ini_get('post_max_size')." upload_max_size: ".ini_get('upload_max_size'),FALSE,FALSE); e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "File size limits - user set: ".$pref['upload_maxfilesize']." Post_max_size: ".ini_get('post_max_size')." upload_max_size: ".ini_get('upload_max_size'), FALSE, FALSE);
} }
$max_upload_size = file_size_decode(ini_get('post_max_size')); $max_upload_size = file_size_decode(ini_get('post_max_size'));
$max_upload_size = file_size_decode(ini_get('upload_max_filesize'), $max_upload_size, 'lt'); $max_upload_size = file_size_decode(ini_get('upload_max_filesize'), $max_upload_size, 'lt');
@@ -739,16 +769,17 @@ function calc_max_upload_size($max_up = -1)
} }
else else
{ {
if (varset($pref['upload_maxfilesize'],0) > 0) $max_upload_size = file_size_decode($pref['upload_maxfilesize'], $max_upload_size, 'lt'); if (varset($pref['upload_maxfilesize'], 0) > 0)
$max_upload_size = file_size_decode($pref['upload_maxfilesize'], $max_upload_size, 'lt');
} }
if ($save_to_db) $max_upload_size = min($max_upload_size, 512000); // Approx 500k limit for database saves if ($save_to_db)
if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Final max upload size: {$max_upload_size}",FALSE,FALSE); $max_upload_size = min($max_upload_size, 512000); // Approx 500k limit for database saves
if (UH_DEBUG)
$admin_log->
e_log_event(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Final max upload size: {$max_upload_size}", FALSE, FALSE);
return $max_upload_size; return $max_upload_size;
} }
// Get an array of permitted filetypes according to a set hierarchy. // Get an array of permitted filetypes according to a set hierarchy.
function get_filetypes($file_mask = FALSE, $filename = '') function get_filetypes($file_mask = FALSE, $filename = '')
{ {
@@ -775,10 +806,10 @@ function get_filetypes($file_mask = FALSE, $filename = '')
{ {
return get_allowed_filetypes('filetypes.php', $file_mask); return get_allowed_filetypes('filetypes.php', $file_mask);
} }
return array(); // Just an empty array return array(
); // Just an empty array
} }
// Scans the array of allowed file types, updates allowed max size as appropriate. // Scans the array of allowed file types, updates allowed max size as appropriate.
// Returns largest allowed file size // Returns largest allowed file size
function set_max_size(&$allowed_filetypes, $max_upload_size) function set_max_size(&$allowed_filetypes, $max_upload_size)
@@ -790,19 +821,20 @@ function set_max_size(&$allowed_filetypes, $max_upload_size)
{ // Unspecified max - use the global value { // Unspecified max - use the global value
$allowed_filetypes[$t] = $max_upload_size; $allowed_filetypes[$t] = $max_upload_size;
} }
elseif ($allowed_filetypes[$t] > $max_upload_size) $allowed_filetypes[$t] = $max_upload_size; elseif ($allowed_filetypes[$t] > $max_upload_size)
if ($allowed_filetypes[$t] > $new_max) $new_max = $allowed_filetypes[$t]; $allowed_filetypes[$t] = $max_upload_size;
if ($allowed_filetypes[$t] > $new_max)
$new_max = $allowed_filetypes[$t];
} }
return $new_max; return $new_max;
} }
// Quick routine if all we want is the size of the largest file the current user can upload // Quick routine if all we want is the size of the largest file the current user can upload
function get_user_max_upload() function get_user_max_upload()
{ {
$a_filetypes = get_filetypes(); $a_filetypes = get_filetypes();
if (count($a_filetypes) == 0) return 0; // Return if no upload allowed if (count($a_filetypes) == 0)
return 0; // Return if no upload allowed
$max_upload_size = calc_max_upload_size(-1); // Find overriding maximum upload size $max_upload_size = calc_max_upload_size(-1); // Find overriding maximum upload size
$max_upload_size = set_max_size($a_filetypes, $max_upload_size); $max_upload_size = set_max_size($a_filetypes, $max_upload_size);
return $max_upload_size; return $max_upload_size;