From 958e68d6a0fda5a411d94bc057b48ae92a9d6b1a Mon Sep 17 00:00:00 2001 From: e107steved Date: Tue, 22 Apr 2008 20:32:59 +0000 Subject: [PATCH] First cut of modified upload system - uses class-based limits in filetypes.xml --- e107_admin/filetypes_.xml | 3 + e107_admin/upload.php | 552 ++++++++++++------- e107_files/misc/index.html | 0 e107_files/misc/null.txt | 0 e107_handlers/upload_handler.php | 375 +++++++++---- e107_languages/English/admin/help/upload.php | 27 +- e107_languages/English/admin/lan_upload.php | 39 +- e107_languages/English/lan_upload.php | 12 +- upload.php | 44 +- 9 files changed, 723 insertions(+), 329 deletions(-) create mode 100644 e107_admin/filetypes_.xml delete mode 100644 e107_files/misc/index.html delete mode 100644 e107_files/misc/null.txt diff --git a/e107_admin/filetypes_.xml b/e107_admin/filetypes_.xml new file mode 100644 index 000000000..1ab9d1594 --- /dev/null +++ b/e107_admin/filetypes_.xml @@ -0,0 +1,3 @@ + + + diff --git a/e107_admin/upload.php b/e107_admin/upload.php index 6252de2ec..a007977fb 100644 --- a/e107_admin/upload.php +++ b/e107_admin/upload.php @@ -11,52 +11,68 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/e107_admin/upload.php,v $ -| $Revision: 1.3 $ -| $Date: 2007-09-22 12:40:03 $ +| $Revision: 1.4 $ +| $Date: 2008-04-22 20:32:39 $ | $Author: e107steved $ +----------------------------------------------------------------------------+ */ require_once("../class2.php"); -if (!getperms("V")) { - header("location:".e_BASE."index.php"); - exit; +if (!getperms("V")) +{ + header("location:".e_BASE."index.php"); + exit; } $e_sub_cat = 'upload'; -if (e_QUERY) { - $tmp = explode(".", e_QUERY); - $action = $tmp[0]; - $id = $tmp[1]; + + +$action = 'list'; // Default action +if (e_QUERY) +{ + $tmp = explode(".", e_QUERY); + $action = $tmp[0]; + $id = varset($tmp[1],0); } -if ($action == "dis" && isset($_POST['updelete']['upload_'.$id]) ) { + + +if ($action == "dis" && isset($_POST['updelete']['upload_'.$id]) ) +{ $res = $sql -> db_Select("upload", "*", "upload_id='".intval($id)."'"); $row = $sql -> db_Fetch(); - if (preg_match("#Binary (.*?)/#", $row['upload_file'], $match)) { + if (preg_match("#Binary (.*?)/#", $row['upload_file'], $match)) + { $sql -> db_Delete("rbinary", "binary_id='".$tp -> toDB($match[1])."'"); - } else if ($row['upload_file'] && file_exists(e_FILE."public/".$row['upload_file'])) { + } + else if ($row['upload_file'] && file_exists(e_FILE."public/".$row['upload_file'])) + { unlink(e_FILE."public/".$row['upload_file']); } - if (preg_match("#Binary (.*?)/#", $row['upload_ss'], $match)) { + if (preg_match("#Binary (.*?)/#", $row['upload_ss'], $match)) + { $sql -> db_Delete("rbinary", "binary_id='".$tp -> toDB($match[1])."'"); - } else if ($row['upload_ss'] && file_exists(e_FILE."public/".$row['upload_ss'])) { + } + else if ($row['upload_ss'] && file_exists(e_FILE."public/".$row['upload_ss'])) + { unlink(e_FILE."public/".$row['upload_ss']); } $message = ($sql->db_Delete("upload", "upload_id='".intval($id)."'")) ? UPLLAN_1 : LAN_DELETED_FAILED; } -if ($action == "dlm") { - header("location: ".e_ADMIN."download.php?dlm.".$id); - exit; +if ($action == "dlm") +{ + header("location: ".e_ADMIN."download.php?dlm.".$id); + exit; } -if ($action == "news") { - header("location: ".e_ADMIN."newspost.php?create.upload.".$id); - exit; +if ($action == "news") +{ + header("location: ".e_ADMIN."newspost.php?create.upload.".$id); + exit; } -if ($action == "dl") { - +if ($action == "dl") +{ $id = str_replace("%20", " ", $id); if (preg_match("/Binary\s(.*?)\/.*/", $id, $result)) { @@ -77,23 +93,26 @@ if ($action == "dl") { } } +require_once(e_HANDLER.'upload_handler.php'); require_once("auth.php"); require_once(e_HANDLER."userclass_class.php"); $gen = new convert; require_once(e_HANDLER."form_handler.php"); $rs = new form; -if (isset($_POST['optionsubmit'])) { - +if (isset($_POST['optionsubmit'])) +{ $pref['upload_storagetype'] = $_POST['upload_storagetype']; $pref['upload_maxfilesize'] = $_POST['upload_maxfilesize']; $pref['upload_class'] = $_POST['upload_class']; $pref['upload_enabled'] = (FILE_UPLOADS ? $_POST['upload_enabled'] : 0); - if ($pref['upload_enabled'] && !$sql->db_Select("links", "*", "link_url='upload.php' ")) { - $sql->db_Insert("links", "0, '".UPLLAN_44."', 'upload.php', '', '', 1,0,0,0,0"); + if ($pref['upload_enabled'] && !$sql->db_Select("links", "*", "link_url='upload.php' ")) + { + $sql->db_Insert("links", "0, '".UPLLAN_44."', 'upload.php', '', '', 1,0,0,0,0"); } - if (!$pref['upload_enabled'] && $sql->db_Select("links", "*", "link_url='upload.php' ")) { + if (!$pref['upload_enabled'] && $sql->db_Select("links", "*", "link_url='upload.php' ")) + { $sql->db_Delete("links", "link_url='upload.php' "); } @@ -101,164 +120,150 @@ if (isset($_POST['optionsubmit'])) { $message = UPLLAN_2; } -if (isset($message)) { - require_once(e_HANDLER."message_handler.php"); - message_handler("ADMIN_MESSAGE", $message); +if (isset($message)) +{ + require_once(e_HANDLER."message_handler.php"); + message_handler("ADMIN_MESSAGE", $message); } -if (!FILE_UPLOADS) { - message_handler("ADMIN_MESSAGE", UPLLAN_41); +if (!FILE_UPLOADS) +{ + message_handler("ADMIN_MESSAGE", UPLLAN_41); } -// view ------------------------------------------------------------------------------------------------------------------------------------------------------------------- +switch ($action) +{ + case 'filetypes' : + if(!getperms("0")) exit; -if ($action == "view") { - $sql->db_Select("upload", "*", "upload_id='$id'"); - $row = $sql->db_Fetch(); - extract($row); + $definition_source = UPLLAN_58; + $source_file = ''; + $edit_upload_list = varset($_POST['upload_do_edit'],FALSE); - $post_author_id = substr($upload_poster, 0, strpos($upload_poster, ".")); - $post_author_name = substr($upload_poster, (strpos($upload_poster, ".")+1)); - $poster = (!$post_author_id ? "".$post_author_name."" : "".$post_author_name.""); - $upload_datestamp = $gen->convert_date($upload_datestamp, "long"); - - $text = "
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
".UPLLAN_3."$upload_id
".LAN_DATE."$upload_datestamp
".UPLLAN_5."$poster
".UPLLAN_6."$upload_email
".UPLLAN_7."".($upload_website ? "$upload_website" : " - ")."
".UPLLAN_8."".($upload_name ? $upload_name: " - ")."
".UPLLAN_9."".($upload_version ? $upload_version : " - ")."
".UPLLAN_10."".(is_numeric($upload_file) ? "Binary file ID ".$upload_file : "$upload_file")."
".UPLLAN_11."".parsesize($upload_filesize)."
".UPLLAN_12."".($upload_ss ? "".$upload_ss."" : " - ")."
".UPLLAN_13."$upload_description
".UPLLAN_14."".($upload_demo ? $upload_demo : " - ")."
".LAN_OPTIONS."".UPLAN_COPYTODLM." | ".UPLLAN_16." | ".UPLLAN_17."
-
"; - - $ns->tablerender(UPLLAN_18, $text); - -} + if (isset($_POST['generate_filetypes_xml'])) + { // Write back edited data to filetypes_.xml + $file_text = "\n"; + foreach ($_POST['file_class_select'] as $k => $c) + { + if (!isset($_POST['file_line_delete_'.$c]) && varsettrue($_POST['file_type_list'][$k])) + { +// echo "Key: {$k} Class: {$c} Delete: {$_POST['file_line_delete'][$k]} List: {$_POST['file_type_list'][$k]} Size: {$_POST['file_maxupload'][$k]}
"; + $file_text .= " \n"; + } + } + $file_text .= "
\n"; + if ((($handle = fopen(e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES,'wt')) == FALSE) + || (fwrite($handle,$file_text) == FALSE) + || (fclose($handle) == FALSE)) + { + $text = UPLLAN_61.e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES; + } + else + { + $text = ''; + $text .= '
'.UPLLAN_59.e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES.'. '.UPLLAN_60.e_ADMIN.e_READ_FILETYPES.'
'; + } + $ns->tablerender(UPLLAN_49, $text); + } -// list ------------------------------------------------------------------------------------------------------------------------------------------------------------------- -$imgd = e_BASE.$IMAGES_DIRECTORY; -$text = "
- - - - - - - - -"; - -$text .= "\n"; -} else { - - $activeUploads = $sql -> db_getList(); - - $text .= UPLLAN_20." ".($active_uploads == 1 ? UPLAN_IS : UPLAN_ARE).$active_uploads." ".($active_uploads == 1 ? UPLLAN_21 : UPLLAN_27)." ..."; - - $text .= ""; - - foreach($activeUploads as $row) + $current_perms = array(); + if (($edit_upload_list && is_readable(e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES)) || (!$edit_upload_list && is_readable(e_ADMIN.e_READ_FILETYPES))) { - extract($row); - $post_author_id = substr($upload_poster, 0, strpos($upload_poster, ".")); - $post_author_name = substr($upload_poster, (strpos($upload_poster, ".")+1)); - $poster = (!$post_author_id ? "".$post_author_name."" : "".$post_author_name.""); - $upload_datestamp = $gen->convert_date($upload_datestamp, "short"); - $text .= " - - - - - - + require_once(e_HANDLER.'xml_class.php'); + $xml = new xmlClass; + $source_file = $edit_upload_list ? e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES : e_ADMIN.e_READ_FILETYPES; + $temp_vars = $xml->loadXMLfile($source_file, true, false); + if ($temp_vars === FALSE) + { + echo "Error parsing XML file!"; + } + else + { +// echo "
";
+//		var_dump($temp_vars);
+//		echo "
"; + foreach ($temp_vars['class'] as $v1) + { + $v = $v1['@attributes']; + $current_perms[$v['name']] = array('type' => $v['type'],'maxupload' => $v['maxupload']); + } + } + } + elseif (is_readable(e_ADMIN.'filetypes.php')) + { + $source_file = 'filetypes.php'; + $current_perms[e_UC_MEMBER] = array('type' => implode(',',array_keys(get_allowed_filetypes('filetypes.php', ''))),'maxupload' => '2M'); + if (is_readable(e_ADMIN.'admin_filetypes.php')) + { + $current_perms[e_UC_ADMIN] = array('type' => implode(',',array_keys(get_allowed_filetypes('admin_filetypes.php', ''))),'maxupload' => '2M'); + $source_file .= ' + admin_filetypes.php'; + } + } + else + { // Set a default + $current_perms[e_UC_MEMBER] = array('type' => 'zip,tar,gz,jpg,png','maxupload' => '2M'); + } + $text = "
+
+
".UPLLAN_22."".LAN_DATE."".UPLLAN_5."".UPLLAN_23."".UPLLAN_24."".UPLLAN_42."
"; - -if (!$active_uploads = $sql->db_Select("upload", "*", "upload_active=0 ORDER BY upload_id ASC")) { - $text .= UPLLAN_19.".\n
".$upload_id ."".$upload_datestamp."".$poster."".$upload_name ."".$upload_file ." -
-
".UPLAN_COPYTODLS." - ".UPLLAN_16." - toJS(UPLLAN_45." [ $upload_name ]")."') \"/> -
+ + + + + + + + + + + + + + + + + + "; + foreach ($current_perms as $uclass => $uinfo) + { + $text .= " + + + + + "; } -} -$text .= "
". + str_replace(array('--SOURCE--', '--DEST--'),array(e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES,e_ADMIN.e_READ_FILETYPES),UPLLAN_52)."
".UPLLAN_57.$source_file."
".UPLLAN_53."".UPLLAN_54."".UPLLAN_55."".UPLAN_DELETE."
\n
"; + // Now put up a box to add a new setting + $text .= " + + + + +   + "; + $text .= " + + + + + + + "; -$ns->tablerender(UPLLAN_43, $text); - - -// options ------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -if (is_readable(e_ADMIN.'filetypes.php')) { - $allowed_filetypes = trim(file_get_contents(e_ADMIN.'filetypes.php')); -} - -$text = "
-
+ $ns->tablerender(UPLLAN_49, $text); + break; + case 'options' : + if(!getperms("0")) exit; + $text = "
+ - - - - - @@ -303,31 +301,187 @@ $text = "
".UPLLAN_25."
@@ -281,13 +286,6 @@ $text = "
".UPLLAN_35."
- ".UPLLAN_48."
".$allowed_filetypes." -
".UPLLAN_37."
".UPLLAN_38."
". $rs->form_close()."
"; -$ns->tablerender(LAN_OPTIONS, $text); + $ns->tablerender(LAN_OPTIONS, $text); + break; + + case 'view' : + $sql->db_Select("upload", "*", "upload_id='{$id}'"); + $row = $sql->db_Fetch(); + extract($row); + + $post_author_id = substr($upload_poster, 0, strpos($upload_poster, ".")); + $post_author_name = substr($upload_poster, (strpos($upload_poster, ".")+1)); + $poster = (!$post_author_id ? "".$post_author_name."" : "".$post_author_name.""); + $upload_datestamp = $gen->convert_date($upload_datestamp, "long"); + + $text = "
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
".UPLLAN_3."{$upload_id}
".LAN_DATE."{$upload_datestamp}
".UPLLAN_5."{$poster}
".UPLLAN_6."{$upload_email}
".UPLLAN_7."".($upload_website ? "{$upload_website}" : " - ")."
".UPLLAN_8."".($upload_name ? $upload_name: " - ")."
".UPLLAN_9."".($upload_version ? $upload_version : " - ")."
".UPLLAN_10."".(is_numeric($upload_file) ? "Binary file ID ".$upload_file : "$upload_file")."
".UPLLAN_11."".parsesize($upload_filesize)."
".UPLLAN_12."".($upload_ss ? "".$upload_ss."" : " - ")."
".UPLLAN_13."{$upload_description}
".UPLLAN_14."".($upload_demo ? $upload_demo : " - ")."
".LAN_OPTIONS."".UPLAN_COPYTODLM." | ".UPLLAN_16." | ".UPLLAN_17."
+
"; + + $ns->tablerender(UPLLAN_18, $text); + // Intentionally fall through into list mode + + case 'list' : + default : + $imgd = e_BASE.$IMAGES_DIRECTORY; + $text = "
+ + + + + + + + + + + + + + + + + + + "; + + $text .= "\n"; + } + else + { + $activeUploads = $sql -> db_getList(); + + $text .= UPLLAN_20." ".($active_uploads == 1 ? UPLAN_IS : UPLAN_ARE).$active_uploads." ".($active_uploads == 1 ? UPLLAN_21 : UPLLAN_27)." ..."; + $text .= ""; + + foreach($activeUploads as $row) + { + extract($row); + $post_author_id = substr($upload_poster, 0, strpos($upload_poster, ".")); + $post_author_name = substr($upload_poster, (strpos($upload_poster, ".")+1)); + $poster = (!$post_author_id ? "".$post_author_name."" : "".$post_author_name.""); + $upload_datestamp = $gen->convert_date($upload_datestamp, "short"); + $text .= " + + + + + + + + "; + } + } + $text .= "
".UPLLAN_22."".LAN_DATE."".UPLLAN_5."".UPLLAN_23."".UPLLAN_8."".UPLLAN_35."".UPLLAN_42."
"; + + if (!$active_uploads = $sql->db_Select("upload", "*", "upload_active=0 ORDER BY upload_id ASC")) + { + $text .= UPLLAN_19.".\n
".$upload_id ."".$upload_datestamp."".$poster."".$upload_name ."".$upload_file ."".parsesize($upload_filesize)." + +
".UPLAN_COPYTODLS." + ".UPLLAN_16." + toJS(UPLLAN_45." [ {$upload_name} ]")."') \"/> +
\n
"; + + $ns->tablerender(UPLLAN_43, $text); +} // end - switch($action) -function parsesize($size) { - $kb = 1024; - $mb = 1024 * $kb; - $gb = 1024 * $mb; - $tb = 1024 * $gb; - if ($size < $kb) { - return $size." b"; - } - else if($size < $mb) { - return round($size/$kb, 2)." kb"; - } - else if($size < $gb) { - return round($size/$mb, 2)." mb"; - } - else if($size < $tb) { - return round($size/$gb, 2)." gb"; - } else { - return round($size/$tb, 2)." tb"; - } + +function upload_adminmenu() +{ + $action = (e_QUERY) ? e_QUERY : "list"; + + $var['list']['text'] = UPLLAN_51; + $var['list']['link'] = e_SELF."?list"; + $var['list']['perm'] = "V"; + + if(getperms("0")) + { + $var['filetypes']['text'] = UPLLAN_49; + $var['filetypes']['link'] = e_SELF."?filetypes"; + $var['filetypes']['perm'] = "0"; + + $var['options']['text'] = UPLLAN_50; + $var['options']['link'] = e_SELF."?options"; + $var['options']['perm'] = "0"; + } + show_admin_menu(UPLLAN_43, $action, $var); } + require_once("footer.php"); ?> \ No newline at end of file diff --git a/e107_files/misc/index.html b/e107_files/misc/index.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/e107_files/misc/null.txt b/e107_files/misc/null.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/e107_handlers/upload_handler.php b/e107_handlers/upload_handler.php index 7fe44bacc..293b66536 100644 --- a/e107_handlers/upload_handler.php +++ b/e107_handlers/upload_handler.php @@ -12,9 +12,20 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/e107_handlers/upload_handler.php,v $ -| $Revision: 1.12 $ -| $Date: 2008-03-17 20:45:29 $ +| $Revision: 1.13 $ +| $Date: 2008-04-22 20:32:40 $ | $Author: e107steved $ + + +********** TEST VERSION DOES INTERMEDIATE COPY *************** +Unaltered code to: + V0.7.x File V1.33 + V0.8.x File V1.12 + +To do: + 1. Criteria for intermediate copy + 2. Make get_file_types compatible with XML counterpart - array of filetype/max size + 3. Check sizes - may be different for various file types for non-admin user, for example +---------------------------------------------------------------+ */ @@ -24,6 +35,14 @@ include_lan(e_LANGUAGEDIR.e_LANGUAGE."/lan_upload_handler.php"); //define("UH_DEBUG",TRUE); define("UH_DEBUG",FALSE); + + +define('e_UPLOAD_TEMP_DIR', e_FILE.'temp/'); // Temporary directory +define('e_READ_FILETYPES','filetypes.xml'); // Upload permissions +define('e_SAVE_FILETYPES','filetypes_.xml'); + + + /* File upload handler - this is the preferred interface for new code ------------------- @@ -43,7 +62,7 @@ Parameters: $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 - Always looks in the admin directory - - defaults to e_ADMIN.admin_filetypes.php for admins (if file exists), otherwise e_ADMIN.filetypes.php for users. + - defaults to e_ADMIN.filetypes.xml, else e_ADMIN.admin_filetypes.php for admins (if file exists), otherwise e_ADMIN.filetypes.php for users. - FALSE disables this option (which implies that 'extra_file_types' is used) 'file_mask' - comma-separated list of file types which if defined limits the allowed file types to those which are in both this list and the file specified by the 'filetypes' option. Enables restriction to, for example, image files. @@ -95,7 +114,17 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) global $admin_log; + if (ini_get('open_basedir') != '') + { // Need to move file to intermediate directory before we can read its contents to check it. + $ul_temp_dir = e_UPLOAD_TEMP_DIR; + } + else + { + $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); +// $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); @@ -112,25 +141,9 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) - $file_mask = varset($options['file_mask'],''); - if (isset($options['filetypes'])) - { - $allowed_filetypes = get_allowed_filetypes($options['filetypes'], $file_mask); - } - elseif (ADMIN && is_readable(e_ADMIN.'admin_filetypes.php')) - { - $allowed_filetypes = get_allowed_filetypes('admin_filetypes.php', $file_mask); - } - else - { - $allowed_filetypes = get_allowed_filetypes('filetypes.php', $file_mask); - } - - $final_chmod = varset($options['final_chmod'],0644); - if (isset($options['file_array_name'])) { $files = $_FILES[$options['file_array_name']]; @@ -154,24 +167,9 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) $uploaded = array(); - // Work out maximum allowable file size - if (UH_DEBUG) - { $admin_log->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('upload_max_filesize'), $max_upload_size, 'lt'); - if (isset($options['max_upload_size'])) - { - $max_upload_size = file_size_decode($options['max_upload_size'], $max_upload_size, 'lt'); - } - else - { - 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 (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 = 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'],'')); + $max_upload_size = set_max_size($allowed_filetypes, $max_upload_size); // That's the basics set up - we can start processing files now @@ -182,81 +180,93 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) $c = 0; foreach ($files['name'] as $key => $name) { - if (($name != '') || $files['size'][$key]) // Need this check for things like file manager which allow multiple possible uploads - { - $name = preg_replace("/[^a-z0-9._-]/", "", str_replace(" ", "_", str_replace("%20", "_", strtolower($name)))); - $raw_name = $name; // Save 'proper' file name - useful for display + $first_error = FALSE; // Clear error flag + if (($name != '') || $files['size'][$key]) // Need this check for things like file manager which allow multiple possible uploads + { + $name = preg_replace("/[^a-z0-9._-]/", "", str_replace(" ", "_", str_replace("%20", "_", strtolower($name)))); + $raw_name = $name; // Save 'proper' file name - useful for display + $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)) - { - $first_error = 249; // 'Too many files uploaded' error - } - else - { - $first_error = $files['error'][$key]; // Start with whatever error PHP gives us for the file - } + if ($max_file_count && ($c > $max_file_count)) + { + $first_error = 249; // 'Too many files uploaded' error + } + else + { + $first_error = $files['error'][$key]; // Start with whatever error PHP gives us for the file + } - if (!$first_error) - { // Check file size early on - if ($files['size'][$key] == 0) - { - $first_error = 4; // Standard error code for zero size file + if (!$first_error) + { // Check file size early on + if ($files['size'][$key] == 0) + { + $first_error = 4; // Standard error code for zero size file + } + elseif ($files['size'][$key] > $max_upload_size) + { + $first_error = 254; + } + elseif (isset($allowed_filetypes[$file_ext]) && ($allowed_filetypes[$file_ext] > 0) && ($files['size'][$key] > $allowed_filetypes[$file_ext])) + { // XML file set limits per extension + $first_error = 254; + } } - elseif ($files['size'][$key] > $max_upload_size) - { - $first_error = 254; - } - } - if (!$first_error) - { - $uploadfile = $files['tmp_name'][$key]; // Name in temporary directory - if (!$uploadfile) $first_error = 253; - } + if (!$first_error) + { + $uploadfile = $files['tmp_name'][$key]; // Name in temporary directory + if (!$uploadfile) $first_error = 253; + } - if (!$first_error) - { - // Need to support multiple files with the same 'real' name in some cases - if (strpos($fileinfo,"attachment") === 0) - { // For attachments, add in a prefix plus time and date to give a unique file name - $addbit = explode('+',$fileinfo,2); - $name = time()."_".USERID."_".trim($addbit[1]).$name; - } - elseif (strpos($fileinfo,"prefix") === 0) - { // For attachments, avatars, photos etc alternatively just add a prefix we've been passed - $addbit = explode('+',$fileinfo,2); - $name = trim($addbit[1]).$name; - } + if (!$first_error) + { + // Need to support multiple files with the same 'real' name in some cases + if (strpos($fileinfo,"attachment") === 0) + { // For attachments, add in a prefix plus time and date to give a unique file name + $addbit = explode('+',$fileinfo,2); + $name = time()."_".USERID."_".trim($addbit[1]).$name; + } + elseif (strpos($fileinfo,"prefix") === 0) + { // For attachments, avatars, photos etc alternatively just add a prefix we've been passed + $addbit = explode('+',$fileinfo,2); + $name = trim($addbit[1]).$name; + } - $destination_file = $uploaddir."/".$name; - - if ($fileinfo == "unique" && file_exists($destination_file)) - { // Modify destination name to make it unique - but only if target file name exists - $name = time()."_".$name; $destination_file = $uploaddir."/".$name; - } - if (file_exists($destination_file) && !$overwrite) $first_error = 250; // Invent our own error number - duplicate file - } + if ($fileinfo == "unique" && file_exists($destination_file)) + { // Modify destination name to make it unique - but only if target file name exists + $name = time()."_".$name; + $destination_file = $uploaddir."/".$name; + } + + if (file_exists($destination_file) && !$overwrite) $first_error = 250; // Invent our own error number - duplicate file + } - if (!$first_error) - { - $tpos = strrchr($files['name'][$key], "."); // Require uploaded files to have an extension - if ($tpos !== FALSE) - { - $fileext = strtolower($tpos); - $tpos = (($file_status = vet_file($uploadfile, $name, $allowed_filetypes, varset($options['extra_file_types'],FALSE))) === TRUE); - } - if ($tpos === FALSE) + if (!$first_error) { + $tpos = FALSE; + if ($file_ext != '') // Require any uploaded file to have an extension + { + if ($ul_temp_dir) + { // Need to move file to our own temporary directory + $tempfilename = $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); + @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); + } + if ($tpos === FALSE) + { // File type upload not permitted - error message and abort - $first_error = 251; // Invent our own error number - file type not permitted + $first_error = 251; // Invent our own error number - file type not permitted + } } - } if (!$first_error) @@ -271,7 +281,7 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) if ($save_to_db) { // 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 - if (UH_DEBUG) $admin_log->e_log_event(10,__FILE__."|".__FUNCTION__."@".__LINE__,"DEBUG","Upload Handler test","Save to DB {$c}: ".$uploaded[$c]['name'],FALSE,FALSE); + 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); $data = mysql_real_escape_string(fread(fopen($files['tmp_name'][$c], "rb"), filesize($uploadfile))); set_magic_quotes_runtime(get_magic_quotes_gpc()); @@ -289,7 +299,7 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) { // Store as flat file // $method = (OPEN_BASEDIR == FALSE ? "copy" : "move_uploaded_file"); // if (@$method($uploadfile, $destination_file)) - if (@move_uploaded_file($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); 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); @@ -494,6 +504,7 @@ function file_upload($uploaddir, $avatar = FALSE, $fileinfo = "", $overwrite = " + /* ==================================================================== VETTING AND UTILITY ROUTINES @@ -515,7 +526,7 @@ function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = F { // 1. Start by checking against filetypes - that's the easy one! $file_ext = strtolower(substr(strrchr($target_name, "."), 1)); - if (!in_array($file_ext, $allowed_filetypes)) + if (!isset($allowed_filetypes[$file_ext])) { if (is_bool($unknown)) return 1; // Reject out of hand if no possible alternative extensions // Otherwise, it could be in the supplementary list @@ -575,6 +586,7 @@ function vet_file($filename, $target_name, $allowed_filetypes = '', $unknown = F // Get array of file types (file extensions) which are permitted - reads a definition file. +// 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 function get_allowed_filetypes($def_file = FALSE, $file_mask = '') { @@ -604,13 +616,14 @@ function get_allowed_filetypes($def_file = FALSE, $file_mask = '') $ftype = strtolower(trim(str_replace('.', '', $ftype))); if (!$file_mask || in_array($ftype, $file_array)) { - $ret[] = $ftype; + $ret[$ftype] = -1; } - } + } return $ret; } + // Parse a file size string (e.g. 16M) and compute the simple numeric value. // If $action is empty, return this value. // If $source evaluates to zero, return the compare value instead @@ -619,6 +632,7 @@ function get_allowed_filetypes($def_file = FALSE, $file_mask = '') function file_size_decode($source, $compare = 0, $action = '') { $source = trim($source); + if (strtolower(substr($source,-1,1)) == 'b') $source = substr($source,0,-1); // Trim a trailing byte indicator $mult = 1; $nostrip = FALSE; if (!$source || is_numeric($source)) @@ -652,4 +666,159 @@ function file_size_decode($source, $compare = 0, $action = '') return 0; } + + +function parsesize($size) +{ + $kb = 1024; + $mb = 1024 * $kb; + $gb = 1024 * $mb; + $tb = 1024 * $gb; + if ($size < $kb) { + return $size." b"; + } + else if($size < $mb) { + return round($size/$kb, 2)." kb"; + } + else if($size < $gb) { + return round($size/$mb, 2)." Mb"; + } + else if($size < $tb) { + return round($size/$gb, 2)." Gb"; + } else { + return round($size/$tb, 2)." Tb"; + } +} + + +// Similar to get_allowed_filetypes(), but expects an XML file +// Returns an array where key is the file extension; value is max upload size +function get_XML_filetypes($def_file = FALSE, $file_mask = '') +{ + $ret = array(); + if ($def_file === FALSE) return $ret; + + if ($file_mask) + { + $file_array = explode(',', $file_mask); + foreach ($file_array as $k => $f) + { + $file_array[$k] = trim($f); + } + } + + if ($def_file && is_readable(e_ADMIN.$def_file)) + { + require_once(e_HANDLER.'xml_class.php'); + $xml = new xmlClass; + $temp_vars = $xml->loadXMLfile(e_ADMIN.$def_file, true, false); + if ($temp_vars === FALSE) return $ret; + foreach ($temp_vars['class'] as $v1) + { + $v = $v1['@attributes']; + if (check_class($v['name'])) + { + $current_perms[$v['name']] = array('type' => $v['type'],'maxupload' => $v['maxupload']); + $a_filetypes = explode(',', $v['type']); + foreach ($a_filetypes as $ftype) + { + $ftype = strtolower(trim(str_replace('.', '', $ftype))); // File extension + if (!$file_mask || in_array($ftype, $file_array)) + { // We can load this extension + if (isset($ret[$ftype])) + { + $ret[$ftype] = file_size_decode($v['maxupload'],$ret[$ftype], 'gt'); // Use largest value + } + else + { + $ret[$ftype] = file_size_decode($v['maxupload']); + } + } + } + } + } + } +// echo '
';
+//  var_dump($ret);
+//  echo '
'; + return $ret; +} + + +// Calculate 'global' maximum upload size - the maximum before extension-specific restrictions taken into account +function calc_max_upload_size($max_up = -1) +{ + global $pref, $admin_log; + // Work out maximum allowable file size + if (UH_DEBUG) + { + $admin_log->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('upload_max_filesize'), $max_upload_size, 'lt'); + if ($max_up > 0) + { + $max_upload_size = file_size_decode($max_up, $max_upload_size, 'lt'); + } + else + { + 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 (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; +} + + + + +// Get an array of permitted filetypes according to a set hierarchy. +function get_filetypes($file_mask = FALSE, $filename = '') +{ + if ($filename != '') + { + if (strtolower(substr($filename) == '.xml')) + { + return get_allowed_filetypes($filename, $file_mask); + } + return get_allowed_filetypes($filename, $file_mask); + } + + if (is_readable(e_ADMIN.e_READ_FILETYPES)) + { + return get_XML_filetypes(e_READ_FILETYPES, $file_mask); + } + + if (ADMIN && is_readable(e_ADMIN.'admin_filetypes.php')) + { + return get_allowed_filetypes('admin_filetypes.php', $file_mask); + } + + if (is_readable(e_ADMIN.'filetypes.php')) + { + return get_allowed_filetypes('filetypes.php', $file_mask); + } + return array(); // Just an empty array +} + + +// Scans the array of allowed file types, updates allowed max size as appropriate. +// Returns largest allowed file size +function set_max_size(&$allowed_filetypes, $max_upload_size) +{ + $new_max = 0; + foreach ($allowed_filetypes as $t => $s) + { + if ($s < 0) + { // Unspecified max - use the global value + $allowed_filetypes[$t] = $max_upload_size; + } + elseif ($allowed_filetypes[$t] > $max_upload_size) $allowed_filetypes[$t] = $max_upload_size; + if ($allowed_filetypes[$t] > $new_max) $new_max = $allowed_filetypes[$t]; + } + return $new_max; +} + + ?> \ No newline at end of file diff --git a/e107_languages/English/admin/help/upload.php b/e107_languages/English/admin/help/upload.php index 0ec0ab8f0..3c7ab8b6e 100644 --- a/e107_languages/English/admin/help/upload.php +++ b/e107_languages/English/admin/help/upload.php @@ -11,14 +11,33 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/help/upload.php,v $ -| $Revision: 1.1.1.1 $ -| $Date: 2006-12-02 04:34:43 $ -| $Author: mcfly_e107 $ +| $Revision: 1.2 $ +| $Date: 2008-04-22 20:32:49 $ +| $Author: e107steved $ +----------------------------------------------------------------------------+ */ if (!defined('e107_INIT')) { exit; } +if (e_QUERY) list($action,$junk) = explode('.',e_QUERY); else $action = 'list'; -$text = "From here you can allow / disallow the ability for users to upload files and manage those files that have been uploaded."; +switch ($action) +{ + case 'filetypes' : + $text = "The file types and maximum file size which can be uploaded are set by user class. This option generates a file called ".e_UPLOAD_TEMP_DIR.e_SAVE_FILETYPES.", + which must be copied or moved to directory ".e_ADMIN_ABS." and renamed to ".e_READ_FILETYPES." before it takes effect.
+ One definition per class is permitted.
+ Note that these definitions apply site-wide, even if the public uploads feature is disabled."; + break; + case 'options' : + $text = "The complete public uploads system may be disabled here.
+ Flatfile storage is generally appropriate (otherwise the maximum file size is hard-limited to 500kb).
+ The maximum filesize overrides any definitions set in filetypes.xml.
+ Public uploads may be restricted to a particular user class, but these settings also apply to other areas of the site where uploads may be permitted, such as + news and forms."; + break; + case 'view' : + default : + $text = "This page lists any submitted uploads. You may choose to delete them, transfer them to downloads, or post them to news"; +} $ns -> tablerender("Public Uploads Help", $text); ?> \ No newline at end of file diff --git a/e107_languages/English/admin/lan_upload.php b/e107_languages/English/admin/lan_upload.php index e1096d21e..8021a665f 100644 --- a/e107_languages/English/admin/lan_upload.php +++ b/e107_languages/English/admin/lan_upload.php @@ -4,8 +4,8 @@ | e107 website system - Language File. | | $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_upload.php,v $ -| $Revision: 1.2 $ -| $Date: 2007-09-22 12:40:12 $ +| $Revision: 1.3 $ +| $Date: 2008-04-22 20:32:49 $ | $Author: e107steved $ +----------------------------------------------------------------------------+ */ @@ -39,34 +39,57 @@ define("UPLLAN_26", "No public uploads will be permitted if disabled"); define("UPLLAN_27", "unmoderated public uploads"); define("UPLLAN_29", "Storage type"); -define("UPLLAN_30", "Choose how to store uploaded files, either as normal files on server or as binary info in database
Note binary is only suitable for smaller files under approximately 500kb"); +define("UPLLAN_30", "Choose how to store uploaded files, either as normal files on server or as binary info in database
Note binary is only suitable for smaller files, and is hard-limited to a maximum of approximately 500kb"); define("UPLLAN_31", "Flatfile"); define("UPLLAN_32", "Binary"); define("UPLLAN_33", "Maximum file size"); -define("UPLLAN_34", "Maximum upload size in bytes - leave blank to use settings from php.ini"); -define("UPLLAN_35", "Allowed file types"); -define("UPLLAN_36", "Please enter one type per line"); +define("UPLLAN_34", "Absolute maximum upload size in bytes. Further limited by settings from php.ini, and by the settings in filetypes.xml"); +define("UPLLAN_35", 'Size'); +//define("UPLLAN_36", "Please enter one type per line"); define("UPLLAN_37", "Permission"); define("UPLLAN_38", "Select to allow only certain users to upload"); define("UPLLAN_39", "Submit"); define("UPLLAN_41", "Please note - file uploads are disabled from your php.ini, it will not be possible to upload files until you set it to On."); - define("UPLLAN_42", "Actions"); define("UPLLAN_43", "Uploads"); define("UPLLAN_44", "Upload"); - define("UPLLAN_45", "Are you sure you want to delete the following file..."); define("UPLAN_COPYTODLM", "copy to download manager"); define("UPLAN_IS", "is "); define("UPLAN_ARE", "are "); define("UPLAN_COPYTODLS", "Copy to Downloads"); +define('UPLAN_DELETE', 'Delete'); +/* define("UPLLAN_48", "For security reasons allowed file types has been moved out of the database into a flatfile located in your admin directory. To use, rename the file e107_admin/filetypes_.php to e107_admin/filetypes.php and add a comma delimited list of file type extensions to it. You should not allow the upload of .html, .txt, etc., as an attacker may upload a file of this type which includes malicious javascript. You should also, of course, not allow the upload of .php files or any other type of executable script."); +*/ +define('UPLLAN_49', 'File Types'); +define('UPLLAN_50', 'Options'); +define('UPLLAN_51', 'List Uploads'); +define('UPLLAN_52', 'This page helps you create a file for managing file upload permissions. The file is saved as --SOURCE--, and must be copied to --DEST-- before it takes effect.'); +define('UPLLAN_53', 'User Class'); +define('UPLLAN_54', 'File Extensions'); +define('UPLLAN_55', 'Max upload size'); +define('UPLLAN_56', 'Generate file'); +define('UPLLAN_57', 'Source for values: '); +define('UPLLAN_58', 'Default'); +define('UPLLAN_59', 'Settings written to '); +define('UPLLAN_60', 'Now move this file to '); +define('UPLLAN_61', 'Error writing file: '); +define('UPLLAN_62', ''); +define('UPLLAN_63', ''); +define('UPLLAN_64', ''); +define('UPLLAN_65', ''); +define('UPLLAN_66', ''); +define('UPLLAN_67', ''); +define('UPLLAN_68', ''); +define('UPLLAN_69', ''); +define('UPLLAN_70', ''); ?> \ No newline at end of file diff --git a/e107_languages/English/lan_upload.php b/e107_languages/English/lan_upload.php index 841dc466d..9c168f15d 100644 --- a/e107_languages/English/lan_upload.php +++ b/e107_languages/English/lan_upload.php @@ -4,8 +4,8 @@ | e107 website system - Language File. | | $Source: /cvs_backup/e107_0.8/e107_languages/English/lan_upload.php,v $ -| $Revision: 1.2 $ -| $Date: 2007-11-23 21:52:44 $ +| $Revision: 1.3 $ +| $Date: 2008-04-22 20:32:50 $ | $Author: e107steved $ +----------------------------------------------------------------------------+ */ @@ -16,6 +16,12 @@ define('LAN_UL_002', 'You do not have the correct permissions to upload files to define('LAN_UL_020', 'Error'); define('LAN_UL_021', 'Upload Failure'); +define('LAN_UL_022', 'May vary by file type'); +define('LAN_UL_023', 'Type'); +define('LAN_UL_024', 'Max Size'); +define('LAN_UL_025', 'Uploads not allowed '); +define('LAN_UL_026', ''); +define('LAN_UL_027', ''); define("LAN_61", "Your Name: "); define("LAN_112", "Email Address: "); @@ -35,7 +41,7 @@ define("LAN_414", "Working demo"); define("LAN_415", "enter URL to site where demo can be viewed"); define("LAN_416", "Submit and Upload"); define("LAN_417", "Upload File"); -define("LAN_418", "Maximum file size: "); +define("LAN_418", "Absolute maximum file size: "); define("DOWLAN_11", "Category"); define("LAN_419", "Allowed filetypes"); define("LAN_420", "fields are required"); diff --git a/upload.php b/upload.php index 2e7983aef..fdee8eb9e 100644 --- a/upload.php +++ b/upload.php @@ -11,9 +11,9 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/upload.php,v $ -| $Revision: 1.4 $ -| $Date: 2008-01-10 03:14:09 $ -| $Author: e107coders $ +| $Revision: 1.5 $ +| $Date: 2008-04-22 20:32:40 $ +| $Author: e107steved $ +----------------------------------------------------------------------------+ */ require_once("class2.php"); @@ -148,10 +148,10 @@ if ($message) $text = "
- + - +
".DOWLAN_11.": "; @@ -170,19 +170,39 @@ $text .= " $text .= "".LAN_406."
".LAN_419.":"; -if (is_readable(e_ADMIN.'filetypes.php')) +require_once(e_HANDLER.'upload_handler.php'); + +$a_filetypes = get_filetypes(); +if (count($a_filetypes) == 0) { - $a_filetypes = trim(file_get_contents(e_ADMIN.'filetypes.php')); - $a_filetypes = explode(',', $a_filetypes); - foreach ($a_filetypes as $ftype) + $text .= LAN_UL_025."
+
+
"; + $ns->tablerender(LAN_417, $text); + require_once(FOOTERF); +} +$max_upload_size = calc_max_upload_size(-1); // Find overriding maximum upload size +$max_upload_size = set_max_size($a_filetypes, $max_upload_size); + + +if (ADMIN) +{ + $upper_limit = calc_max_upload_size(); + $allowed_filetypes = ""; + foreach ($a_filetypes as $type => $size) { - $sa_filetypes[] = '.'.trim(str_replace('.', '', $ftype)); + $allowed_filetypes .= ""; } - $allowed_filetypes = implode(' | ', $sa_filetypes); + $allowed_filetypes .= "
".LAN_UL_023."  ".LAN_UL_024."
{$type}".parsesize($size)."
"; +} +else +{ + $a_filetypes = array_keys($a_filetypes); + $allowed_filetypes = implode(' | ', $a_filetypes); } $text .= " ".$allowed_filetypes."
".LAN_407."
- ".LAN_418.($pref['upload_maxfilesize'] ? $pref['upload_maxfilesize'] : ini_get('upload_max_filesize'))."
"; + ".LAN_418.parsesize($max_upload_size)." (".LAN_UL_022.")
"; $text .= "".LAN_408." ".LAN_420." ";