Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
/**
 * 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;
}