function profileSaveAvatarData(&$value) { global $modSettings, $sourcedir, $smcFunc, $profile_vars, $cur_profile, $context; $memID = $context['id_member']; if (empty($memID) && !empty($context['password_auth_failed'])) { return false; } require_once $sourcedir . '/ManageAttachments.php'; // We need to know where we're going to be putting it.. if (!empty($modSettings['custom_avatar_enabled'])) { $uploadDir = $modSettings['custom_avatar_dir']; $id_folder = 1; } elseif (!empty($modSettings['currentAttachmentUploadDir'])) { if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // Just use the current path for temp files. $uploadDir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; $id_folder = $modSettings['currentAttachmentUploadDir']; } else { $uploadDir = $modSettings['attachmentUploadDir']; $id_folder = 1; } $downloadedExternalAvatar = false; if ($value == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && strlen($_POST['userpicpersonal']) > 7 && !empty($modSettings['avatar_download_external'])) { if (!is_writable($uploadDir)) { fatal_lang_error('attachments_no_write', 'critical'); } require_once $sourcedir . '/Subs-Package.php'; $url = parse_url($_POST['userpicpersonal']); $contents = fetch_web_data('http://' . $url['host'] . (empty($url['port']) ? '' : ':' . $url['port']) . str_replace(' ', '%20', trim($url['path']))); if ($contents != false && ($tmpAvatar = fopen($uploadDir . '/avatar_tmp_' . $memID, 'wb'))) { fwrite($tmpAvatar, $contents); fclose($tmpAvatar); $downloadedExternalAvatar = true; $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID; } } if ($value == 'none') { $profile_vars['avatar'] = ''; // Reset the attach ID. $cur_profile['id_attach'] = 0; $cur_profile['attachment_type'] = 0; $cur_profile['filename'] = ''; removeAttachments(array('id_member' => $memID)); } elseif ($value == 'server_stored' && allowedTo('profile_server_avatar')) { $profile_vars['avatar'] = strtr(empty($_POST['file']) ? empty($_POST['cat']) ? '' : $_POST['cat'] : $_POST['file'], array('&' => '&')); $profile_vars['avatar'] = preg_match('~^([\\w _!@%*=\\-#()\\[\\]&.,]+/)?[\\w _!@%*=\\-#()\\[\\]&.,]+$~', $profile_vars['avatar']) != 0 && preg_match('/\\.\\./', $profile_vars['avatar']) == 0 && file_exists($modSettings['avatar_directory'] . '/' . $profile_vars['avatar']) ? $profile_vars['avatar'] == 'blank.gif' ? '' : $profile_vars['avatar'] : ''; // Clear current profile... $cur_profile['id_attach'] = 0; $cur_profile['attachment_type'] = 0; $cur_profile['filename'] = ''; // Get rid of their old avatar. (if uploaded.) removeAttachments(array('id_member' => $memID)); } elseif ($value == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && empty($modSettings['avatar_download_external'])) { // We need these clean... $cur_profile['id_attach'] = 0; $cur_profile['attachment_type'] = 0; $cur_profile['filename'] = ''; // Remove any attached avatar... removeAttachments(array('id_member' => $memID)); $profile_vars['avatar'] = str_replace('%20', '', preg_replace('~action(?:=|%3d)(?!dlattach)~i', 'action-', $_POST['userpicpersonal'])); if ($profile_vars['avatar'] == 'http://' || $profile_vars['avatar'] == 'http:///') { $profile_vars['avatar'] = ''; } elseif (substr($profile_vars['avatar'], 0, 7) != 'http://') { return 'bad_avatar'; } elseif (!empty($modSettings['avatar_max_height_external']) || !empty($modSettings['avatar_max_width_external'])) { // Now let's validate the avatar. $sizes = url_image_size($profile_vars['avatar']); if (is_array($sizes) && ($sizes[0] > $modSettings['avatar_max_width_external'] && !empty($modSettings['avatar_max_width_external']) || $sizes[1] > $modSettings['avatar_max_height_external'] && !empty($modSettings['avatar_max_height_external']))) { // Houston, we have a problem. The avatar is too large!! if ($modSettings['avatar_action_too_large'] == 'option_refuse') { return 'bad_avatar'; } elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize') { require_once $sourcedir . '/Subs-Graphics.php'; if (downloadAvatar($profile_vars['avatar'], $memID, $modSettings['avatar_max_width_external'], $modSettings['avatar_max_height_external'])) { $profile_vars['avatar'] = ''; $cur_profile['id_attach'] = $modSettings['new_avatar_data']['id']; $cur_profile['filename'] = $modSettings['new_avatar_data']['filename']; $cur_profile['attachment_type'] = $modSettings['new_avatar_data']['type']; } else { return 'bad_avatar'; } } } } } elseif ($value == 'upload' && allowedTo('profile_upload_avatar') || $downloadedExternalAvatar) { if (isset($_FILES['attachment']['name']) && $_FILES['attachment']['name'] != '' || $downloadedExternalAvatar) { // Get the dimensions of the image. if (!$downloadedExternalAvatar) { if (!is_writable($uploadDir)) { fatal_lang_error('attachments_no_write', 'critical'); } if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadDir . '/avatar_tmp_' . $memID)) { fatal_lang_error('attach_timeout', 'critical'); } $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID; } $sizes = @getimagesize($_FILES['attachment']['tmp_name']); // No size, then it's probably not a valid pic. if ($sizes === false) { return 'bad_avatar'; } elseif (!empty($modSettings['avatar_max_width_upload']) && $sizes[0] > $modSettings['avatar_max_width_upload'] || !empty($modSettings['avatar_max_height_upload']) && $sizes[1] > $modSettings['avatar_max_height_upload']) { if (!empty($modSettings['avatar_resize_upload'])) { // Attempt to chmod it. @chmod($uploadDir . '/avatar_tmp_' . $memID, 0644); require_once $sourcedir . '/Subs-Graphics.php'; if (!downloadAvatar($uploadDir . '/avatar_tmp_' . $memID, $memID, $modSettings['avatar_max_width_upload'], $modSettings['avatar_max_height_upload'])) { return 'bad_avatar'; } // Reset attachment avatar data. $cur_profile['id_attach'] = $modSettings['new_avatar_data']['id']; $cur_profile['filename'] = $modSettings['new_avatar_data']['filename']; $cur_profile['attachment_type'] = $modSettings['new_avatar_data']['type']; } else { return 'bad_avatar'; } } elseif (is_array($sizes)) { // Now try to find an infection. require_once $sourcedir . '/Subs-Graphics.php'; if (!checkImageContents($_FILES['attachment']['tmp_name'], !empty($modSettings['avatar_paranoid']))) { // It's bad. Try to re-encode the contents? if (empty($modSettings['avatar_reencode']) || !reencodeImage($_FILES['attachment']['tmp_name'], $sizes[2])) { return 'bad_avatar'; } // We were successful. However, at what price? $sizes = @getimagesize($_FILES['attachment']['tmp_name']); // Hard to believe this would happen, but can you bet? if ($sizes === false) { return 'bad_avatar'; } } $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png', '6' => 'bmp'); $extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : 'bmp'; $mime_type = 'image/' . ($extension === 'jpg' ? 'jpeg' : ($extension === 'bmp' ? 'x-ms-bmp' : $extension)); $destName = 'avatar_' . $memID . '_' . time() . '.' . $extension; list($width, $height) = getimagesize($_FILES['attachment']['tmp_name']); $file_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, null, true) : ''; // Remove previous attachments this member might have had. removeAttachments(array('id_member' => $memID)); $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_member' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'fileext' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string', 'id_folder' => 'int'), array($memID, empty($modSettings['custom_avatar_enabled']) ? 0 : 1, $destName, $file_hash, $extension, filesize($_FILES['attachment']['tmp_name']), (int) $width, (int) $height, $mime_type, $id_folder), array('id_attach')); $cur_profile['id_attach'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach'); $cur_profile['filename'] = $destName; $cur_profile['attachment_type'] = empty($modSettings['custom_avatar_enabled']) ? 0 : 1; $destinationPath = $uploadDir . '/' . (empty($file_hash) ? $destName : $cur_profile['id_attach'] . '_' . $file_hash); if (!rename($_FILES['attachment']['tmp_name'], $destinationPath)) { // I guess a man can try. removeAttachments(array('id_member' => $memID)); fatal_lang_error('attach_timeout', 'critical'); } // Attempt to chmod it. @chmod($uploadDir . '/' . $destinationPath, 0644); } $profile_vars['avatar'] = ''; // Delete any temporary file. if (file_exists($uploadDir . '/avatar_tmp_' . $memID)) { @unlink($uploadDir . '/avatar_tmp_' . $memID); } } else { $profile_vars['avatar'] = ''; } } else { $profile_vars['avatar'] = ''; } // Setup the profile variables so it shows things right on display! $cur_profile['avatar'] = $profile_vars['avatar']; return false; }
function createAttachment(&$attachmentOptions) { global $modSettings, $sourcedir, $backend_subdir; require_once $sourcedir . '/lib/Subs-Graphics.php'; // We need to know where this thing is going. if (!empty($modSettings['currentAttachmentUploadDir'])) { if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // Just use the current path for temp files. $attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; $id_folder = $modSettings['currentAttachmentUploadDir']; } else { $attach_dir = $modSettings['attachmentUploadDir']; $id_folder = 1; } $attachmentOptions['errors'] = array(); if (!isset($attachmentOptions['post'])) { $attachmentOptions['post'] = 0; } if (!isset($attachmentOptions['approved'])) { $attachmentOptions['approved'] = 1; } $already_uploaded = preg_match('~^post_tmp_' . $attachmentOptions['poster'] . '_\\d+$~', $attachmentOptions['tmp_name']) != 0; $file_restricted = @ini_get('open_basedir') != '' && !$already_uploaded; if ($already_uploaded) { $attachmentOptions['tmp_name'] = $attach_dir . '/' . $attachmentOptions['tmp_name']; } // Make sure the file actually exists... sometimes it doesn't. if (!$file_restricted && !file_exists($attachmentOptions['tmp_name']) || !$already_uploaded && !is_uploaded_file($attachmentOptions['tmp_name'])) { $attachmentOptions['errors'] = array('could_not_upload'); return false; } // These are the only valid image types for SMF. $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff'); if (!$file_restricted || $already_uploaded) { $size = @getimagesize($attachmentOptions['tmp_name']); list($attachmentOptions['width'], $attachmentOptions['height']) = $size; // If it's an image get the mime type right. if (empty($attachmentOptions['mime_type']) && $attachmentOptions['width']) { // Got a proper mime type? if (!empty($size['mime'])) { $attachmentOptions['mime_type'] = $size['mime']; } elseif (isset($validImageTypes[$size[2]])) { $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]]; } } } // Get the hash if no hash has been given yet. if (empty($attachmentOptions['file_hash'])) { $attachmentOptions['file_hash'] = getAttachmentFilename($attachmentOptions['name'], false, null, true); } // Is the file too big? if (!empty($modSettings['attachmentSizeLimit']) && $attachmentOptions['size'] > $modSettings['attachmentSizeLimit'] * 1024) { $attachmentOptions['errors'][] = 'too_large'; } if (!empty($modSettings['attachmentCheckExtensions'])) { $allowed = explode(',', strtolower($modSettings['attachmentExtensions'])); foreach ($allowed as $k => $dummy) { $allowed[$k] = trim($dummy); } if (!in_array(strtolower(substr(strrchr($attachmentOptions['name'], '.'), 1)), $allowed)) { $attachmentOptions['errors'][] = 'bad_extension'; } } if (!empty($modSettings['attachmentDirSizeLimit'])) { // This is a really expensive operation for big numbers of // attachments, which is also very easy to cache. Only do it // every ten minutes. if (empty($modSettings['attachment_dirsize']) || empty($modSettings['attachment_dirsize_time']) || $modSettings['attachment_dirsize_time'] < time() - 600) { // It has been cached - just work with this value for now! $dirSize = $modSettings['attachment_dirsize']; } else { // Make sure the directory isn't full. $dirSize = 0; $dir = @opendir($attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical'); while ($file = readdir($dir)) { if ($file == '.' || $file == '..') { continue; } if (preg_match('~^post_tmp_\\d+_\\d+$~', $file) != 0) { // Temp file is more than 5 hours old! if (filemtime($attach_dir . '/' . $file) < time() - 18000) { @unlink($attach_dir . '/' . $file); } continue; } $dirSize += filesize($attach_dir . '/' . $file); } closedir($dir); updateSettings(array('attachment_dirsize' => $dirSize, 'attachment_dirsize_time' => time())); } // Too big! Maybe you could zip it or something... if ($attachmentOptions['size'] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024) { $attachmentOptions['errors'][] = 'directory_full'; } elseif (!isset($modSettings['attachment_full_notified']) && $modSettings['attachmentDirSizeLimit'] > 4000 && $attachmentOptions['size'] + $dirSize > ($modSettings['attachmentDirSizeLimit'] - 2000) * 1024) { require_once $sourcedir . '/lib/Subs-Admin.php'; emailAdmins('admin_attachments_full'); updateSettings(array('attachment_full_notified' => 1)); } } // Check if the file already exists.... (for those who do not encrypt their filenames...) if (empty($modSettings['attachmentEncryptFilenames'])) { // Make sure they aren't trying to upload a nasty file. $disabledFiles = array('con', 'com1', 'com2', 'com3', 'com4', 'prn', 'aux', 'lpt1', '.htaccess', 'index.php'); if (in_array(strtolower(basename($attachmentOptions['name'])), $disabledFiles)) { $attachmentOptions['errors'][] = 'bad_filename'; } // Check if there's another file with that name... $request = smf_db_query(' SELECT id_attach FROM {db_prefix}attachments WHERE filename = {string:filename} LIMIT 1', array('filename' => strtolower($attachmentOptions['name']))); if (mysql_num_rows($request) > 0) { $attachmentOptions['errors'][] = 'taken_filename'; } mysql_free_result($request); } if (!empty($attachmentOptions['errors'])) { return false; } if (!is_writable($attach_dir)) { fatal_lang_error('attachments_no_write', 'critical'); } // Assuming no-one set the extension let's take a look at it. if (empty($attachmentOptions['fileext'])) { $attachmentOptions['fileext'] = strtolower(strrpos($attachmentOptions['name'], '.') !== false ? substr($attachmentOptions['name'], strrpos($attachmentOptions['name'], '.') + 1) : ''); if (strlen($attachmentOptions['fileext']) > 8 || '.' . $attachmentOptions['fileext'] == $attachmentOptions['name']) { $attachmentOptions['fileext'] = ''; } } smf_db_insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int'), array($id_folder, (int) $attachmentOptions['post'], $attachmentOptions['name'], $attachmentOptions['file_hash'], $attachmentOptions['fileext'], (int) $attachmentOptions['size'], empty($attachmentOptions['width']) ? 0 : (int) $attachmentOptions['width'], empty($attachmentOptions['height']) ? '0' : (int) $attachmentOptions['height'], !empty($attachmentOptions['mime_type']) ? $attachmentOptions['mime_type'] : '', (int) $attachmentOptions['approved']), array('id_attach')); $attachmentOptions['id'] = smf_db_insert_id('{db_prefix}attachments', 'id_attach'); if (empty($attachmentOptions['id'])) { return false; } // If it's not approved add to the approval queue. if (!$attachmentOptions['approved']) { smf_db_insert('', '{db_prefix}approval_queue', array('id_attach' => 'int', 'id_msg' => 'int'), array($attachmentOptions['id'], (int) $attachmentOptions['post']), array()); } $attachmentOptions['destination'] = getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], $id_folder, false, $attachmentOptions['file_hash']); if ($already_uploaded) { rename($attachmentOptions['tmp_name'], $attachmentOptions['destination']); } elseif (!move_uploaded_file($attachmentOptions['tmp_name'], $attachmentOptions['destination'])) { fatal_lang_error('attach_timeout', 'critical'); } // Udate the cached directory size, if we care for it. if (!empty($modSettings['attachmentDirSizeLimit'])) { updateSettings(array('attachment_dirsize' => $modSettings['attachment_dirsize'] + $attachmentOptions['size'], 'attachment_dirsize_time' => time())); } // Attempt to chmod it. @chmod($attachmentOptions['destination'], 0644); $size = @getimagesize($attachmentOptions['destination']); list($attachmentOptions['width'], $attachmentOptions['height']) = empty($size) ? array(null, null, null) : $size; // We couldn't access the file before... if ($file_restricted) { // Have a go at getting the right mime type. if (empty($attachmentOptions['mime_type']) && $attachmentOptions['width']) { if (!empty($size['mime'])) { $attachmentOptions['mime_type'] = $size['mime']; } elseif (isset($validImageTypes[$size[2]])) { $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]]; } } if (!empty($attachmentOptions['width']) && !empty($attachmentOptions['height'])) { smf_db_query(' UPDATE {db_prefix}attachments SET width = {int:width}, height = {int:height}, mime_type = {string:mime_type} WHERE id_attach = {int:id_attach}', array('width' => (int) $attachmentOptions['width'], 'height' => (int) $attachmentOptions['height'], 'id_attach' => $attachmentOptions['id'], 'mime_type' => empty($attachmentOptions['mime_type']) ? '' : $attachmentOptions['mime_type'])); } } // Security checks for images // Do we have an image? If yes, we need to check it out! if (isset($validImageTypes[$size[2]])) { if (!checkImageContents($attachmentOptions['destination'], !empty($modSettings['attachment_image_paranoid']))) { // It's bad. Last chance, maybe we can re-encode it? if (empty($modSettings['attachment_image_reencode']) || !reencodeImage($attachmentOptions['destination'], $size[2])) { // Nothing to do: not allowed or not successful re-encoding it. require_once $sourcedir . '/lib/Subs-ManageAttachments.php'; removeAttachments(array('id_attach' => $attachmentOptions['id'])); $attachmentOptions['id'] = null; $attachmentOptions['errors'][] = 'bad_attachment'; return false; } // Success! However, successes usually come for a price: // we might get a new format for our image... $old_format = $size[2]; $size = @getimagesize($attachmentOptions['destination']); if (!empty($size) && $size[2] != $old_format) { // Let's update the image information // !!! This is becoming a mess: we keep coming back and update the database, // instead of getting it right the first time. if (isset($validImageTypes[$size[2]])) { $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]]; smf_db_query(' UPDATE {db_prefix}attachments SET mime_type = {string:mime_type} WHERE id_attach = {int:id_attach}', array('id_attach' => $attachmentOptions['id'], 'mime_type' => $attachmentOptions['mime_type'])); } } } } if (!empty($attachmentOptions['skip_thumbnail']) || empty($attachmentOptions['width']) && empty($attachmentOptions['height'])) { return true; } // Like thumbnails, do we? if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachmentOptions['width'] > $modSettings['attachmentThumbWidth'] || $attachmentOptions['height'] > $modSettings['attachmentThumbHeight'])) { if (createThumbnail($attachmentOptions['destination'], $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) { // Figure out how big we actually made it. $size = @getimagesize($attachmentOptions['destination'] . '_thumb'); list($thumb_width, $thumb_height) = $size; if (!empty($size['mime'])) { $thumb_mime = $size['mime']; } elseif (isset($validImageTypes[$size[2]])) { $thumb_mime = 'image/' . $validImageTypes[$size[2]]; } else { $thumb_mime = ''; } $thumb_filename = $attachmentOptions['name'] . '_thumb'; $thumb_size = filesize($attachmentOptions['destination'] . '_thumb'); $thumb_file_hash = getAttachmentFilename($thumb_filename, false, null, true); // To the database we go! smf_db_insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int'), array($id_folder, (int) $attachmentOptions['post'], 3, $thumb_filename, $thumb_file_hash, $attachmentOptions['fileext'], $thumb_size, $thumb_width, $thumb_height, $thumb_mime, (int) $attachmentOptions['approved']), array('id_attach')); $attachmentOptions['thumb'] = smf_db_insert_id('{db_prefix}attachments', 'id_attach'); if (!empty($attachmentOptions['thumb'])) { smf_db_query(' UPDATE {db_prefix}attachments SET id_thumb = {int:id_thumb} WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachmentOptions['thumb'], 'id_attach' => $attachmentOptions['id'])); rename($attachmentOptions['destination'] . '_thumb', getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], $id_folder, false, $thumb_file_hash)); } } } return true; }
/** * Performs various checks on an uploaded file. * * What it does: * - Requires that $_SESSION['temp_attachments'][$attachID] be properly populated. * * @package Attachments * @param int $attachID id of the attachment to check */ function attachmentChecks($attachID) { global $modSettings, $context, $attachmentOptions; $db = database(); // No data or missing data .... Not necessarily needed, but in case a mod author missed something. if (empty($_SESSION['temp_attachments'][$attachID])) { $error = '$_SESSION[\'temp_attachments\'][$attachID]'; } elseif (empty($attachID)) { $error = '$attachID'; } elseif (empty($context['attachments'])) { $error = '$context[\'attachments\']'; } elseif (empty($context['attach_dir'])) { $error = '$context[\'attach_dir\']'; } // Let's get their attention. if (!empty($error)) { fatal_lang_error('attach_check_nag', 'debug', array($error)); } // These are the only valid image types. $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff'); // Just in case this slipped by the first checks, we stop it here and now if ($_SESSION['temp_attachments'][$attachID]['size'] == 0) { $_SESSION['temp_attachments'][$attachID]['errors'][] = 'attach_0_byte_file'; return false; } // First, the dreaded security check. Sorry folks, but this should't be avoided $size = @getimagesize($_SESSION['temp_attachments'][$attachID]['tmp_name']); if (isset($validImageTypes[$size[2]])) { require_once SUBSDIR . '/Graphics.subs.php'; if (!checkImageContents($_SESSION['temp_attachments'][$attachID]['tmp_name'], !empty($modSettings['attachment_image_paranoid']))) { // It's bad. Last chance, maybe we can re-encode it? if (empty($modSettings['attachment_image_reencode']) || !reencodeImage($_SESSION['temp_attachments'][$attachID]['tmp_name'], $size[2])) { // Nothing to do: not allowed or not successful re-encoding it. $_SESSION['temp_attachments'][$attachID]['errors'][] = 'bad_attachment'; return false; } // Success! However, successes usually come for a price: // we might get a new format for our image... $old_format = $size[2]; $size = @getimagesize($attachmentOptions['tmp_name']); if (!empty($size) && $size[2] != $old_format) { if (isset($validImageTypes[$size[2]])) { $_SESSION['temp_attachments'][$attachID]['type'] = 'image/' . $validImageTypes[$size[2]]; } } } } // Is there room for this in the directory? if (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit'])) { // Check the folder size and count. If it hasn't been done already. if (empty($context['dir_size']) || empty($context['dir_files'])) { $request = $db->query('', ' SELECT COUNT(*), SUM(size) FROM {db_prefix}attachments WHERE id_folder = {int:folder_id} AND attachment_type != {int:type}', array('folder_id' => $modSettings['currentAttachmentUploadDir'], 'type' => 1)); list($context['dir_files'], $context['dir_size']) = $db->fetch_row($request); $db->free_result($request); } $context['dir_size'] += $_SESSION['temp_attachments'][$attachID]['size']; $context['dir_files']++; // Are we about to run out of room? Let's notify the admin then. if (empty($modSettings['attachment_full_notified']) && !empty($modSettings['attachmentDirSizeLimit']) && $modSettings['attachmentDirSizeLimit'] > 4000 && $context['dir_size'] > ($modSettings['attachmentDirSizeLimit'] - 2000) * 1024 || !empty($modSettings['attachmentDirFileLimit']) && $modSettings['attachmentDirFileLimit'] * 0.95 < $context['dir_files'] && $modSettings['attachmentDirFileLimit'] > 500) { require_once SUBSDIR . '/Admin.subs.php'; emailAdmins('admin_attachments_full'); updateSettings(array('attachment_full_notified' => 1)); } // No room left.... What to do now??? if (!empty($modSettings['attachmentDirFileLimit']) && $context['dir_files'] + 2 > $modSettings['attachmentDirFileLimit'] || !empty($modSettings['attachmentDirSizeLimit']) && $context['dir_size'] > $modSettings['attachmentDirSizeLimit'] * 1024) { // If we are managing the directories space automatically, lets get to it if (!empty($modSettings['automanage_attachments']) && $modSettings['automanage_attachments'] == 1) { // Move it to the new folder if we can. if (automanage_attachments_by_space()) { rename($_SESSION['temp_attachments'][$attachID]['tmp_name'], $context['attach_dir'] . '/' . $attachID); $_SESSION['temp_attachments'][$attachID]['tmp_name'] = $context['attach_dir'] . '/' . $attachID; $_SESSION['temp_attachments'][$attachID]['id_folder'] = $modSettings['currentAttachmentUploadDir']; $context['dir_size'] = 0; $context['dir_files'] = 0; } else { if (isset($context['dir_creation_error'])) { $_SESSION['temp_attachments'][$attachID]['errors'][] = $context['dir_creation_error']; } else { $_SESSION['temp_attachments'][$attachID]['errors'][] = 'ran_out_of_space'; } } } else { $_SESSION['temp_attachments'][$attachID]['errors'][] = 'ran_out_of_space'; } } } // Is the file too big? if (!empty($modSettings['attachmentSizeLimit']) && $_SESSION['temp_attachments'][$attachID]['size'] > $modSettings['attachmentSizeLimit'] * 1024) { $_SESSION['temp_attachments'][$attachID]['errors'][] = array('file_too_big', array(comma_format($modSettings['attachmentSizeLimit'], 0))); } // Check the total upload size for this post... $context['attachments']['total_size'] += $_SESSION['temp_attachments'][$attachID]['size']; if (!empty($modSettings['attachmentPostLimit']) && $context['attachments']['total_size'] > $modSettings['attachmentPostLimit'] * 1024) { $_SESSION['temp_attachments'][$attachID]['errors'][] = array('attach_max_total_file_size', array(comma_format($modSettings['attachmentPostLimit'], 0), comma_format($modSettings['attachmentPostLimit'] - ($context['attachments']['total_size'] - $_SESSION['temp_attachments'][$attachID]['size']) / 1024, 0))); } // Have we reached the maximum number of files we are allowed? $context['attachments']['quantity']++; // Set a max limit if none exists if (empty($modSettings['attachmentNumPerPostLimit']) && $context['attachments']['quantity'] >= 50) { $modSettings['attachmentNumPerPostLimit'] = 50; } if (!empty($modSettings['attachmentNumPerPostLimit']) && $context['attachments']['quantity'] > $modSettings['attachmentNumPerPostLimit']) { $_SESSION['temp_attachments'][$attachID]['errors'][] = array('attachments_limit_per_post', array($modSettings['attachmentNumPerPostLimit'])); } // File extension check if (!empty($modSettings['attachmentCheckExtensions'])) { $allowed = explode(',', strtolower($modSettings['attachmentExtensions'])); foreach ($allowed as $k => $dummy) { $allowed[$k] = trim($dummy); } if (!in_array(strtolower(substr(strrchr($_SESSION['temp_attachments'][$attachID]['name'], '.'), 1)), $allowed)) { $allowed_extensions = strtr(strtolower($modSettings['attachmentExtensions']), array(',' => ', ')); $_SESSION['temp_attachments'][$attachID]['errors'][] = array('cant_upload_type', array($allowed_extensions)); } } // Undo the math if there's an error if (!empty($_SESSION['temp_attachments'][$attachID]['errors'])) { if (isset($context['dir_size'])) { $context['dir_size'] -= $_SESSION['temp_attachments'][$attachID]['size']; } if (isset($context['dir_files'])) { $context['dir_files']--; } $context['attachments']['total_size'] -= $_SESSION['temp_attachments'][$attachID]['size']; $context['attachments']['quantity']--; return false; } return true; }