Example #1
0
/**
 * downloads a file from a url and stores it locally for avatar use by id_member.
 * - supports GIF, JPG, PNG, BMP and WBMP formats.
 * - detects if GD2 is available.
 * - uses resizeImageFile() to resize to max_width by max_height, and saves the result to a file.
 * - updates the database info for the member's avatar.
 * - returns whether the download and resize was successful.
 *
 * @param string $temporary_path, the full path to the temporary file
 * @param int $memID, member ID
 * @param int $max_width
 * @param int $max_height
 * @return bool, whether the download and resize was successful.
 *
 */
function downloadAvatar($url, $memID, $max_width, $max_height)
{
    global $modSettings, $sourcedir, $smcFunc;
    $ext = !empty($modSettings['avatar_download_png']) ? 'png' : 'jpeg';
    $destName = 'avatar_' . $memID . '_' . time() . '.' . $ext;
    // Just making sure there is a non-zero member.
    if (empty($memID)) {
        return false;
    }
    require_once $sourcedir . '/ManageAttachments.php';
    removeAttachments(array('id_member' => $memID));
    $id_folder = !empty($modSettings['currentAttachmentUploadDir']) ? $modSettings['currentAttachmentUploadDir'] : 1;
    $avatar_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, null, true) : '';
    $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_member' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-255', 'fileext' => 'string-8', 'size' => 'int', 'id_folder' => 'int'), array($memID, empty($modSettings['custom_avatar_enabled']) ? 0 : 1, $destName, $avatar_hash, $ext, 1, $id_folder), array('id_attach'));
    $attachID = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
    // Retain this globally in case the script wants it.
    $modSettings['new_avatar_data'] = array('id' => $attachID, 'filename' => $destName, 'type' => empty($modSettings['custom_avatar_enabled']) ? 0 : 1);
    $destName = (empty($modSettings['custom_avatar_enabled']) ? is_array($modSettings['attachmentUploadDir']) ? $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']] : $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir']) . '/' . $destName . '.tmp';
    // Resize it.
    if (!empty($modSettings['avatar_download_png'])) {
        $success = resizeImageFile($url, $destName, $max_width, $max_height, 3);
    } else {
        $success = resizeImageFile($url, $destName, $max_width, $max_height);
    }
    // Remove the .tmp extension.
    $destName = substr($destName, 0, -4);
    if ($success) {
        // Walk the right path.
        if (!empty($modSettings['currentAttachmentUploadDir'])) {
            if (!is_array($modSettings['attachmentUploadDir'])) {
                $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
            }
            $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
        } else {
            $path = $modSettings['attachmentUploadDir'];
        }
        // Remove the .tmp extension from the attachment.
        if (rename($destName . '.tmp', empty($avatar_hash) ? $destName : $path . '/' . $attachID . '_' . $avatar_hash)) {
            $destName = empty($avatar_hash) ? $destName : $path . '/' . $attachID . '_' . $avatar_hash;
            list($width, $height) = getimagesize($destName);
            $mime_type = 'image/' . $ext;
            // Write filesize in the database.
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}attachments
				SET size = {int:filesize}, width = {int:width}, height = {int:height},
					mime_type = {string:mime_type}
				WHERE id_attach = {int:current_attachment}', array('filesize' => filesize($destName), 'width' => (int) $width, 'height' => (int) $height, 'current_attachment' => $attachID, 'mime_type' => $mime_type));
            return true;
        } else {
            return false;
        }
    } else {
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}attachments
			WHERE id_attach = {int:current_attachment}', array('current_attachment' => $attachID));
        @unlink($destName . '.tmp');
        return false;
    }
}
Example #2
0
function RepairAttachments()
{
    global $db_prefix, $modSettings, $context, $txt;
    $context['page_title'] = $txt['repair_attachments'];
    $context['description'] = $txt['smf202'];
    $context['selected'] = 'maintenance';
    $context['sub_template'] = 'attachment_repair';
    checkSession('get');
    // If we choose cancel, redirect right back.
    if (isset($_POST['cancel'])) {
        redirectexit('action=manageattachments;sa=maintenance');
    }
    // Try give us a while to sort this out...
    @set_time_limit(600);
    $_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step'];
    $_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep'];
    // Don't recall the session just incase.
    if ($_GET['step'] == 0 && $_GET['substep'] == 0) {
        unset($_SESSION['attachments_to_fix']);
        unset($_SESSION['attachments_to_fix2']);
        // If we're actually fixing stuff - work out what.
        if (isset($_GET['fixErrors'])) {
            // Nothing?
            if (empty($_POST['to_fix'])) {
                redirectexit('action=manageattachments;sa=maintenance');
            }
            $_SESSION['attachments_to_fix'] = array();
            //!!! No need to do this I think.
            foreach ($_POST['to_fix'] as $key => $value) {
                $_SESSION['attachments_to_fix'][] = $value;
            }
        }
    }
    $to_fix = !empty($_SESSION['attachments_to_fix']) ? $_SESSION['attachments_to_fix'] : array();
    $context['repair_errors'] = isset($_SESSION['attachments_to_fix2']) ? $_SESSION['attachments_to_fix2'] : array();
    $fix_errors = isset($_GET['fixErrors']) ? true : false;
    // All the valid problems are here:
    $context['repair_errors'] = array('missing_thumbnail_parent' => 0, 'parent_missing_thumbnail' => 0, 'file_missing_on_disk' => 0, 'file_wrong_size' => 0, 'file_size_of_zero' => 0, 'attachment_no_msg' => 0, 'avatar_no_member' => 0);
    // Get stranded thumbnails.
    if ($_GET['step'] <= 0) {
        $result = db_query("\n\t\t\tSELECT MAX(ID_ATTACH)\n\t\t\tFROM {$db_prefix}attachments\n\t\t\tWHERE attachmentType = 3", __FILE__, __LINE__);
        list($thumbnails) = mysql_fetch_row($result);
        mysql_free_result($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_remove = array();
            $result = db_query("\n\t\t\t\tSELECT thumb.ID_ATTACH, thumb.filename, thumb.file_hash\n\t\t\t\tFROM {$db_prefix}attachments AS thumb\n\t\t\t\t\tLEFT JOIN {$db_prefix}attachments AS tparent ON (tparent.ID_THUMB = thumb.ID_ATTACH)\n\t\t\t\tWHERE thumb.ID_ATTACH BETWEEN {$_GET['substep']} AND {$_GET['substep']} + 499\n\t\t\t\t\tAND thumb.attachmentType = 3\n\t\t\t\t\tAND tparent.ID_ATTACH IS NULL\n\t\t\t\tGROUP BY thumb.ID_ATTACH", __FILE__, __LINE__);
            while ($row = mysql_fetch_assoc($result)) {
                $to_remove[] = $row['ID_ATTACH'];
                $context['repair_errors']['missing_thumbnail_parent']++;
                // If we are repairing remove the file from disk now.
                if ($fix_errors && in_array('missing_thumbnail_parent', $to_fix)) {
                    $filename = getAttachmentFilename($row['filename'], $row['ID_ATTACH'], false, $row['file_hash']);
                    @unlink($filename);
                }
            }
            if (mysql_num_rows($result) != 0) {
                $to_fix[] = 'missing_thumbnail_parent';
            }
            mysql_free_result($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove) && in_array('missing_thumbnail_parent', $to_fix)) {
                db_query("\n\t\t\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\t\t\tWHERE ID_ATTACH IN (" . implode(', ', $to_remove) . ")\n\t\t\t\t\t\tAND attachmentType = 3", __FILE__, __LINE__);
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 1;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // Find parents which think they have thumbnails, but actually, don't.
    if ($_GET['step'] <= 1) {
        $result = db_query("\n\t\t\tSELECT MAX(ID_ATTACH)\n\t\t\tFROM {$db_prefix}attachments\n\t\t\tWHERE ID_THUMB != 0", __FILE__, __LINE__);
        list($thumbnails) = mysql_fetch_row($result);
        mysql_free_result($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_update = array();
            $result = db_query("\n\t\t\t\tSELECT a.ID_ATTACH\n\t\t\t\tFROM {$db_prefix}attachments AS a\n\t\t\t\t\tLEFT JOIN {$db_prefix}attachments AS thumb ON (thumb.ID_ATTACH = a.ID_THUMB)\n\t\t\t\tWHERE a.ID_ATTACH BETWEEN {$_GET['substep']} AND {$_GET['substep']} + 499\n\t\t\t\t\tAND a.ID_THUMB != 0\n\t\t\t\t\tAND thumb.ID_ATTACH IS NULL", __FILE__, __LINE__);
            while ($row = mysql_fetch_assoc($result)) {
                $to_update[] = $row['ID_ATTACH'];
                $context['repair_errors']['parent_missing_thumbnail']++;
            }
            if (mysql_num_rows($result) != 0) {
                $to_fix[] = 'parent_missing_thumbnail';
            }
            mysql_free_result($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_update) && in_array('parent_missing_thumbnail', $to_fix)) {
                db_query("\n\t\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\t\tSET ID_THUMB = 0\n\t\t\t\t\tWHERE ID_ATTACH IN (" . implode(', ', $to_update) . ")", __FILE__, __LINE__);
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 2;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // This may take forever I'm afraid, but life sucks... recount EVERY attachments!
    if ($_GET['step'] <= 2) {
        $result = db_query("\n\t\t\tSELECT MAX(ID_ATTACH)\n\t\t\tFROM {$db_prefix}attachments", __FILE__, __LINE__);
        list($thumbnails) = mysql_fetch_row($result);
        mysql_free_result($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 250) {
            $to_remove = array();
            $errors_found = array();
            $result = db_query("\n\t\t\t\tSELECT ID_ATTACH, filename, file_hash, size, attachmentType\n\t\t\t\tFROM {$db_prefix}attachments\n\t\t\t\tWHERE ID_ATTACH BETWEEN {$_GET['substep']} AND {$_GET['substep']} + 249", __FILE__, __LINE__);
            while ($row = mysql_fetch_assoc($result)) {
                // Get the filename.
                if ($row['attachmentType'] == 1) {
                    $filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename'];
                } else {
                    $filename = getAttachmentFilename($row['filename'], $row['ID_ATTACH'], false, $row['file_hash']);
                }
                // File doesn't exist?
                if (!file_exists($filename)) {
                    $to_remove[] = $row['ID_ATTACH'];
                    $context['repair_errors']['file_missing_on_disk']++;
                    $errors_found[] = 'file_missing_on_disk';
                    // Are we fixing this?
                    if ($fix_errors && in_array('file_missing_on_disk', $to_fix)) {
                        $to_remove[] = $row['ID_ATTACH'];
                    }
                } elseif (filesize($filename) == 0) {
                    $context['repair_errors']['file_size_of_zero']++;
                    $errors_found[] = 'file_size_of_zero';
                    // Fixing?
                    if ($fix_errors && in_array('file_size_of_zero', $to_fix)) {
                        $to_remove[] = $row['ID_ATTACH'];
                        @unlink($filename);
                    }
                } elseif (filesize($filename) != $row['size']) {
                    $context['repair_errors']['file_wrong_size']++;
                    $errors_found[] = 'file_wrong_size';
                    // Fix it here?
                    if ($fix_errors && in_array('file_wrong_size', $to_fix)) {
                        db_query("\n\t\t\t\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\t\t\t\tSET size = " . filesize($filename) . "\n\t\t\t\t\t\t\tWHERE ID_ATTACH = {$row['ID_ATTACH']}\n\t\t\t\t\t\t\tLIMIT 1", __FILE__, __LINE__);
                    }
                }
            }
            if (in_array('file_missing_on_disk', $errors_found)) {
                $to_fix[] = 'file_missing_on_disk';
            }
            if (in_array('file_size_of_zero', $errors_found)) {
                $to_fix[] = 'file_size_of_zero';
            }
            if (in_array('file_wrong_size', $errors_found)) {
                $to_fix[] = 'file_wrong_size';
            }
            mysql_free_result($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove)) {
                db_query("\n\t\t\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\t\t\tWHERE ID_ATTACH IN (" . implode(', ', $to_remove) . ")", __FILE__, __LINE__);
                db_query("\n\t\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\t\tSET ID_THUMB = 0\n\t\t\t\t\tWHERE ID_THUMB IN (" . implode(', ', $to_remove) . ")", __FILE__, __LINE__);
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 3;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // Get avatars with no members associated with them.
    if ($_GET['step'] <= 3) {
        $result = db_query("\n\t\t\tSELECT MAX(ID_ATTACH)\n\t\t\tFROM {$db_prefix}attachments", __FILE__, __LINE__);
        list($thumbnails) = mysql_fetch_row($result);
        mysql_free_result($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_remove = array();
            $result = db_query("\n\t\t\t\tSELECT a.ID_ATTACH, a.filename, a.file_hash, a.attachmentType\n\t\t\t\tFROM {$db_prefix}attachments AS a\n\t\t\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = a.ID_MEMBER)\n\t\t\t\tWHERE a.ID_ATTACH BETWEEN {$_GET['substep']} AND {$_GET['substep']} + 499\n\t\t\t\t\tAND a.ID_MEMBER != 0\n\t\t\t\t\tAND a.ID_MSG = 0\n\t\t\t\t\tAND mem.ID_MEMBER IS NULL", __FILE__, __LINE__);
            while ($row = mysql_fetch_assoc($result)) {
                $to_remove[] = $row['ID_ATTACH'];
                $context['repair_errors']['avatar_no_member']++;
                // If we are repairing remove the file from disk now.
                if ($fix_errors && in_array('avatar_no_member', $to_fix)) {
                    if ($row['attachmentType'] == 1) {
                        $filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename'];
                    } else {
                        $filename = getAttachmentFilename($row['filename'], $row['ID_ATTACH'], false, $row['file_hash']);
                    }
                    @unlink($filename);
                }
            }
            if (mysql_num_rows($result) != 0) {
                $to_fix[] = 'avatar_no_member';
            }
            mysql_free_result($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove) && in_array('avatar_no_member', $to_fix)) {
                db_query("\n\t\t\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\t\t\tWHERE ID_ATTACH IN (" . implode(', ', $to_remove) . ")\n\t\t\t\t\t\tAND ID_MEMBER != 0\n\t\t\t\t\t\tAND ID_MSG = 0", __FILE__, __LINE__);
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 4;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // What about attachments, who are missing a message :'(
    if ($_GET['step'] <= 4) {
        $result = db_query("\n\t\t\tSELECT MAX(ID_ATTACH)\n\t\t\tFROM {$db_prefix}attachments", __FILE__, __LINE__);
        list($thumbnails) = mysql_fetch_row($result);
        mysql_free_result($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_remove = array();
            $result = db_query("\n\t\t\t\tSELECT a.ID_ATTACH, a.filename, a.file_hash\n\t\t\t\tFROM {$db_prefix}attachments AS a\n\t\t\t\t\tLEFT JOIN {$db_prefix}messages AS m ON (m.ID_MSG = a.ID_MSG)\n\t\t\t\tWHERE a.ID_ATTACH BETWEEN {$_GET['substep']} AND {$_GET['substep']} + 499\n\t\t\t\t\tAND a.ID_MEMBER = 0\n\t\t\t\t\tAND a.ID_MSG != 0\n\t\t\t\t\tAND m.ID_MSG IS NULL", __FILE__, __LINE__);
            while ($row = mysql_fetch_assoc($result)) {
                $to_remove[] = $row['ID_ATTACH'];
                $context['repair_errors']['attachment_no_msg']++;
                // If we are repairing remove the file from disk now.
                if ($fix_errors && in_array('attachment_no_msg', $to_fix)) {
                    $filename = getAttachmentFilename($row['filename'], $row['ID_ATTACH'], false, $row['file_hash']);
                    @unlink($filename);
                }
            }
            if (mysql_num_rows($result) != 0) {
                $to_fix[] = 'attachment_no_msg';
            }
            mysql_free_result($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove) && in_array('attachment_no_msg', $to_fix)) {
                db_query("\n\t\t\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\t\t\tWHERE ID_ATTACH IN (" . implode(', ', $to_remove) . ")\n\t\t\t\t\t\tAND ID_MEMBER = 0\n\t\t\t\t\t\tAND ID_MSG != 0", __FILE__, __LINE__);
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 5;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // Got here we must be doing well :D
    $context['completed'] = $fix_errors ? true : false;
    $context['errors_found'] = !empty($to_fix) ? true : false;
}
function RepairAttachments()
{
    global $modSettings, $context, $txt, $smcFunc;
    checkSession('get');
    // If we choose cancel, redirect right back.
    if (isset($_POST['cancel'])) {
        redirectexit('action=admin;area=manageattachments;sa=maintenance');
    }
    // Try give us a while to sort this out...
    @set_time_limit(600);
    $_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step'];
    $_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep'];
    // Don't recall the session just in case.
    if ($_GET['step'] == 0 && $_GET['substep'] == 0) {
        unset($_SESSION['attachments_to_fix'], $_SESSION['attachments_to_fix2']);
        // If we're actually fixing stuff - work out what.
        if (isset($_GET['fixErrors'])) {
            // Nothing?
            if (empty($_POST['to_fix'])) {
                redirectexit('action=admin;area=manageattachments;sa=maintenance');
            }
            $_SESSION['attachments_to_fix'] = array();
            //!!! No need to do this I think.
            foreach ($_POST['to_fix'] as $key => $value) {
                $_SESSION['attachments_to_fix'][] = $value;
            }
        }
    }
    // All the valid problems are here:
    $context['repair_errors'] = array('missing_thumbnail_parent' => 0, 'parent_missing_thumbnail' => 0, 'file_missing_on_disk' => 0, 'file_wrong_size' => 0, 'file_size_of_zero' => 0, 'attachment_no_msg' => 0, 'avatar_no_member' => 0, 'wrong_folder' => 0);
    $to_fix = !empty($_SESSION['attachments_to_fix']) ? $_SESSION['attachments_to_fix'] : array();
    $context['repair_errors'] = isset($_SESSION['attachments_to_fix2']) ? $_SESSION['attachments_to_fix2'] : $context['repair_errors'];
    $fix_errors = isset($_GET['fixErrors']) ? true : false;
    // Get stranded thumbnails.
    if ($_GET['step'] <= 0) {
        $result = $smcFunc['db_query']('', '
			SELECT MAX(id_attach)
			FROM {db_prefix}attachments
			WHERE attachment_type = {int:thumbnail}', array('thumbnail' => 3));
        list($thumbnails) = $smcFunc['db_fetch_row']($result);
        $smcFunc['db_free_result']($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_remove = array();
            $result = $smcFunc['db_query']('', '
				SELECT thumb.id_attach, thumb.id_folder, thumb.filename, thumb.file_hash
				FROM {db_prefix}attachments AS thumb
					LEFT JOIN {db_prefix}attachments AS tparent ON (tparent.id_thumb = thumb.id_attach)
				WHERE thumb.id_attach BETWEEN {int:substep} AND {int:substep} + 499
					AND thumb.attachment_type = {int:thumbnail}
					AND tparent.id_attach IS NULL', array('thumbnail' => 3, 'substep' => $_GET['substep']));
            while ($row = $smcFunc['db_fetch_assoc']($result)) {
                // Only do anything once... just in case
                if (!isset($to_remove[$row['id_attach']])) {
                    $to_remove[$row['id_attach']] = $row['id_attach'];
                    $context['repair_errors']['missing_thumbnail_parent']++;
                    // If we are repairing remove the file from disk now.
                    if ($fix_errors && in_array('missing_thumbnail_parent', $to_fix)) {
                        $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
                        @unlink($filename);
                    }
                }
            }
            if ($smcFunc['db_num_rows']($result) != 0) {
                $to_fix[] = 'missing_thumbnail_parent';
            }
            $smcFunc['db_free_result']($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove) && in_array('missing_thumbnail_parent', $to_fix)) {
                $smcFunc['db_query']('', '
					DELETE FROM {db_prefix}attachments
					WHERE id_attach IN ({array_int:to_remove})
						AND attachment_type = {int:attachment_type}', array('to_remove' => $to_remove, 'attachment_type' => 3));
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 1;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // Find parents which think they have thumbnails, but actually, don't.
    if ($_GET['step'] <= 1) {
        $result = $smcFunc['db_query']('', '
			SELECT MAX(id_attach)
			FROM {db_prefix}attachments
			WHERE id_thumb != {int:no_thumb}', array('no_thumb' => 0));
        list($thumbnails) = $smcFunc['db_fetch_row']($result);
        $smcFunc['db_free_result']($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_update = array();
            $result = $smcFunc['db_query']('', '
				SELECT a.id_attach
				FROM {db_prefix}attachments AS a
					LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)
				WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499
					AND a.id_thumb != {int:no_thumb}
					AND thumb.id_attach IS NULL', array('no_thumb' => 0, 'substep' => $_GET['substep']));
            while ($row = $smcFunc['db_fetch_assoc']($result)) {
                $to_update[] = $row['id_attach'];
                $context['repair_errors']['parent_missing_thumbnail']++;
            }
            if ($smcFunc['db_num_rows']($result) != 0) {
                $to_fix[] = 'parent_missing_thumbnail';
            }
            $smcFunc['db_free_result']($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_update) && in_array('parent_missing_thumbnail', $to_fix)) {
                $smcFunc['db_query']('', '
					UPDATE {db_prefix}attachments
					SET id_thumb = {int:no_thumb}
					WHERE id_attach IN ({array_int:to_update})', array('to_update' => $to_update, 'no_thumb' => 0));
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 2;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // This may take forever I'm afraid, but life sucks... recount EVERY attachments!
    if ($_GET['step'] <= 2) {
        $result = $smcFunc['db_query']('', '
			SELECT MAX(id_attach)
			FROM {db_prefix}attachments', array());
        list($thumbnails) = $smcFunc['db_fetch_row']($result);
        $smcFunc['db_free_result']($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 250) {
            $to_remove = array();
            $errors_found = array();
            $result = $smcFunc['db_query']('', '
				SELECT id_attach, id_folder, filename, file_hash, size, attachment_type
				FROM {db_prefix}attachments
				WHERE id_attach BETWEEN {int:substep} AND {int:substep} + 249', array('substep' => $_GET['substep']));
            while ($row = $smcFunc['db_fetch_assoc']($result)) {
                // Get the filename.
                if ($row['attachment_type'] == 1) {
                    $filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename'];
                } else {
                    $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
                }
                // File doesn't exist?
                if (!file_exists($filename)) {
                    // If we're lucky it might just be in a different folder.
                    if (!empty($modSettings['currentAttachmentUploadDir'])) {
                        // Get the attachment name with out the folder.
                        $attachment_name = !empty($row['file_hash']) ? $row['id_attach'] . '_' . $row['file_hash'] : getLegacyAttachmentFilename($row['filename'], $row['id_attach'], null, true);
                        if (!is_array($modSettings['attachmentUploadDir'])) {
                            $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
                        }
                        // Loop through the other folders.
                        foreach ($modSettings['attachmentUploadDir'] as $id => $dir) {
                            if (file_exists($dir . '/' . $attachment_name)) {
                                $context['repair_errors']['wrong_folder']++;
                                $errors_found[] = 'wrong_folder';
                                // Are we going to fix this now?
                                if ($fix_errors && in_array('wrong_folder', $to_fix)) {
                                    $smcFunc['db_query']('', '
										UPDATE {db_prefix}attachments
										SET id_folder = {int:new_folder}
										WHERE id_attach = {int:id_attach}', array('new_folder' => $id, 'id_attach' => $row['id_attach']));
                                }
                                continue 2;
                            }
                        }
                    }
                    $to_remove[] = $row['id_attach'];
                    $context['repair_errors']['file_missing_on_disk']++;
                    $errors_found[] = 'file_missing_on_disk';
                } elseif (filesize($filename) == 0) {
                    $context['repair_errors']['file_size_of_zero']++;
                    $errors_found[] = 'file_size_of_zero';
                    // Fixing?
                    if ($fix_errors && in_array('file_size_of_zero', $to_fix)) {
                        $to_remove[] = $row['id_attach'];
                        @unlink($filename);
                    }
                } elseif (filesize($filename) != $row['size']) {
                    $context['repair_errors']['file_wrong_size']++;
                    $errors_found[] = 'file_wrong_size';
                    // Fix it here?
                    if ($fix_errors && in_array('file_wrong_size', $to_fix)) {
                        $smcFunc['db_query']('', '
							UPDATE {db_prefix}attachments
							SET size = {int:filesize}
							WHERE id_attach = {int:id_attach}', array('filesize' => filesize($filename), 'id_attach' => $row['id_attach']));
                    }
                }
            }
            if (in_array('file_missing_on_disk', $errors_found)) {
                $to_fix[] = 'file_missing_on_disk';
            }
            if (in_array('file_size_of_zero', $errors_found)) {
                $to_fix[] = 'file_size_of_zero';
            }
            if (in_array('file_wrong_size', $errors_found)) {
                $to_fix[] = 'file_wrong_size';
            }
            if (in_array('wrong_folder', $errors_found)) {
                $to_fix[] = 'wrong_folder';
            }
            $smcFunc['db_free_result']($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove)) {
                $smcFunc['db_query']('', '
					DELETE FROM {db_prefix}attachments
					WHERE id_attach IN ({array_int:to_remove})', array('to_remove' => $to_remove));
                $smcFunc['db_query']('', '
					UPDATE {db_prefix}attachments
					SET id_thumb = {int:no_thumb}
					WHERE id_thumb IN ({array_int:to_remove})', array('to_remove' => $to_remove, 'no_thumb' => 0));
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 3;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // Get avatars with no members associated with them.
    if ($_GET['step'] <= 3) {
        $result = $smcFunc['db_query']('', '
			SELECT MAX(id_attach)
			FROM {db_prefix}attachments', array());
        list($thumbnails) = $smcFunc['db_fetch_row']($result);
        $smcFunc['db_free_result']($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_remove = array();
            $result = $smcFunc['db_query']('', '
				SELECT a.id_attach, a.id_folder, a.filename, a.file_hash, a.attachment_type
				FROM {db_prefix}attachments AS a
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member)
				WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499
					AND a.id_member != {int:no_member}
					AND a.id_msg = {int:no_msg}
					AND mem.id_member IS NULL', array('no_member' => 0, 'no_msg' => 0, 'substep' => $_GET['substep']));
            while ($row = $smcFunc['db_fetch_assoc']($result)) {
                $to_remove[] = $row['id_attach'];
                $context['repair_errors']['avatar_no_member']++;
                // If we are repairing remove the file from disk now.
                if ($fix_errors && in_array('avatar_no_member', $to_fix)) {
                    if ($row['attachment_type'] == 1) {
                        $filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename'];
                    } else {
                        $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
                    }
                    @unlink($filename);
                }
            }
            if ($smcFunc['db_num_rows']($result) != 0) {
                $to_fix[] = 'avatar_no_member';
            }
            $smcFunc['db_free_result']($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove) && in_array('avatar_no_member', $to_fix)) {
                $smcFunc['db_query']('', '
					DELETE FROM {db_prefix}attachments
					WHERE id_attach IN ({array_int:to_remove})
						AND id_member != {int:no_member}
						AND id_msg = {int:no_msg}', array('to_remove' => $to_remove, 'no_member' => 0, 'no_msg' => 0));
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 4;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // What about attachments, who are missing a message :'(
    if ($_GET['step'] <= 4) {
        $result = $smcFunc['db_query']('', '
			SELECT MAX(id_attach)
			FROM {db_prefix}attachments', array());
        list($thumbnails) = $smcFunc['db_fetch_row']($result);
        $smcFunc['db_free_result']($result);
        for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) {
            $to_remove = array();
            $result = $smcFunc['db_query']('', '
				SELECT a.id_attach, a.id_folder, a.filename, a.file_hash
				FROM {db_prefix}attachments AS a
					LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
				WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499
					AND a.id_member = {int:no_member}
					AND a.id_msg != {int:no_msg}
					AND m.id_msg IS NULL', array('no_member' => 0, 'no_msg' => 0, 'substep' => $_GET['substep']));
            while ($row = $smcFunc['db_fetch_assoc']($result)) {
                $to_remove[] = $row['id_attach'];
                $context['repair_errors']['attachment_no_msg']++;
                // If we are repairing remove the file from disk now.
                if ($fix_errors && in_array('attachment_no_msg', $to_fix)) {
                    $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
                    @unlink($filename);
                }
            }
            if ($smcFunc['db_num_rows']($result) != 0) {
                $to_fix[] = 'attachment_no_msg';
            }
            $smcFunc['db_free_result']($result);
            // Do we need to delete what we have?
            if ($fix_errors && !empty($to_remove) && in_array('attachment_no_msg', $to_fix)) {
                $smcFunc['db_query']('', '
					DELETE FROM {db_prefix}attachments
					WHERE id_attach IN ({array_int:to_remove})
						AND id_member = {int:no_member}
						AND id_msg != {int:no_msg}', array('to_remove' => $to_remove, 'no_member' => 0, 'no_msg' => 0));
            }
            pauseAttachmentMaintenance($to_fix, $thumbnails);
        }
        $_GET['step'] = 5;
        $_GET['substep'] = 0;
        pauseAttachmentMaintenance($to_fix);
    }
    // Got here we must be doing well - just the template! :D
    $context['page_title'] = $txt['repair_attachments'];
    $context[$context['admin_menu_name']]['current_subsection'] = 'maintenance';
    $context['sub_template'] = 'attachment_repair';
    // What stage are we at?
    $context['completed'] = $fix_errors ? true : false;
    $context['errors_found'] = !empty($to_fix) ? true : false;
}
Example #4
0
/**
 * Load message image attachments for use in the print page function
 * Returns array of file attachment name along with width/height properties
 * Will only return approved attachments
 *
 * @param int[] $id_messages
 */
function messagesAttachments($id_messages)
{
    global $modSettings;
    $db = database();
    $request = $db->query('', '
		SELECT
			a.id_attach, a.id_msg, a.approved, a.width, a.height, a.file_hash, a.filename, a.id_folder, a.mime_type
		FROM {db_prefix}attachments AS a
		WHERE a.id_msg IN ({array_int:message_list})
			AND a.attachment_type = {int:attachment_type}', array('message_list' => $id_messages, 'attachment_type' => 0, 'is_approved' => 1));
    $temp = array();
    $printattach = array();
    while ($row = $db->fetch_assoc($request)) {
        $temp[$row['id_attach']] = $row;
        if (!isset($printattach[$row['id_msg']])) {
            $printattach[$row['id_msg']] = array();
        }
    }
    $db->free_result($request);
    ksort($temp);
    // Load them into $context so the template can use them
    foreach ($temp as $row) {
        if (!empty($row['width']) && !empty($row['height'])) {
            if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $row['height'] * ($modSettings['max_image_width'] / $row['width']) <= $modSettings['max_image_height'])) {
                if ($row['width'] > $modSettings['max_image_width']) {
                    $row['height'] = floor($row['height'] * ($modSettings['max_image_width'] / $row['width']));
                    $row['width'] = $modSettings['max_image_width'];
                }
            } elseif (!empty($modSettings['max_image_width'])) {
                if ($row['height'] > $modSettings['max_image_height']) {
                    $row['width'] = floor($row['width'] * $modSettings['max_image_height'] / $row['height']);
                    $row['height'] = $modSettings['max_image_height'];
                }
            }
            $row['filename'] = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
            // save for the template
            $printattach[$row['id_msg']][] = $row;
        }
    }
    return $printattach;
}
Example #5
0
function makeAvatarChanges($memID, &$post_errors)
{
    global $modSettings, $sourcedir, $db_prefix;
    if (!isset($_POST['avatar_choice']) || empty($memID)) {
        return;
    }
    require_once $sourcedir . '/ManageAttachments.php';
    $uploadDir = empty($modSettings['custom_avatar_enabled']) ? $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir'];
    $downloadedExternalAvatar = false;
    if ($_POST['avatar_choice'] == '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');
        }
        require_once $sourcedir . '/Subs-Package.php';
        $url = parse_url($_POST['userpicpersonal']);
        $contents = fetch_web_data('http://' . $url['host'] . (empty($url['port']) ? '' : ':' . $url['port']) . $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 ($_POST['avatar_choice'] == 'server_stored' && allowedTo('profile_server_avatar')) {
        $_POST['avatar'] = strtr(empty($_POST['file']) ? empty($_POST['cat']) ? '' : $_POST['cat'] : $_POST['file'], array('&amp;' => '&'));
        $_POST['avatar'] = preg_match('~^([\\w _!@%*=\\-#()\\[\\]&.,]+/)?[\\w _!@%*=\\-#()\\[\\]&.,]+$~', $_POST['avatar']) != 0 && preg_match('/\\.\\./', $_POST['avatar']) == 0 && file_exists($modSettings['avatar_directory'] . '/' . $_POST['avatar']) ? $_POST['avatar'] == 'blank.gif' ? '' : $_POST['avatar'] : '';
        // Get rid of their old avatar. (if uploaded.)
        removeAttachments('a.ID_MEMBER = ' . $memID);
    } elseif ($_POST['avatar_choice'] == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && empty($modSettings['avatar_download_external'])) {
        // Remove any attached avatar...
        removeAttachments('a.ID_MEMBER = ' . $memID);
        $_POST['avatar'] = preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $_POST['userpicpersonal']);
        if ($_POST['avatar'] == 'http://' || $_POST['avatar'] == 'http:///') {
            $_POST['avatar'] = '';
        } elseif (substr($_POST['avatar'], 0, 7) != 'http://') {
            $post_errors[] = '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($_POST['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') {
                    $post_errors[] = 'bad_avatar';
                } elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize') {
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (downloadAvatar($_POST['avatar'], $memID, $modSettings['avatar_max_width_external'], $modSettings['avatar_max_height_external'])) {
                        $_POST['avatar'] = '';
                    } else {
                        $post_errors[] = 'bad_avatar';
                    }
                }
            }
        }
    } elseif ($_POST['avatar_choice'] == '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');
                }
                if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadDir . '/avatar_tmp_' . $memID)) {
                    fatal_lang_error('smf124');
                }
                $_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) {
                $post_errors[] = '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';
                    downloadAvatar($uploadDir . '/avatar_tmp_' . $memID, $memID, $modSettings['avatar_max_width_upload'], $modSettings['avatar_max_height_upload']);
                } else {
                    $post_errors[] = 'bad_avatar';
                }
            } elseif (is_array($sizes)) {
                // Though not an exhaustive list, better safe than sorry.
                $fp = fopen($_FILES['attachment']['tmp_name'], 'rb');
                if (!$fp) {
                    fatal_lang_error('smf124');
                }
                // Now try to find an infection.
                while (!feof($fp)) {
                    if (preg_match('~(iframe|\\<\\?php|\\<\\?[\\s=]|\\<%[\\s=]|html|eval|body|script\\W)~', fgets($fp, 4096)) === 1) {
                        if (file_exists($uploadDir . '/avatar_tmp_' . $memID)) {
                            @unlink($uploadDir . '/avatar_tmp_' . $memID);
                        }
                        fatal_lang_error('smf124');
                    }
                }
                fclose($fp);
                $extensions = array('1' => '.gif', '2' => '.jpg', '3' => '.png', '6' => '.bmp');
                $extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : '.bmp';
                $destName = 'avatar_' . $memID . $extension;
                list($width, $height) = getimagesize($_FILES['attachment']['tmp_name']);
                // Remove previous attachments this member might have had.
                removeAttachments('a.ID_MEMBER = ' . $memID);
                $file_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, true) : '';
                db_query("\n\t\t\t\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t\t\t\t(ID_MEMBER, attachmentType, filename, file_hash, size, width, height)\n\t\t\t\t\tVALUES ({$memID}, " . (empty($modSettings['custom_avatar_enabled']) ? '0' : '1') . ", '{$destName}', '" . (empty($file_hash) ? "" : "{$file_hash}") . "', " . filesize($_FILES['attachment']['tmp_name']) . ", " . (int) $width . ", " . (int) $height . ")", __FILE__, __LINE__);
                $attachID = db_insert_id();
                // Try to move this avatar.
                $destinationPath = $uploadDir . '/' . (empty($file_hash) ? $destName : $attachID . '_' . $file_hash);
                if (!rename($_FILES['attachment']['tmp_name'], $destinationPath)) {
                    // The move failed, get rid of it and die.
                    db_query("\n\t\t\t\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\t\t\t\tWHERE ID_ATTACH = {$attachID}", __FILE__, __LINE__);
                    fatal_lang_error('smf124');
                }
                // Attempt to chmod it.
                @chmod($destinationPath, 0644);
            }
            $_POST['avatar'] = '';
            // Delete any temporary file.
            if (file_exists($uploadDir . '/avatar_tmp_' . $memID)) {
                @unlink($uploadDir . '/avatar_tmp_' . $memID);
            }
        } else {
            $_POST['avatar'] = '';
        }
    } else {
        $_POST['avatar'] = '';
    }
}
Example #6
0
function shd_attachment_info($attach_info)
{
    global $scripturl, $context, $modSettings, $txt, $sourcedir, $smcFunc;
    $filename = preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attach_info['filename']));
    $deleteable = shd_allowed_to('shd_delete_attachment', $context['ticket']['dept']);
    $attach = array('id' => $attach_info['id_attach'], 'name' => $filename, 'size' => round($attach_info['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], 'byte_size' => $attach_info['filesize'], 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'], 'link' => shd_attach_icon($filename) . '&nbsp;<a href="' . $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'] . '">' . htmlspecialchars($attach_info['filename']) . '</a>', 'is_image' => !empty($modSettings['attachmentShowImages']) && !empty($attach_info['width']) && !empty($attach_info['height']), 'can_delete' => $deleteable);
    if ($attach['is_image']) {
        $attach += array('real_width' => $attach_info['width'], 'width' => $attach_info['width'], 'real_height' => $attach_info['height'], 'height' => $attach_info['height']);
        // Let's see, do we want thumbs?
        if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attach_info['width'] > $modSettings['attachmentThumbWidth'] || $attach_info['height'] > $modSettings['attachmentThumbHeight']) && strlen($attach_info['filename']) < 249) {
            // A proper thumb doesn't exist yet? Create one!
            if (empty($attach_info['id_thumb']) || $attach_info['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attach_info['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attach_info['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attach_info['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                $filename = getAttachmentFilename($attach_info['filename'], $attach_info['id_attach'], $attach_info['id_folder']);
                require_once $sourcedir . '/Subs-Graphics.php';
                if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                    // So what folder are we putting this image in?
                    if (!empty($modSettings['currentAttachmentUploadDir'])) {
                        if (!is_array($modSettings['attachmentUploadDir'])) {
                            $modSettings['attachmentUploadDir'] = json_decode($modSettings['attachmentUploadDir'], true);
                        }
                        $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
                        $id_folder_thumb = $modSettings['currentAttachmentUploadDir'];
                    } else {
                        $path = $modSettings['attachmentUploadDir'];
                        $id_folder_thumb = 1;
                    }
                    // Calculate the size of the created thumbnail.
                    $size = @getimagesize($filename . '_thumb');
                    list($attach_info['thumb_width'], $attach_info['thumb_height']) = $size;
                    $thumb_size = filesize($filename . '_thumb');
                    // 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');
                    // What about the extension?
                    $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
                    // Figure out the mime type.
                    if (!empty($size['mime'])) {
                        $thumb_mime = $size['mime'];
                    } else {
                        $thumb_mime = 'image/' . $thumb_ext;
                    }
                    $thumb_filename = $attach_info['filename'] . '_thumb';
                    $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true);
                    // Add this beauty to the database.
                    $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, 0, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attach_info['thumb_width'], (int) $attach_info['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
                    $old_id_thumb = $attach_info['id_thumb'];
                    $attach_info['id_thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
                    if (!empty($attach_info['id_thumb'])) {
                        // Update the tables to notify that we has us a thumbnail
                        $smcFunc['db_query']('', '
							UPDATE {db_prefix}attachments
							SET id_thumb = {int:id_thumb}
							WHERE id_attach = {int:id_attach}', array('id_thumb' => $attach_info['id_thumb'], 'id_attach' => $attach_info['id_attach']));
                        $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_attachments', array('id_attach' => 'int', 'id_ticket' => 'int', 'id_msg' => 'int'), array($attach_info['id_thumb'], $attach_info['id_ticket'], $attach_info['id_msg']), array('id_attach'));
                        $thumb_realname = getAttachmentFilename($thumb_filename, $attach_info['id_thumb'], $id_folder_thumb, false, $thumb_hash);
                        rename($filename . '_thumb', $thumb_realname);
                        // Do we need to remove an old thumbnail?
                        if (!empty($old_id_thumb)) {
                            require_once $sourcedir . '/ManageAttachments.php';
                            removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
                        }
                    }
                }
            }
            // Only adjust dimensions on successful thumbnail creation.
            if (!empty($attach_info['thumb_width']) && !empty($attach_info['thumb_height'])) {
                $attach['width'] = $attach_info['thumb_width'];
                $attach['height'] = $attach_info['thumb_height'];
            }
        }
        if (!empty($attach_info['id_thumb'])) {
            $attach['thumbnail'] = array('id' => $attach_info['id_thumb'], 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_thumb'] . ';image');
        }
        $attach['thumbnail']['has_thumb'] = !empty($attach_info['id_thumb']);
        // If thumbnails are disabled, check the maximum size of the image.
        if (!$attach['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attach_info['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attach_info['height'] > $modSettings['max_image_height'])) {
            if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width'] <= $modSettings['max_image_height'])) {
                $attach['width'] = $modSettings['max_image_width'];
                $attach['height'] = floor($attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width']);
            } elseif (!empty($modSettings['max_image_width'])) {
                $attach['width'] = floor($attach['width'] * $modSettings['max_image_height'] / $attach['height']);
                $attach['height'] = $modSettings['max_image_height'];
            }
        } elseif ($attach['thumbnail']['has_thumb']) {
            // Make it a popup (since invariably it'll break the layout otherwise)
            $attach['thumbnail']['javascript'] = 'return reqWin(\'' . $attach['href'] . ';image\', ' . ($attach_info['width'] + 20) . ', ' . ($attach_info['height'] + 20) . ', true);';
        }
    }
    return $attach;
}
Example #7
0
function createAttachment(&$attachmentOptions)
{
    global $db_prefix, $modSettings, $sourcedir;
    $attachmentOptions['errors'] = array();
    if (!isset($attachmentOptions['post'])) {
        $attachmentOptions['post'] = 0;
    }
    $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'] = $modSettings['attachmentUploadDir'] . '/' . $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;
    }
    if (!$file_restricted || $already_uploaded) {
        list($attachmentOptions['width'], $attachmentOptions['height']) = @getimagesize($attachmentOptions['tmp_name']);
    }
    // Get the hash if no hash has been given yet.
    if (empty($attachmentOptions['file_hash'])) {
        $attachmentOptions['file_hash'] = getAttachmentFilename($attachmentOptions['name'], false, 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'])) {
        // Make sure the directory isn't full.
        $dirSize = 0;
        $dir = @opendir($modSettings['attachmentUploadDir']) or fatal_lang_error('smf115b');
        while ($file = readdir($dir)) {
            if (substr($file, 0, -1) == '.') {
                continue;
            }
            if (preg_match('~^post_tmp_\\d+_\\d+$~', $file) != 0) {
                // Temp file is more than 5 hours old!
                if (filemtime($modSettings['attachmentUploadDir'] . '/' . $file) < time() - 18000) {
                    @unlink($modSettings['attachmentUploadDir'] . '/' . $file);
                }
                continue;
            }
            $dirSize += filesize($modSettings['attachmentUploadDir'] . '/' . $file);
        }
        closedir($dir);
        // Too big!  Maybe you could zip it or something...
        if ($attachmentOptions['size'] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024) {
            $attachmentOptions['errors'][] = 'directory_full';
        }
    }
    // 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 = db_query("\n\t\t\tSELECT ID_ATTACH\n\t\t\tFROM {$db_prefix}attachments\n\t\t\tWHERE filename = '" . strtolower($attachmentOptions['name']) . "'\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        if (mysql_num_rows($request) > 0) {
            $attachmentOptions['errors'][] = 'taken_filename';
        }
        mysql_free_result($request);
    }
    if (!empty($attachmentOptions['errors'])) {
        return false;
    }
    if (!is_writable($modSettings['attachmentUploadDir'])) {
        fatal_lang_error('attachments_no_write');
    }
    db_query("\n\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t(ID_MSG, filename, file_hash, size, width, height)\n\t\tVALUES (" . (int) $attachmentOptions['post'] . ", SUBSTRING('" . $attachmentOptions['name'] . "', 1, 255), '{$attachmentOptions['file_hash']}', " . (int) $attachmentOptions['size'] . ', ' . (empty($attachmentOptions['width']) ? '0' : (int) $attachmentOptions['width']) . ', ' . (empty($attachmentOptions['height']) ? '0' : (int) $attachmentOptions['height']) . ')', __FILE__, __LINE__);
    $attachmentOptions['id'] = db_insert_id();
    if (empty($attachmentOptions['id'])) {
        return false;
    }
    $attachmentOptions['destination'] = getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], 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('smf124');
    } elseif ($file_restricted) {
        list($attachmentOptions['width'], $attachmentOptions['height']) = @getimagesize($attachmentOptions['destination']);
        if (!empty($attachmentOptions['width']) && !empty($attachmentOptions['height'])) {
            db_query("\n\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\tSET\n\t\t\t\t\twidth = " . (int) $attachmentOptions['width'] . ",\n\t\t\t\t\theight = " . (int) $attachmentOptions['height'] . "\n\t\t\t\tWHERE ID_ATTACH = {$attachmentOptions['id']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
        }
    }
    // Attempt to chmod it.
    @chmod($attachmentOptions['destination'], 0644);
    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'])) {
        require_once $sourcedir . '/Subs-Graphics.php';
        if (createThumbnail($attachmentOptions['destination'], $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
            // Figure out how big we actually made it.
            list($thumb_width, $thumb_height) = @getimagesize($attachmentOptions['destination'] . '_thumb');
            $thumb_filename = addslashes($attachmentOptions['name'] . '_thumb');
            $thumb_size = filesize($attachmentOptions['destination'] . '_thumb');
            // To the database we go!
            $thumb_file_hash = getAttachmentFilename($thumb_filename, false, true);
            db_query("\n\t\t\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t\t\t(ID_MSG, attachmentType, filename, file_hash, size, width, height)\n\t\t\t\tVALUES (" . (int) $attachmentOptions['post'] . ", 3, SUBSTRING('{$thumb_filename}', 1, 255), '{$thumb_file_hash}', " . (int) $thumb_size . ", " . (int) $thumb_width . ", " . (int) $thumb_height . ")", __FILE__, __LINE__);
            $attachmentOptions['thumb'] = db_insert_id();
            if (!empty($attachmentOptions['thumb'])) {
                db_query("\n\t\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\t\tSET ID_THUMB = {$attachmentOptions['thumb']}\n\t\t\t\t\tWHERE ID_ATTACH = {$attachmentOptions['id']}\n\t\t\t\t\tLIMIT 1", __FILE__, __LINE__);
                rename($attachmentOptions['destination'] . '_thumb', getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], false, $thumb_file_hash));
            }
        }
    }
    return true;
}
Example #8
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;
}
function removeAllAttachments()
{
    global $to_prefix, $smcFunc;
    $result = convert_query("\n\t\tSELECT value\n\t\tFROM {$to_prefix}settings\n\t\tWHERE variable = 'attachmentUploadDir'\n\t\tLIMIT 1");
    list($attachmentUploadDir) = $smcFunc['db_fetch_row']($result);
    $smcFunc['db_free_result']($result);
    // !!! This should probably be done in chunks too.
    $result = convert_query("\n\t\tSELECT id_attach, filename\n\t\tFROM {$to_prefix}attachments");
    while ($row = $smcFunc['db_fetch_assoc']($result)) {
        $filename = $row['filename'];
        $id_attach = $row['id_attach'];
        $physical_filename = getAttachmentFilename($filename, $id_attach);
        if (file_exists($physical_filename)) {
            @unlink($physical_filename);
        }
    }
    $smcFunc['db_free_result']($result);
}
Example #10
0
function downloadAvatar($url, $memID, $max_width, $max_height)
{
    global $modSettings, $db_prefix, $sourcedir, $gd2;
    $destName = 'avatar_' . $memID . '.' . (!empty($modSettings['avatar_download_png']) ? 'png' : 'jpeg');
    $default_formats = array('1' => 'gif', '2' => 'jpeg', '3' => 'png', '6' => 'bmp', '15' => 'wbmp');
    // Check to see if GD is installed and what version.
    $testGD = get_extension_funcs('gd');
    // If GD is not installed, this function is pointless.
    if (empty($testGD)) {
        return false;
    }
    // Just making sure there is a non-zero member.
    if (empty($memID)) {
        return false;
    }
    // GD 2 maybe?
    $gd2 = in_array('imagecreatetruecolor', $testGD) && function_exists('imagecreatetruecolor');
    unset($testGD);
    require_once $sourcedir . '/ManageAttachments.php';
    removeAttachments('a.ID_MEMBER = ' . $memID);
    $avatar_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, true) : '';
    db_query("\n\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t(ID_MEMBER, attachmentType, filename, file_hash, size)\n\t\tVALUES ({$memID}, " . (empty($modSettings['custom_avatar_enabled']) ? '0' : '1') . ", '{$destName}', '" . (empty($avatar_hash) ? "" : "{$avatar_hash}") . "', 1)", __FILE__, __LINE__);
    $attachID = db_insert_id();
    $destName = (empty($modSettings['custom_avatar_enabled']) ? $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir']) . '/' . $destName . '.tmp';
    $success = false;
    $sizes = url_image_size($url);
    require_once $sourcedir . '/Subs-Package.php';
    $fp = fopen($destName, 'wb');
    if ($fp && substr($url, 0, 7) == 'http://') {
        $fileContents = fetch_web_data($url);
        // Though not an exhaustive list, better safe than sorry.
        if (preg_match('~(iframe|\\<\\?php|\\<\\?[\\s=]|\\<%[\\s=]|html|eval|body|script\\W)~', $fileContents) === 1) {
            fclose($fp);
            return false;
        }
        fwrite($fp, $fileContents);
        fclose($fp);
    } elseif ($fp) {
        $fp2 = fopen($url, 'rb');
        $prev_chunk = '';
        while (!feof($fp2)) {
            $cur_chunk = fread($fp2, 8192);
            // Make sure nothing odd came through.
            if (preg_match('~(iframe|\\<\\?php|\\<\\?[\\s=]|\\<%[\\s=]|html|eval|body|script\\W)~', $prev_chunk . $cur_chunk) === 1) {
                fclose($fp2);
                fclose($fp);
                unlink($destName);
                return false;
            }
            fwrite($fp, $cur_chunk);
            $prev_chunk = $cur_chunk;
        }
        fclose($fp2);
        fclose($fp);
    } else {
        $sizes = array(-1, -1, -1);
    }
    // Gif? That might mean trouble if gif support is not available.
    if ($sizes[2] == 1 && !function_exists('imagecreatefromgif') && function_exists('imagecreatefrompng')) {
        // Download it to the temporary file... use the special gif library... and save as png.
        if ($img = @gif_loadFile($destName) && gif_outputAsPng($img, $destName)) {
            $sizes[2] = 3;
        }
    }
    // A known and supported format?
    if (isset($default_formats[$sizes[2]]) && function_exists('imagecreatefrom' . $default_formats[$sizes[2]])) {
        $imagecreatefrom = 'imagecreatefrom' . $default_formats[$sizes[2]];
        if ($src_img = @$imagecreatefrom($destName)) {
            resizeImage($src_img, $destName, imagesx($src_img), imagesy($src_img), $max_width, $max_height);
            $success = true;
        }
    }
    // Remove the .tmp extension.
    $destName = substr($destName, 0, -4);
    if ($success) {
        // Remove the .tmp extension from the attachment.
        if (rename($destName . '.tmp', empty($avatar_hash) ? $destName : $modSettings['attachmentUploadDir'] . '/' . $attachID . '_' . $avatar_hash)) {
            $destName = empty($avatar_hash) ? $destName : $modSettings['attachmentUploadDir'] . '/' . $attachID . '_' . $avatar_hash;
            list($width, $height) = getimagesize($destName);
            // Write filesize in the database.
            db_query("\n\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\tSET size = " . filesize($destName) . ", width = " . (int) $width . ", height = " . (int) $height . "\n\t\t\t\tWHERE ID_ATTACH = {$attachID}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
            return true;
        } else {
            return false;
        }
    } else {
        db_query("\n\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\tWHERE ID_ATTACH = {$attachID}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        @unlink($destName . '.tmp');
        return false;
    }
}
    /**
     * Maintenance function to move attachments from one directory to another
     */
    public function action_transfer()
    {
        global $modSettings, $txt;
        checkSession();
        // We will need the functions from here
        require_once SUBSDIR . '/Attachments.subs.php';
        require_once SUBSDIR . '/ManageAttachments.subs.php';
        // The list(s) of directory's that are available.
        $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
        if (!empty($modSettings['attachment_basedirectories'])) {
            $modSettings['attachment_basedirectories'] = unserialize($modSettings['attachment_basedirectories']);
        } else {
            $modSettings['basedirectory_for_attachments'] = array();
        }
        // Clean the inputs
        $_POST['from'] = (int) $_POST['from'];
        $_POST['auto'] = !empty($_POST['auto']) ? (int) $_POST['auto'] : 0;
        $_POST['to'] = (int) $_POST['to'];
        $start = !empty($_POST['empty_it']) ? 0 : $modSettings['attachmentDirFileLimit'];
        $_SESSION['checked'] = !empty($_POST['empty_it']) ? true : false;
        // Prepare for the moving
        $limit = 501;
        $results = array();
        $dir_files = 0;
        $current_progress = 0;
        $total_moved = 0;
        $total_not_moved = 0;
        // Need to know where we are moving things from
        if (empty($_POST['from']) || empty($_POST['auto']) && empty($_POST['to'])) {
            $results[] = $txt['attachment_transfer_no_dir'];
        }
        // Same location, that's easy
        if ($_POST['from'] == $_POST['to']) {
            $results[] = $txt['attachment_transfer_same_dir'];
        }
        // No errors so determine how many we may have to move
        if (empty($results)) {
            // Get the total file count for the progress bar.
            $total_progress = getFolderAttachmentCount($_POST['from']);
            $total_progress -= $start;
            if ($total_progress < 1) {
                $results[] = $txt['attachment_transfer_no_find'];
            }
        }
        // Nothing to move (no files in source or below the max limit)
        if (empty($results)) {
            // Moving them automaticaly?
            if (!empty($_POST['auto'])) {
                $modSettings['automanage_attachments'] = 1;
                // Create sub directroys off the root or from an attachment directory?
                $modSettings['use_subdirectories_for_attachments'] = $_POST['auto'] == -1 ? 0 : 1;
                $modSettings['basedirectory_for_attachments'] = $_POST['auto'] > 0 ? $modSettings['attachmentUploadDir'][$_POST['auto']] : $modSettings['basedirectory_for_attachments'];
                // Finaly, where do they need to go
                automanage_attachments_check_directory();
                $new_dir = $modSettings['currentAttachmentUploadDir'];
            } else {
                $new_dir = $_POST['to'];
            }
            $modSettings['currentAttachmentUploadDir'] = $new_dir;
            $break = false;
            while ($break === false) {
                @set_time_limit(300);
                if (function_exists('apache_reset_timeout')) {
                    @apache_reset_timeout();
                }
                // If limits are set, get the file count and size for the destination folder
                if ($dir_files <= 0 && (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit']))) {
                    $current_dir = attachDirProperties($new_dir);
                    $dir_files = $current_dir['files'];
                    $dir_size = $current_dir['size'];
                }
                // Find some attachments to move
                list($tomove_count, $tomove) = findAttachmentsToMove($_POST['from'], $start, $limit);
                // Nothing found to move
                if ($tomove_count === 0) {
                    if (empty($current_progress)) {
                        $results[] = $txt['attachment_transfer_no_find'];
                    }
                    break;
                }
                // No more to move after this batch then set the finished flag.
                if ($tomove_count < $limit) {
                    $break = true;
                }
                // Move them
                $moved = array();
                foreach ($tomove as $row) {
                    $source = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
                    $dest = $modSettings['attachmentUploadDir'][$new_dir] . '/' . basename($source);
                    // Size and file count check
                    if (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit'])) {
                        $dir_files++;
                        $dir_size += !empty($row['size']) ? $row['size'] : filesize($source);
                        // If we've reached a directory limit. Do something if we are in auto mode, otherwise set an error.
                        if (!empty($modSettings['attachmentDirSizeLimit']) && $dir_size > $modSettings['attachmentDirSizeLimit'] * 1024 || !empty($modSettings['attachmentDirFileLimit']) && $dir_files > $modSettings['attachmentDirFileLimit']) {
                            // Since we're in auto mode. Create a new folder and reset the counters.
                            if (!empty($_POST['auto'])) {
                                automanage_attachments_by_space();
                                $results[] = sprintf($txt['attachments_transfered'], $total_moved, $modSettings['attachmentUploadDir'][$new_dir]);
                                if (!empty($total_not_moved)) {
                                    $results[] = sprintf($txt['attachments_not_transfered'], $total_not_moved);
                                }
                                $dir_files = 0;
                                $total_moved = 0;
                                $total_not_moved = 0;
                                $break = false;
                                break;
                            } else {
                                $results[] = $txt['attachment_transfer_no_room'];
                                $break = true;
                                break;
                            }
                        }
                    }
                    // Actually move the file
                    if (@rename($source, $dest)) {
                        $total_moved++;
                        $current_progress++;
                        $moved[] = $row['id_attach'];
                    } else {
                        $total_not_moved++;
                    }
                }
                // Update the database to reflect the new file location
                if (!empty($moved)) {
                    moveAttachments($moved, $new_dir);
                }
                $new_dir = $modSettings['currentAttachmentUploadDir'];
                // Create / update the progress bar.
                // @todo why was this done this way?
                if (!$break) {
                    $percent_done = min(round($current_progress / $total_progress * 100, 0), 100);
                    $prog_bar = '
						<div class="progress_bar">
							<div class="full_bar">' . $percent_done . '%</div>
							<div class="green_percent" style="width: ' . $percent_done . '%;">&nbsp;</div>
						</div>';
                    // Write it to a file so it can be displayed
                    $fp = fopen(BOARDDIR . '/progress.php', 'w');
                    fwrite($fp, $prog_bar);
                    fclose($fp);
                    usleep(500000);
                }
            }
            $results[] = sprintf($txt['attachments_transfered'], $total_moved, $modSettings['attachmentUploadDir'][$new_dir]);
            if (!empty($total_not_moved)) {
                $results[] = sprintf($txt['attachments_not_transfered'], $total_not_moved);
            }
        }
        // All done, time to clean up
        $_SESSION['results'] = $results;
        if (file_exists(BOARDDIR . '/progress.php')) {
            unlink(BOARDDIR . '/progress.php');
        }
        redirectexit('action=admin;area=manageattachments;sa=maintenance#transfer');
    }
Example #12
0
/**
 * This loads an attachment's contextual data including, most importantly, its size if it is an image.
 *
 * What it does:
 * - Pre-condition: $attachments array to have been filled with the proper attachment data, as Display() does.
 * - It requires the view_attachments permission to calculate image size.
 * - It attempts to keep the "aspect ratio" of the posted image in line, even if it has to be resized by
 * the max_image_width and max_image_height settings.
 *
 * @todo change this pre-condition, too fragile and error-prone.
 *
 * @package Attachments
 * @param int $id_msg message number to load attachments for
 * @return array of attachments
 */
function loadAttachmentContext($id_msg)
{
    global $attachments, $modSettings, $txt, $scripturl, $topic;
    // Set up the attachment info - based on code by Meriadoc.
    $attachmentData = array();
    $have_unapproved = false;
    if (isset($attachments[$id_msg]) && !empty($modSettings['attachmentEnable'])) {
        foreach ($attachments[$id_msg] as $i => $attachment) {
            $attachmentData[$i] = array('id' => $attachment['id_attach'], 'name' => preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attachment['filename'], ENT_COMPAT, 'UTF-8')), 'downloads' => $attachment['downloads'], 'size' => $attachment['filesize'] < 1024000 ? round($attachment['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'] : round($attachment['filesize'] / 1024 / 1024, 2) . ' ' . $txt['megabyte'], 'byte_size' => $attachment['filesize'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'], 'link' => '<a href="' . $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'] . '">' . htmlspecialchars($attachment['filename'], ENT_COMPAT, 'UTF-8') . '</a>', 'is_image' => !empty($attachment['width']) && !empty($attachment['height']) && !empty($modSettings['attachmentShowImages']), 'is_approved' => $attachment['approved'], 'file_hash' => $attachment['file_hash']);
            // If something is unapproved we'll note it so we can sort them.
            if (!$attachment['approved']) {
                $have_unapproved = true;
            }
            if (!$attachmentData[$i]['is_image']) {
                continue;
            }
            $attachmentData[$i]['real_width'] = $attachment['width'];
            $attachmentData[$i]['width'] = $attachment['width'];
            $attachmentData[$i]['real_height'] = $attachment['height'];
            $attachmentData[$i]['height'] = $attachment['height'];
            // Let's see, do we want thumbs?
            if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachment['width'] > $modSettings['attachmentThumbWidth'] || $attachment['height'] > $modSettings['attachmentThumbHeight']) && strlen($attachment['filename']) < 249) {
                // A proper thumb doesn't exist yet? Create one! Or, it needs update.
                if (empty($attachment['id_thumb']) || $attachment['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attachment['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attachment['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attachment['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                    $filename = getAttachmentFilename($attachment['filename'], $attachment['id_attach'], $attachment['id_folder'], false, $attachment['file_hash']);
                    $attachment = array_merge($attachment, updateAttachmentThumbnail($filename, $attachment['id_attach'], $id_msg, $attachment['id_thumb']));
                }
                // Only adjust dimensions on successful thumbnail creation.
                if (!empty($attachment['thumb_width']) && !empty($attachment['thumb_height'])) {
                    $attachmentData[$i]['width'] = $attachment['thumb_width'];
                    $attachmentData[$i]['height'] = $attachment['thumb_height'];
                }
            }
            if (!empty($attachment['id_thumb'])) {
                $attachmentData[$i]['thumbnail'] = array('id' => $attachment['id_thumb'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_thumb'] . ';image');
            }
            $attachmentData[$i]['thumbnail']['has_thumb'] = !empty($attachment['id_thumb']);
            // If thumbnails are disabled, check the maximum size of the image.
            if (!$attachmentData[$i]['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attachment['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachment['height'] > $modSettings['max_image_height'])) {
                if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attachment['height'] * $modSettings['max_image_width'] / $attachment['width'] <= $modSettings['max_image_height'])) {
                    $attachmentData[$i]['width'] = $modSettings['max_image_width'];
                    $attachmentData[$i]['height'] = floor($attachment['height'] * $modSettings['max_image_width'] / $attachment['width']);
                } elseif (!empty($modSettings['max_image_width'])) {
                    $attachmentData[$i]['width'] = floor($attachment['width'] * $modSettings['max_image_height'] / $attachment['height']);
                    $attachmentData[$i]['height'] = $modSettings['max_image_height'];
                }
            } elseif ($attachmentData[$i]['thumbnail']['has_thumb']) {
                // If the image is too large to show inline, make it a popup.
                if (!empty($modSettings['max_image_width']) && $attachmentData[$i]['real_width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachmentData[$i]['real_height'] > $modSettings['max_image_height']) {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return reqWin(\'' . $attachmentData[$i]['href'] . ';image\', ' . ($attachment['width'] + 20) . ', ' . ($attachment['height'] + 20) . ', true);';
                } else {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return expandThumb(' . $attachment['id_attach'] . ');';
                }
            }
            if (!$attachmentData[$i]['thumbnail']['has_thumb']) {
                $attachmentData[$i]['downloads']++;
            }
        }
    }
    // Do we need to instigate a sort?
    if ($have_unapproved) {
        usort($attachmentData, 'approved_attach_sort');
    }
    return $attachmentData;
}
Example #13
0
/**
 * Create an attachment, with the given array of parameters.
 * - Adds any addtional or missing parameters to $attachmentOptions.
 * - Renames the temporary file.
 * - Creates a thumbnail if the file is an image and the option enabled.
 *
 * @param array $attachmentOptions
 */
function createAttachment(&$attachmentOptions)
{
    global $modSettings, $sourcedir, $smcFunc, $context;
    global $txt, $boarddir;
    require_once $sourcedir . '/Subs-Graphics.php';
    // 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 this is an image we need to set a few additional parameters.
    $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);
    }
    // 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'] = '';
        }
    }
    $smcFunc['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((int) $attachmentOptions['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'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
    // @todo Add an error here maybe?
    if (empty($attachmentOptions['id'])) {
        return false;
    }
    // Now that we have the attach id, let's rename this sucker and finish up.
    $attachmentOptions['destination'] = getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], $attachmentOptions['id_folder'], false, $attachmentOptions['file_hash']);
    rename($attachmentOptions['tmp_name'], $attachmentOptions['destination']);
    // If it's not approved then add to the approval queue.
    if (!$attachmentOptions['approved']) {
        $smcFunc['db_insert']('', '{db_prefix}approval_queue', array('id_attach' => 'int', 'id_msg' => 'int'), array($attachmentOptions['id'], (int) $attachmentOptions['post']), array());
    }
    if (empty($modSettings['attachmentThumbnails']) || empty($attachmentOptions['width']) && empty($attachmentOptions['height'])) {
        return true;
    }
    // Like thumbnails, do we?
    if (!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);
            $thumb_path = $attachmentOptions['destination'] . '_thumb';
            // We should check the file size and count here since thumbs are added to the existing totals.
            if (!empty($modSettings['automanage_attachments']) && $modSettings['automanage_attachments'] == 1 && !empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit'])) {
                $context['dir_size'] = isset($context['dir_size']) ? $context['dir_size'] += $thumb_size : ($context['dir_size'] = 0);
                $context['dir_files'] = isset($context['dir_files']) ? $context['dir_files']++ : ($context['dir_files'] = 0);
                // If the folder is full, try to create a new one and move the thumb to it.
                if ($context['dir_size'] > $modSettings['attachmentDirSizeLimit'] * 1024 || $context['dir_files'] + 2 > $modSettings['attachmentDirFileLimit']) {
                    if (automanage_attachments_by_space()) {
                        rename($thumb_path, $context['attach_dir'] . '/' . $thumb_filename);
                        $thumb_path = $context['attach_dir'] . '/' . $thumb_filename;
                        $context['dir_size'] = $thumb_size;
                        $context['dir_files'] = 1;
                    }
                }
            }
            // If a new folder has been already created. Gotta move this thumb there then.
            if ($modSettings['currentAttachmentUploadDir'] != $attachmentOptions['id_folder']) {
                rename($thumb_path, $context['attach_dir'] . '/' . $thumb_filename);
                $thumb_path = $context['attach_dir'] . '/' . $thumb_filename;
            }
            // To the database we go!
            $smcFunc['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($modSettings['currentAttachmentUploadDir'], (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'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
            if (!empty($attachmentOptions['thumb'])) {
                $smcFunc['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($thumb_path, getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], $modSettings['currentAttachmentUploadDir'], false, $thumb_file_hash));
            }
        }
    }
    return true;
}
Example #14
0
/**
 * Move avatars to their new directory.
 *
 * @package Attachments
 */
function moveAvatars()
{
    global $modSettings;
    $db = database();
    $request = $db->query('', '
		SELECT id_attach, id_folder, id_member, filename, file_hash
		FROM {db_prefix}attachments
		WHERE attachment_type = {int:attachment_type}
			AND id_member > {int:guest_id_member}', array('attachment_type' => 0, 'guest_id_member' => 0));
    $updatedAvatars = array();
    while ($row = $db->fetch_assoc($request)) {
        $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
        if (rename($filename, $modSettings['custom_avatar_dir'] . '/' . $row['filename'])) {
            $updatedAvatars[] = $row['id_attach'];
        }
    }
    $db->free_result($request);
    if (!empty($updatedAvatars)) {
        $db->query('', '
			UPDATE {db_prefix}attachments
			SET attachment_type = {int:attachment_type}
			WHERE id_attach IN ({array_int:updated_avatars})', array('updated_avatars' => $updatedAvatars, 'attachment_type' => 1));
    }
}
Example #15
0
function Post()
{
    global $txt, $scripturl, $topic, $db_prefix, $modSettings, $board, $ID_MEMBER;
    global $user_info, $sc, $board_info, $context, $settings, $sourcedir;
    global $options, $func, $language;
    loadLanguage('Post');
    $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new');
    // You can't reply with a poll... hacker.
    if (isset($_REQUEST['poll']) && !empty($topic) && !isset($_REQUEST['msg'])) {
        unset($_REQUEST['poll']);
    }
    // Posting an event?
    $context['make_event'] = isset($_REQUEST['calendar']);
    // You must be posting to *some* board.
    if (empty($board) && !$context['make_event']) {
        fatal_lang_error('smf232', false);
    }
    require_once $sourcedir . '/Subs-Post.php';
    if (isset($_REQUEST['xml'])) {
        $context['sub_template'] = 'post';
        // Just in case of an earlier error...
        $context['preview_message'] = '';
        $context['preview_subject'] = '';
    }
    // Check if it's locked.  It isn't locked if no topic is specified.
    if (!empty($topic)) {
        $request = db_query("\n\t\t\tSELECT\n\t\t\t\tt.locked, IFNULL(ln.ID_TOPIC, 0) AS notify, t.isSticky, t.ID_POLL, t.numReplies, mf.ID_MEMBER,\n\t\t\t\tt.ID_FIRST_MSG, mf.subject, GREATEST(ml.posterTime, ml.modifiedTime) AS lastPostTime\n\t\t\tFROM {$db_prefix}topics AS t\n\t\t\t\tLEFT JOIN {$db_prefix}log_notify AS ln ON (ln.ID_TOPIC = t.ID_TOPIC AND ln.ID_MEMBER = {$ID_MEMBER})\n\t\t\t\tLEFT JOIN {$db_prefix}messages AS mf ON (mf.ID_MSG = t.ID_FIRST_MSG)\n\t\t\t\tLEFT JOIN {$db_prefix}messages AS ml ON (ml.ID_MSG = t.ID_LAST_MSG)\n\t\t\tWHERE t.ID_TOPIC = {$topic}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        list($locked, $context['notify'], $sticky, $pollID, $context['num_replies'], $ID_MEMBER_POSTER, $ID_FIRST_MSG, $first_subject, $lastPostTime) = mysql_fetch_row($request);
        mysql_free_result($request);
        // If this topic already has a poll, they sure can't add another.
        if (isset($_REQUEST['poll']) && $pollID > 0) {
            unset($_REQUEST['poll']);
        }
        if (empty($_REQUEST['msg'])) {
            if ($user_info['is_guest'] && !allowedTo('post_reply_any')) {
                is_not_guest();
            }
            if ($ID_MEMBER_POSTER != $ID_MEMBER) {
                isAllowedTo('post_reply_any');
            } elseif (!allowedTo('post_reply_any')) {
                isAllowedTo('post_reply_own');
            }
        }
        $context['can_lock'] = allowedTo('lock_any') || $ID_MEMBER == $ID_MEMBER_POSTER && allowedTo('lock_own');
        $context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']);
        $context['notify'] = !empty($context['notify']);
        $context['sticky'] = isset($_REQUEST['sticky']) ? !empty($_REQUEST['sticky']) : $sticky;
    } else {
        if ((!$context['make_event'] || !empty($board)) && (!isset($_REQUEST['poll']) || $modSettings['pollMode'] != '1')) {
            isAllowedTo('post_new');
        }
        $locked = 0;
        // !!! These won't work if you're making an event.
        $context['can_lock'] = allowedTo(array('lock_any', 'lock_own'));
        $context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']);
        $context['notify'] = !empty($context['notify']);
        $context['sticky'] = !empty($_REQUEST['sticky']);
    }
    // !!! These won't work if you're posting an event!
    $context['can_notify'] = allowedTo('mark_any_notify');
    $context['can_move'] = allowedTo('move_any');
    $context['can_announce'] = allowedTo('announce_topic');
    $context['locked'] = !empty($locked) || !empty($_REQUEST['lock']);
    // An array to hold all the attachments for this topic.
    $context['current_attachments'] = array();
    // Don't allow a post if it's locked and you aren't all powerful.
    if ($locked && !allowedTo('moderate_board')) {
        fatal_lang_error(90, false);
    }
    // Check the users permissions - is the user allowed to add or post a poll?
    if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') {
        // New topic, new poll.
        if (empty($topic)) {
            isAllowedTo('poll_post');
        } elseif ($ID_MEMBER == $ID_MEMBER_POSTER && !allowedTo('poll_add_any')) {
            isAllowedTo('poll_add_own');
        } else {
            isAllowedTo('poll_add_any');
        }
        // Set up the poll options.
        $context['poll_options'] = array('max_votes' => empty($_POST['poll_max_votes']) ? '1' : max(1, $_POST['poll_max_votes']), 'hide' => empty($_POST['poll_hide']) ? 0 : $_POST['poll_hide'], 'expire' => !isset($_POST['poll_expire']) ? '' : $_POST['poll_expire'], 'change_vote' => isset($_POST['poll_change_vote']));
        // Make all five poll choices empty.
        $context['choices'] = array(array('id' => 0, 'number' => 1, 'label' => '', 'is_last' => false), array('id' => 1, 'number' => 2, 'label' => '', 'is_last' => false), array('id' => 2, 'number' => 3, 'label' => '', 'is_last' => false), array('id' => 3, 'number' => 4, 'label' => '', 'is_last' => false), array('id' => 4, 'number' => 5, 'label' => '', 'is_last' => true));
    }
    if ($context['make_event']) {
        // They might want to pick a board.
        if (!isset($context['current_board'])) {
            $context['current_board'] = 0;
        }
        // Start loading up the event info.
        $context['event'] = array();
        $context['event']['title'] = isset($_REQUEST['evtitle']) ? htmlspecialchars(stripslashes($_REQUEST['evtitle'])) : '';
        $context['event']['id'] = isset($_REQUEST['eventid']) ? (int) $_REQUEST['eventid'] : -1;
        $context['event']['new'] = $context['event']['id'] == -1;
        // Permissions check!
        isAllowedTo('calendar_post');
        // Editing an event?  (but NOT previewing!?)
        if (!$context['event']['new'] && !isset($_REQUEST['subject'])) {
            // If the user doesn't have permission to edit the post in this topic, redirect them.
            if ($ID_MEMBER_POSTER != $ID_MEMBER || !allowedTo('modify_own') && !allowedTo('modify_any')) {
                require_once $sourcedir . '/Calendar.php';
                return CalendarPost();
            }
            // Get the current event information.
            $request = db_query("\n\t\t\t\tSELECT\n\t\t\t\t\tID_MEMBER, title, MONTH(startDate) AS month, DAYOFMONTH(startDate) AS day,\n\t\t\t\t\tYEAR(startDate) AS year, (TO_DAYS(endDate) - TO_DAYS(startDate)) AS span\n\t\t\t\tFROM {$db_prefix}calendar\n\t\t\t\tWHERE ID_EVENT = " . $context['event']['id'] . "\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
            $row = mysql_fetch_assoc($request);
            mysql_free_result($request);
            // Make sure the user is allowed to edit this event.
            if ($row['ID_MEMBER'] != $ID_MEMBER) {
                isAllowedTo('calendar_edit_any');
            } elseif (!allowedTo('calendar_edit_any')) {
                isAllowedTo('calendar_edit_own');
            }
            $context['event']['month'] = $row['month'];
            $context['event']['day'] = $row['day'];
            $context['event']['year'] = $row['year'];
            $context['event']['title'] = $row['title'];
            $context['event']['span'] = $row['span'] + 1;
        } else {
            $today = getdate();
            // You must have a month and year specified!
            if (!isset($_REQUEST['month'])) {
                $_REQUEST['month'] = $today['mon'];
            }
            if (!isset($_REQUEST['year'])) {
                $_REQUEST['year'] = $today['year'];
            }
            $context['event']['month'] = (int) $_REQUEST['month'];
            $context['event']['year'] = (int) $_REQUEST['year'];
            $context['event']['day'] = isset($_REQUEST['day']) ? $_REQUEST['day'] : ($_REQUEST['month'] == $today['mon'] ? $today['mday'] : 0);
            $context['event']['span'] = isset($_REQUEST['span']) ? $_REQUEST['span'] : 1;
            // Make sure the year and month are in the valid range.
            if ($context['event']['month'] < 1 || $context['event']['month'] > 12) {
                fatal_lang_error('calendar1', false);
            }
            if ($context['event']['year'] < $modSettings['cal_minyear'] || $context['event']['year'] > $modSettings['cal_maxyear']) {
                fatal_lang_error('calendar2', false);
            }
            // Get a list of boards they can post in.
            $boards = boardsAllowedTo('post_new');
            if (empty($boards)) {
                fatal_lang_error('cannot_post_new');
            }
            $request = db_query("\n\t\t\t\tSELECT c.name AS catName, c.ID_CAT, b.ID_BOARD, b.name AS boardName, b.childLevel\n\t\t\t\tFROM {$db_prefix}boards AS b\n\t\t\t\t\tLEFT JOIN {$db_prefix}categories AS c ON (c.ID_CAT = b.ID_CAT)\n\t\t\t\tWHERE {$user_info['query_see_board']}" . (in_array(0, $boards) ? '' : "\n\t\t\t\t\tAND b.ID_BOARD IN (" . implode(', ', $boards) . ")"), __FILE__, __LINE__);
            $context['event']['boards'] = array();
            while ($row = mysql_fetch_assoc($request)) {
                $context['event']['boards'][] = array('id' => $row['ID_BOARD'], 'name' => $row['boardName'], 'childLevel' => $row['childLevel'], 'prefix' => str_repeat('&nbsp;', $row['childLevel'] * 3), 'cat' => array('id' => $row['ID_CAT'], 'name' => $row['catName']));
            }
            mysql_free_result($request);
        }
        // Find the last day of the month.
        $context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year']));
        $context['event']['board'] = !empty($board) ? $board : $modSettings['cal_defaultboard'];
    }
    if (empty($context['post_errors'])) {
        $context['post_errors'] = array();
    }
    // See if any new replies have come along.
    if (empty($_REQUEST['msg']) && !empty($topic)) {
        if (empty($options['no_new_reply_warning']) && isset($_REQUEST['num_replies'])) {
            $newReplies = $context['num_replies'] > $_REQUEST['num_replies'] ? $context['num_replies'] - $_REQUEST['num_replies'] : 0;
            if (!empty($newReplies)) {
                if ($newReplies == 1) {
                    $txt['error_new_reply'] = isset($_GET['num_replies']) ? $txt['error_new_reply_reading'] : $txt['error_new_reply'];
                } else {
                    $txt['error_new_replies'] = sprintf(isset($_GET['num_replies']) ? $txt['error_new_replies_reading'] : $txt['error_new_replies'], $newReplies);
                }
                // If they've come from the display page then we treat the error differently....
                if (isset($_GET['num_replies'])) {
                    $newRepliesError = $newReplies;
                } else {
                    $context['post_error'][$newReplies == 1 ? 'new_reply' : 'new_replies'] = true;
                }
                $modSettings['topicSummaryPosts'] = $newReplies > $modSettings['topicSummaryPosts'] ? max($modSettings['topicSummaryPosts'], 5) : $modSettings['topicSummaryPosts'];
            }
        }
        // Check whether this is a really old post being bumped...
        if (!empty($modSettings['oldTopicDays']) && $lastPostTime + $modSettings['oldTopicDays'] * 86400 < time() && empty($sticky) && !isset($_REQUEST['subject'])) {
            $oldTopicError = true;
        }
    }
    // Get a response prefix (like 'Re:') in the default forum language.
    if (!isset($context['response_prefix']) && !($context['response_prefix'] = cache_get_data('response_prefix'))) {
        if ($language === $user_info['language']) {
            $context['response_prefix'] = $txt['response_prefix'];
        } else {
            loadLanguage('index', $language, false);
            $context['response_prefix'] = $txt['response_prefix'];
            loadLanguage('index');
        }
        cache_put_data('response_prefix', $context['response_prefix'], 600);
    }
    // Previewing, modifying, or posting?
    if (isset($_REQUEST['message']) || !empty($context['post_error'])) {
        // Validate inputs.
        if (empty($context['post_error'])) {
            if ($func['htmltrim']($_REQUEST['subject']) == '') {
                $context['post_error']['no_subject'] = true;
            }
            if ($func['htmltrim']($_REQUEST['message']) == '') {
                $context['post_error']['no_message'] = true;
            }
            if (!empty($modSettings['max_messageLength']) && $func['strlen']($_REQUEST['message']) > $modSettings['max_messageLength']) {
                $context['post_error']['long_message'] = true;
            }
            // Are you... a guest?
            if ($user_info['is_guest']) {
                $_REQUEST['guestname'] = !isset($_REQUEST['guestname']) ? '' : trim($_REQUEST['guestname']);
                $_REQUEST['email'] = !isset($_REQUEST['email']) ? '' : trim($_REQUEST['email']);
                // Validate the name and email.
                if (!isset($_REQUEST['guestname']) || trim(strtr($_REQUEST['guestname'], '_', ' ')) == '') {
                    $context['post_error']['no_name'] = true;
                } elseif ($func['strlen']($_REQUEST['guestname']) > 25) {
                    $context['post_error']['long_name'] = true;
                } else {
                    require_once $sourcedir . '/Subs-Members.php';
                    if (isReservedName(htmlspecialchars($_REQUEST['guestname']), 0, true, false)) {
                        $context['post_error']['bad_name'] = true;
                    }
                }
                if (empty($modSettings['guest_post_no_email'])) {
                    if (!isset($_REQUEST['email']) || $_REQUEST['email'] == '') {
                        $context['post_error']['no_email'] = true;
                    } elseif (preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($_REQUEST['email'])) == 0) {
                        $context['post_error']['bad_email'] = true;
                    }
                }
            }
            // This is self explanatory - got any questions?
            if (isset($_REQUEST['question']) && trim($_REQUEST['question']) == '') {
                $context['post_error']['no_question'] = true;
            }
            // This means they didn't click Post and get an error.
            $really_previewing = true;
        } else {
            if (!isset($_REQUEST['subject'])) {
                $_REQUEST['subject'] = '';
            }
            if (!isset($_REQUEST['message'])) {
                $_REQUEST['message'] = '';
            }
            if (!isset($_REQUEST['icon'])) {
                $_REQUEST['icon'] = 'xx';
            }
            $really_previewing = false;
        }
        // Set up the inputs for the form.
        $form_subject = strtr($func['htmlspecialchars'](stripslashes($_REQUEST['subject'])), array("\r" => '', "\n" => '', "\t" => ''));
        $form_message = $func['htmlspecialchars'](stripslashes($_REQUEST['message']), ENT_QUOTES);
        // Make sure the subject isn't too long - taking into account special characters.
        if ($func['strlen']($form_subject) > 100) {
            $form_subject = $func['substr']($form_subject, 0, 100);
        }
        // Have we inadvertently trimmed off the subject of useful information?
        if ($func['htmltrim']($form_subject) === '') {
            $context['post_error']['no_subject'] = true;
        }
        // Any errors occurred?
        if (!empty($context['post_error'])) {
            loadLanguage('Errors');
            $context['error_type'] = 'minor';
            $context['post_error']['messages'] = array();
            foreach ($context['post_error'] as $post_error => $dummy) {
                if ($post_error == 'messages') {
                    continue;
                }
                $context['post_error']['messages'][] = $txt['error_' . $post_error];
                // If it's not a minor error flag it as such.
                if (!in_array($post_error, array('new_reply', 'new_replies', 'old_topic'))) {
                    $context['error_type'] = 'serious';
                }
            }
        }
        if (isset($_REQUEST['poll'])) {
            $context['question'] = isset($_REQUEST['question']) ? $func['htmlspecialchars'](stripslashes(trim($_REQUEST['question']))) : '';
            $context['choices'] = array();
            $choice_id = 0;
            $_POST['options'] = empty($_POST['options']) ? array() : htmlspecialchars__recursive(stripslashes__recursive($_POST['options']));
            foreach ($_POST['options'] as $option) {
                if (trim($option) == '') {
                    continue;
                }
                $context['choices'][] = array('id' => $choice_id++, 'number' => $choice_id, 'label' => $option, 'is_last' => false);
            }
            if (count($context['choices']) < 2) {
                $context['choices'][] = array('id' => $choice_id++, 'number' => $choice_id, 'label' => '', 'is_last' => false);
                $context['choices'][] = array('id' => $choice_id++, 'number' => $choice_id, 'label' => '', 'is_last' => false);
            }
            $context['choices'][count($context['choices']) - 1]['is_last'] = true;
        }
        // Are you... a guest?
        if ($user_info['is_guest']) {
            $_REQUEST['guestname'] = !isset($_REQUEST['guestname']) ? '' : trim($_REQUEST['guestname']);
            $_REQUEST['email'] = !isset($_REQUEST['email']) ? '' : trim($_REQUEST['email']);
            $_REQUEST['guestname'] = htmlspecialchars($_REQUEST['guestname']);
            $context['name'] = $_REQUEST['guestname'];
            $_REQUEST['email'] = htmlspecialchars($_REQUEST['email']);
            $context['email'] = $_REQUEST['email'];
            $user_info['name'] = $_REQUEST['guestname'];
        }
        // Only show the preview stuff if they hit Preview.
        if ($really_previewing == true || isset($_REQUEST['xml'])) {
            // Set up the preview message and subject and censor them...
            $context['preview_message'] = $form_message;
            preparsecode($form_message, true);
            preparsecode($context['preview_message']);
            // Do all bulletin board code tags, with or without smileys.
            $context['preview_message'] = parse_bbc($context['preview_message'], isset($_REQUEST['ns']) ? 0 : 1);
            if ($form_subject != '') {
                $context['preview_subject'] = $form_subject;
                censorText($context['preview_subject']);
                censorText($context['preview_message']);
            } else {
                $context['preview_subject'] = '<i>' . $txt[24] . '</i>';
            }
            // Protect any CDATA blocks.
            if (isset($_REQUEST['xml'])) {
                $context['preview_message'] = strtr($context['preview_message'], array(']]>' => ']]]]><![CDATA[>'));
            }
        }
        // Set up the checkboxes.
        $context['notify'] = !empty($_REQUEST['notify']);
        $context['use_smileys'] = !isset($_REQUEST['ns']);
        $context['icon'] = isset($_REQUEST['icon']) ? preg_replace('~[\\./\\\\*\':"<>]~', '', $_REQUEST['icon']) : 'xx';
        // Set the destination action for submission.
        $context['destination'] = 'post2;start=' . $_REQUEST['start'] . (isset($_REQUEST['msg']) ? ';msg=' . $_REQUEST['msg'] . ';sesc=' . $sc : '') . (isset($_REQUEST['poll']) ? ';poll' : '');
        $context['submit_label'] = isset($_REQUEST['msg']) ? $txt[10] : $txt[105];
        // Previewing an edit?
        if (isset($_REQUEST['msg'])) {
            if (!empty($modSettings['attachmentEnable'])) {
                $request = db_query("\n\t\t\t\t\tSELECT IFNULL(size, -1) AS filesize, filename, ID_ATTACH\n\t\t\t\t\tFROM {$db_prefix}attachments\n\t\t\t\t\tWHERE ID_MSG = " . (int) $_REQUEST['msg'] . "\n\t\t\t\t\t\t AND attachmentType = 0", __FILE__, __LINE__);
                while ($row = mysql_fetch_assoc($request)) {
                    if ($row['filesize'] <= 0) {
                        continue;
                    }
                    $context['current_attachments'][] = array('name' => $row['filename'], 'id' => $row['ID_ATTACH']);
                }
                mysql_free_result($request);
            }
            // Allow moderators to change names....
            if (allowedTo('moderate_forum') && !empty($topic)) {
                $request = db_query("\n\t\t\t\t\tSELECT ID_MEMBER, posterName, posterEmail\n\t\t\t\t\tFROM {$db_prefix}messages\n\t\t\t\t\tWHERE ID_MSG = " . (int) $_REQUEST['msg'] . "\n\t\t\t\t\t\tAND ID_TOPIC = {$topic}\n\t\t\t\t\tLIMIT 1", __FILE__, __LINE__);
                $row = mysql_fetch_assoc($request);
                mysql_free_result($request);
                if (empty($row['ID_MEMBER'])) {
                    $context['name'] = htmlspecialchars($row['posterName']);
                    $context['email'] = htmlspecialchars($row['posterEmail']);
                }
            }
        }
        // No check is needed, since nothing is really posted.
        checkSubmitOnce('free');
    } elseif (isset($_REQUEST['msg'])) {
        checkSession('get');
        // Get the existing message.
        $request = db_query("\n\t\t\tSELECT\n\t\t\t\tm.ID_MEMBER, m.modifiedTime, m.smileysEnabled, m.body,\n\t\t\t\tm.posterName, m.posterEmail, m.subject, m.icon,\n\t\t\t\tIFNULL(a.size, -1) AS filesize, a.filename, a.ID_ATTACH,\n\t\t\t\tt.ID_MEMBER_STARTED AS ID_MEMBER_POSTER, m.posterTime\n\t\t\tFROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)\n\t\t\t\tLEFT JOIN {$db_prefix}attachments AS a ON (a.ID_MSG = m.ID_MSG AND a.attachmentType = 0)\n\t\t\tWHERE m.ID_MSG = " . (int) $_REQUEST['msg'] . "\n\t\t\t\tAND m.ID_TOPIC = {$topic}\n\t\t\t\tAND t.ID_TOPIC = {$topic}", __FILE__, __LINE__);
        // The message they were trying to edit was most likely deleted.
        // !!! Change this error message?
        if (mysql_num_rows($request) == 0) {
            fatal_lang_error('smf232', false);
        }
        $row = mysql_fetch_assoc($request);
        $attachment_stuff = array($row);
        while ($row2 = mysql_fetch_assoc($request)) {
            $attachment_stuff[] = $row2;
        }
        mysql_free_result($request);
        if ($row['ID_MEMBER'] == $ID_MEMBER && !allowedTo('modify_any')) {
            // Give an extra five minutes over the disable time threshold, so they can type.
            if (!empty($modSettings['edit_disable_time']) && $row['posterTime'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) {
                fatal_lang_error('modify_post_time_passed', false);
            } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('modify_own')) {
                isAllowedTo('modify_replies');
            } else {
                isAllowedTo('modify_own');
            }
        } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('modify_any')) {
            isAllowedTo('modify_replies');
        } else {
            isAllowedTo('modify_any');
        }
        // When was it last modified?
        if (!empty($row['modifiedTime'])) {
            $context['last_modified'] = timeformat($row['modifiedTime']);
        }
        // Get the stuff ready for the form.
        $form_subject = $row['subject'];
        $form_message = un_preparsecode($row['body']);
        censorText($form_message);
        censorText($form_subject);
        // Check the boxes that should be checked.
        $context['use_smileys'] = !empty($row['smileysEnabled']);
        $context['icon'] = $row['icon'];
        // Load up 'em attachments!
        foreach ($attachment_stuff as $attachment) {
            if ($attachment['filesize'] >= 0 && !empty($modSettings['attachmentEnable'])) {
                $context['current_attachments'][] = array('name' => $attachment['filename'], 'id' => $attachment['ID_ATTACH']);
            }
        }
        // Allow moderators to change names....
        if (allowedTo('moderate_forum') && empty($row['ID_MEMBER'])) {
            $context['name'] = htmlspecialchars($row['posterName']);
            $context['email'] = htmlspecialchars($row['posterEmail']);
        }
        // Set the destinaton.
        $context['destination'] = 'post2;start=' . $_REQUEST['start'] . ';msg=' . $_REQUEST['msg'] . ';sesc=' . $sc . (isset($_REQUEST['poll']) ? ';poll' : '');
        $context['submit_label'] = $txt[10];
    } else {
        // By default....
        $context['use_smileys'] = true;
        $context['icon'] = 'xx';
        if ($user_info['is_guest']) {
            $context['name'] = '';
            $context['email'] = '';
        }
        $context['destination'] = 'post2;start=' . $_REQUEST['start'] . (isset($_REQUEST['poll']) ? ';poll' : '');
        $context['submit_label'] = $txt[105];
        // Posting a quoted reply?
        if (!empty($topic) && !empty($_REQUEST['quote'])) {
            checkSession('get');
            // Make sure they _can_ quote this post, and if so get it.
            $request = db_query("\n\t\t\t\tSELECT m.subject, IFNULL(mem.realName, m.posterName) AS posterName, m.posterTime, m.body\n\t\t\t\tFROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)\n\t\t\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)\n\t\t\t\tWHERE m.ID_MSG = " . (int) $_REQUEST['quote'] . "\n\t\t\t\t\tAND b.ID_BOARD = m.ID_BOARD\n\t\t\t\t\tAND {$user_info['query_see_board']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
            if (mysql_num_rows($request) == 0) {
                fatal_lang_error('quoted_post_deleted', false);
            }
            list($form_subject, $mname, $mdate, $form_message) = mysql_fetch_row($request);
            mysql_free_result($request);
            // Add 'Re: ' to the front of the quoted subject.
            if (trim($context['response_prefix']) != '' && $func['strpos']($form_subject, trim($context['response_prefix'])) !== 0) {
                $form_subject = $context['response_prefix'] . $form_subject;
            }
            // Censor the message and subject.
            censorText($form_message);
            censorText($form_subject);
            $form_message = preg_replace('~<br(?: /)?' . '>~i', "\n", $form_message);
            // Remove any nested quotes, if necessary.
            if (!empty($modSettings['removeNestedQuotes'])) {
                $form_message = preg_replace(array('~\\n?\\[quote.*?\\].+?\\[/quote\\]\\n?~is', '~^\\n~', '~\\[/quote\\]~'), '', $form_message);
            }
            // Add a quote string on the front and end.
            $form_message = '[quote author=' . $mname . ' link=topic=' . $topic . '.msg' . (int) $_REQUEST['quote'] . '#msg' . (int) $_REQUEST['quote'] . ' date=' . $mdate . ']' . "\n" . $form_message . "\n" . '[/quote]';
        } elseif (!empty($topic) && empty($_REQUEST['quote'])) {
            // Get the first message's subject.
            $form_subject = $first_subject;
            // Add 'Re: ' to the front of the subject.
            if (trim($context['response_prefix']) != '' && $form_subject != '' && $func['strpos']($form_subject, trim($context['response_prefix'])) !== 0) {
                $form_subject = $context['response_prefix'] . $form_subject;
            }
            // Censor the subject.
            censorText($form_subject);
            $form_message = '';
        } else {
            $form_subject = isset($_GET['subject']) ? $_GET['subject'] : '';
            $form_message = '';
        }
    }
    // !!! This won't work if you're posting an event.
    if (allowedTo('post_attachment')) {
        if (empty($_SESSION['temp_attachments'])) {
            $_SESSION['temp_attachments'] = array();
        }
        // If this isn't a new post, check the current attachments.
        if (isset($_REQUEST['msg'])) {
            $request = db_query("\n\t\t\t\tSELECT COUNT(*), SUM(size)\n\t\t\t\tFROM {$db_prefix}attachments\n\t\t\t\tWHERE ID_MSG = " . (int) $_REQUEST['msg'] . "\n\t\t\t\t\tAND attachmentType = 0", __FILE__, __LINE__);
            list($quantity, $total_size) = mysql_fetch_row($request);
            mysql_free_result($request);
        } else {
            $quantity = 0;
            $total_size = 0;
        }
        $temp_start = 0;
        if (!empty($_SESSION['temp_attachments'])) {
            foreach ($_SESSION['temp_attachments'] as $attachID => $name) {
                $temp_start++;
                if (preg_match('~^post_tmp_' . $ID_MEMBER . '_\\d+$~', $attachID) == 0) {
                    unset($_SESSION['temp_attachments'][$attachID]);
                    continue;
                }
                if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) {
                    $deleted_attachments = true;
                    unset($_SESSION['temp_attachments'][$attachID]);
                    @unlink($modSettings['attachmentUploadDir'] . '/' . $attachID);
                    continue;
                }
                $quantity++;
                $total_size += filesize($modSettings['attachmentUploadDir'] . '/' . $attachID);
                $context['current_attachments'][] = array('name' => getAttachmentFilename($name, false, true), 'id' => $attachID);
            }
        }
        if (!empty($_POST['attach_del'])) {
            $del_temp = array();
            foreach ($_POST['attach_del'] as $i => $dummy) {
                $del_temp[$i] = (int) $dummy;
            }
            foreach ($context['current_attachments'] as $k => $dummy) {
                if (!in_array($dummy['id'], $del_temp)) {
                    $context['current_attachments'][$k]['unchecked'] = true;
                    $deleted_attachments = !isset($deleted_attachments) || is_bool($deleted_attachments) ? 1 : $deleted_attachments + 1;
                    $quantity--;
                }
            }
        }
        if (!empty($_FILES['attachment'])) {
            foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy) {
                if ($_FILES['attachment']['name'][$n] == '') {
                    continue;
                }
                if (!is_uploaded_file($_FILES['attachment']['tmp_name'][$n]) || @ini_get('open_basedir') == '' && !file_exists($_FILES['attachment']['tmp_name'][$n])) {
                    fatal_lang_error('smf124');
                }
                if (!empty($modSettings['attachmentSizeLimit']) && $_FILES['attachment']['size'][$n] > $modSettings['attachmentSizeLimit'] * 1024) {
                    fatal_lang_error('smf122', false, array($modSettings['attachmentSizeLimit']));
                }
                $quantity++;
                if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit']) {
                    fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
                }
                $total_size += $_FILES['attachment']['size'][$n];
                if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) {
                    fatal_lang_error('smf122', false, array($modSettings['attachmentPostLimit']));
                }
                if (!empty($modSettings['attachmentCheckExtensions'])) {
                    if (!in_array(strtolower(substr(strrchr($_FILES['attachment']['name'][$n], '.'), 1)), explode(',', strtolower($modSettings['attachmentExtensions'])))) {
                        fatal_error($_FILES['attachment']['name'][$n] . '.<br />' . $txt['smf123'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
                    }
                }
                if (!empty($modSettings['attachmentDirSizeLimit'])) {
                    // Make sure the directory isn't full.
                    $dirSize = 0;
                    $dir = @opendir($modSettings['attachmentUploadDir']) or fatal_lang_error('smf115b');
                    while ($file = readdir($dir)) {
                        if (substr($file, 0, -1) == '.') {
                            continue;
                        }
                        if (preg_match('~^post_tmp_\\d+_\\d+$~', $file) != 0) {
                            // Temp file is more than 5 hours old!
                            if (filemtime($modSettings['attachmentUploadDir'] . '/' . $file) < time() - 18000) {
                                @unlink($modSettings['attachmentUploadDir'] . '/' . $file);
                            }
                            continue;
                        }
                        $dirSize += filesize($modSettings['attachmentUploadDir'] . '/' . $file);
                    }
                    closedir($dir);
                    // Too big!  Maybe you could zip it or something...
                    if ($_FILES['attachment']['size'][$n] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024) {
                        fatal_lang_error('smf126');
                    }
                }
                if (!is_writable($modSettings['attachmentUploadDir'])) {
                    fatal_lang_error('attachments_no_write');
                }
                $attachID = 'post_tmp_' . $ID_MEMBER . '_' . $temp_start++;
                $_SESSION['temp_attachments'][$attachID] = stripslashes(basename($_FILES['attachment']['name'][$n]));
                $context['current_attachments'][] = array('name' => basename(stripslashes($_FILES['attachment']['name'][$n])), 'id' => $attachID);
                $destName = $modSettings['attachmentUploadDir'] . '/' . $attachID;
                if (!move_uploaded_file($_FILES['attachment']['tmp_name'][$n], $destName)) {
                    fatal_lang_error('smf124');
                }
                @chmod($destName, 0644);
            }
        }
    }
    // If we are coming here to make a reply, and someone has already replied... make a special warning message.
    if (isset($newRepliesError)) {
        $context['post_error']['messages'][] = $newRepliesError == 1 ? $txt['error_new_reply'] : $txt['error_new_replies'];
        $context['error_type'] = 'minor';
    }
    if (isset($oldTopicError)) {
        $context['post_error']['messages'][] = $txt['error_old_topic'];
        $context['error_type'] = 'minor';
    }
    // What are you doing?  Posting a poll, modifying, previewing, new post, or reply...
    if (isset($_REQUEST['poll'])) {
        $context['page_title'] = $txt['smf20'];
    } elseif ($context['make_event']) {
        $context['page_title'] = $context['event']['id'] == -1 ? $txt['calendar23'] : $txt['calendar20'];
    } elseif (isset($_REQUEST['msg'])) {
        $context['page_title'] = $txt[66];
    } elseif (isset($_REQUEST['subject'], $context['preview_subject'])) {
        $context['page_title'] = $txt[507] . ' - ' . strip_tags($context['preview_subject']);
    } elseif (empty($topic)) {
        $context['page_title'] = $txt[33];
    } else {
        $context['page_title'] = $txt[25];
    }
    // Build the link tree.
    if (empty($topic)) {
        $context['linktree'][] = array('name' => '<i>' . $txt[33] . '</i>');
    } else {
        $context['linktree'][] = array('url' => $scripturl . '?topic=' . $topic . '.' . $_REQUEST['start'], 'name' => $form_subject, 'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><b class="nav">' . $context['page_title'] . ' ( </b></span>', 'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><b class="nav"> )</b></span>');
    }
    // If they've unchecked an attachment, they may still want to attach that many more files, but don't allow more than num_allowed_attachments.
    // !!! This won't work if you're posting an event.
    $context['num_allowed_attachments'] = min($modSettings['attachmentNumPerPostLimit'] - count($context['current_attachments']) + (isset($deleted_attachments) ? $deleted_attachments : 0), $modSettings['attachmentNumPerPostLimit']);
    $context['can_post_attachment'] = !empty($modSettings['attachmentEnable']) && $modSettings['attachmentEnable'] == 1 && allowedTo('post_attachment') && $context['num_allowed_attachments'] > 0;
    $context['subject'] = addcslashes($form_subject, '"');
    $context['message'] = str_replace(array('"', '<', '>', '  '), array('&quot;', '&lt;', '&gt;', ' &nbsp;'), $form_message);
    $context['attached'] = '';
    $context['allowed_extensions'] = strtr($modSettings['attachmentExtensions'], array(',' => ', '));
    $context['make_poll'] = isset($_REQUEST['poll']);
    // Message icons - customized icons are off?
    if (empty($modSettings['messageIcons_enable'])) {
        $context['icons'] = array(array('value' => 'xx', 'name' => $txt[281]), array('value' => 'thumbup', 'name' => $txt[282]), array('value' => 'thumbdown', 'name' => $txt[283]), array('value' => 'exclamation', 'name' => $txt[284]), array('value' => 'question', 'name' => $txt[285]), array('value' => 'lamp', 'name' => $txt[286]), array('value' => 'smiley', 'name' => $txt[287]), array('value' => 'angry', 'name' => $txt[288]), array('value' => 'cheesy', 'name' => $txt[289]), array('value' => 'grin', 'name' => $txt[293]), array('value' => 'sad', 'name' => $txt[291]), array('value' => 'wink', 'name' => $txt[292]));
        foreach ($context['icons'] as $k => $dummy) {
            $context['icons'][$k]['url'] = $settings['images_url'] . '/post/' . $dummy['value'] . '.gif';
            $context['icons'][$k]['is_last'] = false;
        }
        $context['icon_url'] = $settings['images_url'] . '/post/' . $context['icon'] . '.gif';
    } else {
        // Regardless of what *should* exist, let's do this properly.
        $stable_icons = array('xx', 'thumbup', 'thumbdown', 'exclamation', 'question', 'lamp', 'smiley', 'angry', 'cheesy', 'grin', 'sad', 'wink', 'moved', 'recycled', 'wireless');
        $context['icon_sources'] = array();
        foreach ($stable_icons as $icon) {
            $context['icon_sources'][$icon] = 'images_url';
        }
        // Array for all icons that need to revert to the default theme!
        $context['javascript_icons'] = array();
        if (($temp = cache_get_data('posting_icons-' . $board, 480)) == null) {
            $request = db_query("\n\t\t\t\tSELECT title, filename\n\t\t\t\tFROM {$db_prefix}message_icons\n\t\t\t\tWHERE ID_BOARD IN (0, {$board})", __FILE__, __LINE__);
            $icon_data = array();
            while ($row = mysql_fetch_assoc($request)) {
                $icon_data[] = $row;
            }
            mysql_free_result($request);
            cache_put_data('posting_icons-' . $board, $icon_data, 480);
        } else {
            $icon_data = $temp;
        }
        $context['icons'] = array();
        foreach ($icon_data as $icon) {
            if (!isset($context['icon_sources'][$icon['filename']])) {
                $context['icon_sources'][$icon['filename']] = file_exists($settings['theme_dir'] . '/images/post/' . $icon['filename'] . '.gif') ? 'images_url' : 'default_images_url';
            }
            // If the icon exists only in the default theme, ensure the javascript popup respects this.
            if ($context['icon_sources'][$icon['filename']] == 'default_images_url') {
                $context['javascript_icons'][] = $icon['filename'];
            }
            $context['icons'][] = array('value' => $icon['filename'], 'name' => $icon['title'], 'url' => $settings[$context['icon_sources'][$icon['filename']]] . '/post/' . $icon['filename'] . '.gif', 'is_last' => false);
        }
        $context['icon_url'] = $settings[isset($context['icon_sources'][$context['icon']]) ? $context['icon_sources'][$context['icon']] : 'images_url'] . '/post/' . $context['icon'] . '.gif';
    }
    if (!empty($context['icons'])) {
        $context['icons'][count($context['icons']) - 1]['is_last'] = true;
    }
    $found = false;
    for ($i = 0, $n = count($context['icons']); $i < $n; $i++) {
        $context['icons'][$i]['selected'] = $context['icon'] == $context['icons'][$i]['value'];
        if ($context['icons'][$i]['selected']) {
            $found = true;
        }
    }
    if (!$found) {
        array_unshift($context['icons'], array('value' => $context['icon'], 'name' => $txt['current_icon'], 'url' => $context['icon_url'], 'is_last' => empty($context['icons']), 'selected' => true));
    }
    if (!empty($topic)) {
        getTopic();
    }
    $context['back_to_topic'] = isset($_REQUEST['goback']) || isset($_REQUEST['msg']) && !isset($_REQUEST['subject']);
    $context['show_additional_options'] = !empty($_POST['additional_options']) || !empty($_SESSION['temp_attachments']) || !empty($deleted_attachments);
    $context['is_new_topic'] = empty($topic);
    $context['is_new_post'] = !isset($_REQUEST['msg']);
    $context['is_first_post'] = $context['is_new_topic'] || isset($_REQUEST['msg']) && $_REQUEST['msg'] == $ID_FIRST_MSG;
    // Register this form in the session variables.
    checkSubmitOnce('register');
    // Finally, load the template.
    if (WIRELESS) {
        $context['sub_template'] = WIRELESS_PROTOCOL . '_post';
    } elseif (!isset($_REQUEST['xml'])) {
        loadTemplate('Post');
    }
}
Example #16
0
function loadAttachmentContext($ID_MSG)
{
    global $attachments, $modSettings, $txt, $scripturl, $topic, $db_prefix, $sourcedir;
    // Set up the attachment info - based on code by Meriadoc.
    $attachmentData = array();
    if (isset($attachments[$ID_MSG]) && !empty($modSettings['attachmentEnable'])) {
        foreach ($attachments[$ID_MSG] as $i => $attachment) {
            $attachmentData[$i] = array('id' => $attachment['ID_ATTACH'], 'name' => htmlspecialchars($attachment['filename']), 'downloads' => $attachment['downloads'], 'size' => round($attachment['filesize'] / 1024, 2) . ' ' . $txt['smf211'], 'byte_size' => $attachment['filesize'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['ID_ATTACH'], 'link' => '<a href="' . $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['ID_ATTACH'] . '">' . htmlspecialchars($attachment['filename']) . '</a>', 'is_image' => !empty($attachment['width']) && !empty($attachment['height']) && !empty($modSettings['attachmentShowImages']));
            if (!$attachmentData[$i]['is_image']) {
                continue;
            }
            $attachmentData[$i]['real_width'] = $attachment['width'];
            $attachmentData[$i]['width'] = $attachment['width'];
            $attachmentData[$i]['real_height'] = $attachment['height'];
            $attachmentData[$i]['height'] = $attachment['height'];
            // Let's see, do we want thumbs?
            if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachment['width'] > $modSettings['attachmentThumbWidth'] || $attachment['height'] > $modSettings['attachmentThumbHeight']) && strlen($attachment['filename']) < 249) {
                // A proper thumb doesn't exist yet? Create one!
                if (empty($attachment['ID_THUMB']) || $attachment['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attachment['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attachment['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attachment['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                    $filename = getAttachmentFilename($attachment['filename'], $attachment['ID_ATTACH']);
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                        // Calculate the size of the created thumbnail.
                        list($attachment['thumb_width'], $attachment['thumb_height']) = @getimagesize($filename . '_thumb');
                        $thumb_size = filesize($filename . '_thumb');
                        $thumb_filename = addslashes($attachment['filename'] . '_thumb');
                        // Add this beauty to the database.
                        db_query("\n\t\t\t\t\t\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t\t\t\t\t\t(ID_MSG, attachmentType, filename, size, width, height)\n\t\t\t\t\t\t\tVALUES ({$ID_MSG}, 3, '{$thumb_filename}', " . (int) $thumb_size . ", " . (int) $attachment['thumb_width'] . ", " . (int) $attachment['thumb_height'] . ")", __FILE__, __LINE__);
                        $attachment['ID_THUMB'] = db_insert_id();
                        if (!empty($attachment['ID_THUMB'])) {
                            db_query("\n\t\t\t\t\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\t\t\t\t\tSET ID_THUMB = {$attachment['ID_THUMB']}\n\t\t\t\t\t\t\t\tWHERE ID_ATTACH = {$attachment['ID_ATTACH']}\n\t\t\t\t\t\t\t\tLIMIT 1", __FILE__, __LINE__);
                            $thumb_realname = getAttachmentFilename($thumb_filename, $attachment['ID_THUMB'], true);
                            rename($filename . '_thumb', $modSettings['attachmentUploadDir'] . '/' . $thumb_realname);
                        }
                    }
                }
                $attachmentData[$i]['width'] = $attachment['thumb_width'];
                $attachmentData[$i]['height'] = $attachment['thumb_height'];
            }
            if (!empty($attachment['ID_THUMB'])) {
                $attachmentData[$i]['thumbnail'] = array('id' => $attachment['ID_THUMB'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['ID_THUMB'] . ';image');
            }
            $attachmentData[$i]['thumbnail']['has_thumb'] = !empty($attachment['ID_THUMB']);
            // If thumbnails are disabled, check the maximum size of the image.
            if (!$attachmentData[$i]['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attachment['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachment['height'] > $modSettings['max_image_height'])) {
                if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attachment['height'] * $modSettings['max_image_width'] / $attachment['width'] <= $modSettings['max_image_height'])) {
                    $attachmentData[$i]['width'] = $modSettings['max_image_width'];
                    $attachmentData[$i]['height'] = floor($attachment['height'] * $modSettings['max_image_width'] / $attachment['width']);
                } elseif (!empty($modSettings['max_image_width'])) {
                    $attachmentData[$i]['width'] = floor($attachment['width'] * $modSettings['max_image_height'] / $attachment['height']);
                    $attachmentData[$i]['height'] = $modSettings['max_image_height'];
                }
            } elseif ($attachmentData[$i]['thumbnail']['has_thumb']) {
                // If the image is too large to show inline, make it a popup.
                if (!empty($modSettings['max_image_width']) && $attachmentData[$i]['real_width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachmentData[$i]['real_height'] > $modSettings['max_image_height']) {
                    $attachmentData[$i]['thumbnail']['javascript'] = "return reqWin('" . $attachmentData[$i]['href'] . ";image', " . ($attachment['width'] + 20) . ', ' . ($attachment['height'] + 20) . ', true);';
                } else {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return expandThumb(' . $attachment['ID_ATTACH'] . ');';
                }
            }
            if (!$attachmentData[$i]['thumbnail']['has_thumb']) {
                $attachmentData[$i]['downloads']++;
            }
        }
    }
    return $attachmentData;
}
Example #17
0
function tpattach()
{
    global $txt, $modSettings, $context, $smcFunc;
    // Some defaults that we need.
    $context['character_set'] = empty($modSettings['global_character_set']) ? empty($txt['lang_character_set']) ? 'ISO-8859-1' : $txt['lang_character_set'] : $modSettings['global_character_set'];
    $context['utf8'] = $context['character_set'] === 'UTF-8' && (strpos(strtolower(PHP_OS), 'win') === false || @version_compare(PHP_VERSION, '4.2.3') != -1);
    $context['no_last_modified'] = true;
    // Make sure some attachment was requested!
    if (!isset($_REQUEST['attach']) && !isset($_REQUEST['id'])) {
        fatal_lang_error('no_access', false);
    }
    $_REQUEST['attach'] = isset($_REQUEST['attach']) ? (int) $_REQUEST['attach'] : (int) $_REQUEST['id'];
    if (isset($_REQUEST['type']) && $_REQUEST['type'] == 'avatar') {
        $request = $smcFunc['db_query']('', '
			SELECT id_folder, filename, file_hash, fileext, id_attach, attachment_type, mime_type, approved
			FROM {db_prefix}attachments
			WHERE id_attach = {int:id_attach}
				AND id_member > {int:blank_id_member}
			LIMIT 1', array('id_attach' => $_REQUEST['attach'], 'blank_id_member' => 0));
        $_REQUEST['image'] = true;
    } else {
        $request = $smcFunc['db_query']('', '
			SELECT a.id_folder, a.filename, a.file_hash, a.fileext, a.id_attach, 
				a.attachment_type, a.mime_type, a.approved
			FROM {db_prefix}attachments AS a
			WHERE a.id_attach = {int:attach}
			LIMIT 1', array('attach' => $_REQUEST['attach']));
    }
    if ($smcFunc['db_num_rows']($request) == 0) {
        fatal_lang_error('no_access', false);
    }
    list($id_folder, $real_filename, $file_hash, $file_ext, $id_attach, $attachment_type, $mime_type, $is_approved) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    $filename = getAttachmentFilename($real_filename, $_REQUEST['attach'], $id_folder, false, $file_hash);
    // This is done to clear any output that was made before now. (would use ob_clean(), but that's PHP 4.2.0+...)
    ob_end_clean();
    if (!empty($modSettings['enableCompressedOutput']) && @version_compare(PHP_VERSION, '4.2.0') >= 0 && @filesize($filename) <= 4194304 && in_array($file_ext, array('txt', 'html', 'htm', 'js', 'doc', 'pdf', 'docx', 'rtf', 'css', 'php', 'log', 'xml', 'sql', 'c', 'java'))) {
        @ob_start('ob_gzhandler');
    } else {
        ob_start();
        header('Content-Encoding: none');
    }
    // No point in a nicer message, because this is supposed to be an attachment anyway...
    if (!file_exists($filename)) {
        loadLanguage('Errors');
        header('HTTP/1.0 404 ' . $txt['attachment_not_found']);
        header('Content-Type: text/plain; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']));
        // We need to die like this *before* we send any anti-caching headers as below.
        die('404 - ' . $txt['attachment_not_found']);
    }
    // If it hasn't been modified since the last time this attachement was retrieved, there's no need to display it again.
    if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
        list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
        if (strtotime($modified_since) >= filemtime($filename)) {
            ob_end_clean();
            // Answer the question - no, it hasn't been modified ;).
            header('HTTP/1.1 304 Not Modified');
            exit;
        }
    }
    // Check whether the ETag was sent back, and cache based on that...
    $eTag = '"' . substr($_REQUEST['attach'] . $real_filename . filemtime($filename), 0, 64) . '"';
    if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false) {
        ob_end_clean();
        header('HTTP/1.1 304 Not Modified');
        exit;
    }
    // Send the attachment headers.
    header('Pragma: ');
    if (!$context['browser']['is_gecko']) {
        header('Content-Transfer-Encoding: binary');
    }
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($filename)) . ' GMT');
    header('Accept-Ranges: bytes');
    header('Set-Cookie:');
    header('Connection: close');
    header('ETag: ' . $eTag);
    // IE 6 just doesn't play nice. As dirty as this seems, it works.
    if ($context['browser']['is_ie6'] && isset($_REQUEST['image'])) {
        unset($_REQUEST['image']);
    } elseif (filesize($filename) != 0) {
        $size = @getimagesize($filename);
        if (!empty($size)) {
            // What headers are valid?
            $validTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'x-ms-bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
            // Do we have a mime type we can simpy use?
            if (!empty($size['mime']) && !in_array($size[2], array(4, 13))) {
                header('Content-Type: ' . strtr($size['mime'], array('image/bmp' => 'image/x-ms-bmp')));
            } elseif (isset($validTypes[$size[2]])) {
                header('Content-Type: image/' . $validTypes[$size[2]]);
            } elseif (isset($_REQUEST['image'])) {
                unset($_REQUEST['image']);
            }
        } elseif (isset($_REQUEST['image'])) {
            unset($_REQUEST['image']);
        }
    }
    header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename="' . $real_filename . '"');
    if (!isset($_REQUEST['image'])) {
        header('Content-Type: application/octet-stream');
    }
    // If this has an "image extension" - but isn't actually an image - then ensure it isn't cached cause of silly IE.
    if (!isset($_REQUEST['image']) && in_array($file_ext, array('gif', 'jpg', 'bmp', 'png', 'jpeg', 'tiff'))) {
        header('Cache-Control: no-cache');
    } else {
        header('Cache-Control: max-age=' . 525600 * 60 . ', private');
    }
    if (empty($modSettings['enableCompressedOutput']) || filesize($filename) > 4194304) {
        header('Content-Length: ' . filesize($filename));
    }
    // Try to buy some time...
    @set_time_limit(0);
    // Since we don't do output compression for files this large...
    if (filesize($filename) > 4194304) {
        // Forcibly end any output buffering going on.
        if (function_exists('ob_get_level')) {
            while (@ob_get_level() > 0) {
                @ob_end_clean();
            }
        } else {
            @ob_end_clean();
            @ob_end_clean();
            @ob_end_clean();
        }
        $fp = fopen($filename, 'rb');
        while (!feof($fp)) {
            if (isset($callback)) {
                echo $callback(fread($fp, 8192));
            } else {
                echo fread($fp, 8192);
            }
            flush();
        }
        fclose($fp);
    } elseif (isset($callback) || @readfile($filename) == null) {
        echo isset($callback) ? $callback(file_get_contents($filename)) : file_get_contents($filename);
    }
    obExit(false);
}
Example #18
0
function CopyAttachment($row, $attach_dir)
{
    global $modSettings;
    // Original attachment link
    $row['original_file_link'] = getAttachmentFilename($row['filename'], $row['original_id'], $row['folder']);
    // New Attachment
    // Ay caramba!, we can't have two files with exact same name, so we need a new filename
    if (empty($modSettings['attachmentEncryptFilenames'])) {
        $row['filename'] = GenerateUniqueFilename($attach_dir . '/', $row['filename']);
        // Couldn't generate a new filename so return
        if (empty($row['filename'])) {
            return 0;
        } else {
            // Destination attachment link
            $row['file_link'] = $attach_dir . '/' . $row['filename'];
        }
    } else {
        // Destination attachment link
        $row['file_link'] = $attach_dir . '/' . getAttachmentFilename($row['filename'], $row['file_id'], $attach_dir, true);
    }
    // Now copy the file
    if (copy($row['original_file_link'], $row['file_link']) !== false) {
        // Attempt to chmod it.
        @chmod($row['file_link'], 0644);
        //Success
        // But what about the thumbnail
        if (!empty($row['thumb_id'])) {
            // Original attachment link
            $row['original_thumb_link'] = getAttachmentFilename($row['thumbname'], $row['original_thumb_id'], $row['thumbfolder']);
            if (empty($modSettings['attachmentEncryptFilenames'])) {
                $row['thumbname'] = $row['filename'] . '_thumb';
                $row['thumb_link'] = $attach_dir . '/' . $row['thumbname'];
            } else {
                $row['thumb_link'] = $attach_dir . '/' . getAttachmentFilename($row['thumbname'], $row['thumb_id'], $attach_dir, true);
            }
            // If it fails to copy the thumb, send back 0
            if (copy($row['original_thumb_link'], $row['thumb_link']) !== false) {
                // Attempt to chmod it.
                @chmod($row['thumb_link'], 0644);
            } else {
                return 0;
            }
        }
        //send back the new filename to store in the db
        return $row['filename'];
    }
    // If haven't exited, we must have failed
    return 0;
}
Example #19
0
function removeAttachments($condition, $query_type = '', $return_affected_messages = false, $autoThumbRemoval = true)
{
    global $modSettings, $smcFunc;
    //!!! This might need more work!
    $new_condition = array();
    $query_parameter = array('thumb_attachment_type' => 3);
    if (is_array($condition)) {
        foreach ($condition as $real_type => $restriction) {
            // Doing a NOT?
            $is_not = substr($real_type, 0, 4) == 'not_';
            $type = $is_not ? substr($real_type, 4) : $real_type;
            if (in_array($type, array('id_member', 'id_attach', 'id_msg'))) {
                $new_condition[] = 'a.' . $type . ($is_not ? ' NOT' : '') . ' IN (' . (is_array($restriction) ? '{array_int:' . $real_type . '}' : '{int:' . $real_type . '}') . ')';
            } elseif ($type == 'attachment_type') {
                $new_condition[] = 'a.attachment_type = {int:' . $real_type . '}';
            } elseif ($type == 'poster_time') {
                $new_condition[] = 'm.poster_time < {int:' . $real_type . '}';
            } elseif ($type == 'last_login') {
                $new_condition[] = 'mem.last_login < {int:' . $real_type . '}';
            } elseif ($type == 'size') {
                $new_condition[] = 'a.size > {int:' . $real_type . '}';
            } elseif ($type == 'id_topic') {
                $new_condition[] = 'm.id_topic IN (' . (is_array($restriction) ? '{array_int:' . $real_type . '}' : '{int:' . $real_type . '}') . ')';
            }
            // Add the parameter!
            $query_parameter[$real_type] = $restriction;
        }
        $condition = implode(' AND ', $new_condition);
    }
    // Delete it only if it exists...
    $msgs = array();
    $attach = array();
    $parents = array();
    // Get all the attachment names and id_msg's.
    $request = smf_db_query('
		SELECT
			a.id_folder, a.filename, a.file_hash, a.attachment_type, a.id_attach, a.id_member' . ($query_type == 'messages' ? ', m.id_msg' : ', a.id_msg') . ',
			thumb.id_folder AS thumb_folder, IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.filename AS thumb_filename, thumb.file_hash AS thumb_file_hash, thumb_parent.id_attach AS id_parent
			FROM {db_prefix}attachments AS a' . ($query_type == 'members' ? '
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member)' : ($query_type == 'messages' ? '
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)' : '')) . '
			LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)
			LEFT JOIN {db_prefix}attachments AS thumb_parent ON (thumb.attachment_type = {int:thumb_attachment_type} AND thumb_parent.id_thumb = a.id_attach)
			WHERE ' . $condition, $query_parameter);
    while ($row = mysql_fetch_assoc($request)) {
        // Figure out the "encrypted" filename and unlink it ;).
        if ($row['attachment_type'] == 1) {
            @unlink($modSettings['custom_avatar_dir'] . '/' . $row['filename']);
        } else {
            $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
            @unlink($filename);
            // If this was a thumb, the parent attachment should know about it.
            if (!empty($row['id_parent'])) {
                $parents[] = $row['id_parent'];
            }
            // If this attachments has a thumb, remove it as well.
            if (!empty($row['id_thumb']) && $autoThumbRemoval) {
                $thumb_filename = getAttachmentFilename($row['thumb_filename'], $row['id_thumb'], $row['thumb_folder'], false, $row['thumb_file_hash']);
                @unlink($thumb_filename);
                $attach[] = $row['id_thumb'];
            }
        }
        // Make a list.
        if ($return_affected_messages && empty($row['attachment_type'])) {
            $msgs[] = $row['id_msg'];
        }
        $attach[] = $row['id_attach'];
    }
    mysql_free_result($request);
    // Removed attachments don't have to be updated anymore.
    $parents = array_diff($parents, $attach);
    if (!empty($parents)) {
        smf_db_query('
			UPDATE {db_prefix}attachments
			SET id_thumb = {int:no_thumb}
			WHERE id_attach IN ({array_int:parent_attachments})', array('parent_attachments' => $parents, 'no_thumb' => 0));
    }
    if (!empty($attach)) {
        smf_db_query('
			DELETE FROM {db_prefix}attachments
			WHERE id_attach IN ({array_int:attachment_list})', array('attachment_list' => $attach));
    }
    if ($return_affected_messages) {
        return array_unique($msgs);
    }
}
Example #20
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('&amp;' => '&'));
        $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 loadAttachmentContext($id_msg)
{
    global $attachments, $modSettings, $txt, $scripturl, $topic, $sourcedir, $smcFunc;
    // Set up the attachment info - based on code by Meriadoc.
    $attachmentData = array();
    $have_unapproved = false;
    if (isset($attachments[$id_msg]) && !empty($modSettings['attachmentEnable'])) {
        foreach ($attachments[$id_msg] as $i => $attachment) {
            $attachmentData[$i] = array('id' => $attachment['id_attach'], 'name' => preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attachment['filename'])), 'downloads' => $attachment['downloads'], 'size' => round($attachment['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], 'byte_size' => $attachment['filesize'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'], 'link' => '<a href="' . $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'] . '">' . htmlspecialchars($attachment['filename']) . '</a>', 'is_image' => !empty($attachment['width']) && !empty($attachment['height']) && !empty($modSettings['attachmentShowImages']), 'is_approved' => $attachment['approved']);
            // If something is unapproved we'll note it so we can sort them.
            if (!$attachment['approved']) {
                $have_unapproved = true;
            }
            if (!$attachmentData[$i]['is_image']) {
                continue;
            }
            $attachmentData[$i]['real_width'] = $attachment['width'];
            $attachmentData[$i]['width'] = $attachment['width'];
            $attachmentData[$i]['real_height'] = $attachment['height'];
            $attachmentData[$i]['height'] = $attachment['height'];
            // Let's see, do we want thumbs?
            if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachment['width'] > $modSettings['attachmentThumbWidth'] || $attachment['height'] > $modSettings['attachmentThumbHeight']) && strlen($attachment['filename']) < 249) {
                // A proper thumb doesn't exist yet? Create one!
                if (empty($attachment['id_thumb']) || $attachment['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attachment['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attachment['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attachment['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                    $filename = getAttachmentFilename($attachment['filename'], $attachment['id_attach'], $attachment['id_folder']);
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                        // So what folder are we putting this image in?
                        if (!empty($modSettings['currentAttachmentUploadDir'])) {
                            if (!is_array($modSettings['attachmentUploadDir'])) {
                                $modSettings['attachmentUploadDir'] = @unserialize($modSettings['attachmentUploadDir']);
                            }
                            $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
                            $id_folder_thumb = $modSettings['currentAttachmentUploadDir'];
                        } else {
                            $path = $modSettings['attachmentUploadDir'];
                            $id_folder_thumb = 1;
                        }
                        // Calculate the size of the created thumbnail.
                        $size = @getimagesize($filename . '_thumb');
                        list($attachment['thumb_width'], $attachment['thumb_height']) = $size;
                        $thumb_size = filesize($filename . '_thumb');
                        // 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');
                        // What about the extension?
                        $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
                        // Figure out the mime type.
                        if (!empty($size['mime'])) {
                            $thumb_mime = $size['mime'];
                        } else {
                            $thumb_mime = 'image/' . $thumb_ext;
                        }
                        $thumb_filename = $attachment['filename'] . '_thumb';
                        $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true);
                        // Add this beauty to the database.
                        $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, $id_msg, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attachment['thumb_width'], (int) $attachment['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
                        $old_id_thumb = $attachment['id_thumb'];
                        $attachment['id_thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
                        if (!empty($attachment['id_thumb'])) {
                            $smcFunc['db_query']('', '
								UPDATE {db_prefix}attachments
								SET id_thumb = {int:id_thumb}
								WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachment['id_thumb'], 'id_attach' => $attachment['id_attach']));
                            $thumb_realname = getAttachmentFilename($thumb_filename, $attachment['id_thumb'], $id_folder_thumb, false, $thumb_hash);
                            rename($filename . '_thumb', $thumb_realname);
                            // Do we need to remove an old thumbnail?
                            if (!empty($old_id_thumb)) {
                                require_once $sourcedir . '/ManageAttachments.php';
                                removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
                            }
                        }
                    }
                }
                // Only adjust dimensions on successful thumbnail creation.
                if (!empty($attachment['thumb_width']) && !empty($attachment['thumb_height'])) {
                    $attachmentData[$i]['width'] = $attachment['thumb_width'];
                    $attachmentData[$i]['height'] = $attachment['thumb_height'];
                }
            }
            if (!empty($attachment['id_thumb'])) {
                $attachmentData[$i]['thumbnail'] = array('id' => $attachment['id_thumb'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_thumb'] . ';image');
            }
            $attachmentData[$i]['thumbnail']['has_thumb'] = !empty($attachment['id_thumb']);
            // If thumbnails are disabled, check the maximum size of the image.
            if (!$attachmentData[$i]['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attachment['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachment['height'] > $modSettings['max_image_height'])) {
                if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attachment['height'] * $modSettings['max_image_width'] / $attachment['width'] <= $modSettings['max_image_height'])) {
                    $attachmentData[$i]['width'] = $modSettings['max_image_width'];
                    $attachmentData[$i]['height'] = floor($attachment['height'] * $modSettings['max_image_width'] / $attachment['width']);
                } elseif (!empty($modSettings['max_image_width'])) {
                    $attachmentData[$i]['width'] = floor($attachment['width'] * $modSettings['max_image_height'] / $attachment['height']);
                    $attachmentData[$i]['height'] = $modSettings['max_image_height'];
                }
            } elseif ($attachmentData[$i]['thumbnail']['has_thumb']) {
                // If the image is too large to show inline, make it a popup.
                if (!empty($modSettings['max_image_width']) && $attachmentData[$i]['real_width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachmentData[$i]['real_height'] > $modSettings['max_image_height']) {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return reqWin(\'' . $attachmentData[$i]['href'] . ';image\', ' . ($attachment['width'] + 20) . ', ' . ($attachment['height'] + 20) . ', true);';
                } else {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return expandThumb(' . $attachment['id_attach'] . ');';
                }
            }
            if (!$attachmentData[$i]['thumbnail']['has_thumb']) {
                $attachmentData[$i]['downloads']++;
            }
        }
    }
    // Do we need to instigate a sort?
    if ($have_unapproved) {
        usort($attachmentData, 'approved_attach_sort');
    }
    return $attachmentData;
}
Example #22
0
 /**
  * Downloads an attachment or avatar, and increments the download count.
  * It requires the view_attachments permission. (not for avatars!)
  * It disables the session parser, and clears any previous output.
  * It is accessed via the query string ?action=dlattach.
  * Views to attachments and avatars do not increase hits and are not logged in the "Who's Online" log.
  */
 public function action_dlattach()
 {
     global $txt, $modSettings, $user_info, $context, $topic;
     // Some defaults that we need.
     $context['no_last_modified'] = true;
     // Make sure some attachment was requested!
     if (!isset($_REQUEST['attach']) && !isset($_REQUEST['id'])) {
         fatal_lang_error('no_access', false);
     }
     // We need to do some work on attachments and avatars.
     require_once SUBSDIR . '/Attachments.subs.php';
     $id_attach = isset($_REQUEST['attach']) ? (int) $_REQUEST['attach'] : (int) $_REQUEST['id'];
     if (isset($_REQUEST['type']) && $_REQUEST['type'] == 'avatar') {
         $attachment = getAvatar($id_attach);
         $is_avatar = true;
         $_REQUEST['image'] = true;
     } else {
         isAllowedTo('view_attachments');
         $attachment = getAttachmentFromTopic($id_attach, $topic);
     }
     if (empty($attachment)) {
         fatal_lang_error('no_access', false);
     }
     list($id_folder, $real_filename, $file_hash, $file_ext, $id_attach, $attachment_type, $mime_type, $is_approved, $id_member) = $attachment;
     // If it isn't yet approved, do they have permission to view it?
     if (!$is_approved && ($id_member == 0 || $user_info['id'] != $id_member) && ($attachment_type == 0 || $attachment_type == 3)) {
         isAllowedTo('approve_posts');
     }
     // Update the download counter (unless it's a thumbnail or an avatar).
     if (empty($is_avatar) || $attachment_type != 3) {
         increaseDownloadCounter($id_attach);
     }
     $filename = getAttachmentFilename($real_filename, $id_attach, $id_folder, false, $file_hash);
     // This is done to clear any output that was made before now.
     while (ob_get_level() > 0) {
         @ob_end_clean();
     }
     if (!empty($modSettings['enableCompressedOutput']) && @filesize($filename) <= 4194304 && in_array($file_ext, array('txt', 'html', 'htm', 'js', 'doc', 'docx', 'rtf', 'css', 'php', 'log', 'xml', 'sql', 'c', 'java'))) {
         ob_start('ob_gzhandler');
     } else {
         ob_start();
         header('Content-Encoding: none');
     }
     // No point in a nicer message, because this is supposed to be an attachment anyway...
     if (!file_exists($filename)) {
         loadLanguage('Errors');
         header((preg_match('~HTTP/1\\.[01]~i', $_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0') . ' 404 Not Found');
         header('Content-Type: text/plain; charset=UTF-8');
         // We need to die like this *before* we send any anti-caching headers as below.
         die('404 - ' . $txt['attachment_not_found']);
     }
     // If it hasn't been modified since the last time this attachment was retrieved, there's no need to display it again.
     if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
         list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
         if (strtotime($modified_since) >= filemtime($filename)) {
             @ob_end_clean();
             // Answer the question - no, it hasn't been modified ;).
             header('HTTP/1.1 304 Not Modified');
             exit;
         }
     }
     // Check whether the ETag was sent back, and cache based on that...
     $eTag = '"' . substr($id_attach . $real_filename . filemtime($filename), 0, 64) . '"';
     if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false) {
         @ob_end_clean();
         header('HTTP/1.1 304 Not Modified');
         exit;
     }
     // Send the attachment headers.
     header('Pragma: ');
     if (!isBrowser('gecko')) {
         header('Content-Transfer-Encoding: binary');
     }
     header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
     header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($filename)) . ' GMT');
     header('Accept-Ranges: bytes');
     header('Connection: close');
     header('ETag: ' . $eTag);
     // Make sure the mime type warrants an inline display.
     if (isset($_REQUEST['image']) && !empty($mime_type) && strpos($mime_type, 'image/') !== 0) {
         unset($_REQUEST['image']);
     } elseif (!empty($mime_type) && (isset($_REQUEST['image']) || !in_array($file_ext, array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff')))) {
         header('Content-Type: ' . strtr($mime_type, array('image/bmp' => 'image/x-ms-bmp')));
     } else {
         header('Content-Type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream'));
         if (isset($_REQUEST['image'])) {
             unset($_REQUEST['image']);
         }
     }
     $disposition = !isset($_REQUEST['image']) ? 'attachment' : 'inline';
     // Different browsers like different standards...
     if (isBrowser('firefox')) {
         header('Content-Disposition: ' . $disposition . '; filename*=UTF-8\'\'' . rawurlencode(preg_replace_callback('~&#(\\d{3,8});~', 'fixchar__callback', $real_filename)));
     } elseif (isBrowser('opera')) {
         header('Content-Disposition: ' . $disposition . '; filename="' . preg_replace_callback('~&#(\\d{3,8});~', 'fixchar__callback', $real_filename) . '"');
     } elseif (isBrowser('ie')) {
         header('Content-Disposition: ' . $disposition . '; filename="' . urlencode(preg_replace_callback('~&#(\\d{3,8});~', 'fixchar__callback', $real_filename)) . '"');
     } else {
         header('Content-Disposition: ' . $disposition . '; filename="' . $real_filename . '"');
     }
     // If this has an "image extension" - but isn't actually an image - then ensure it isn't cached cause of silly IE.
     if (!isset($_REQUEST['image']) && in_array($file_ext, array('gif', 'jpg', 'bmp', 'png', 'jpeg', 'tiff'))) {
         header('Cache-Control: no-cache');
     } else {
         header('Cache-Control: max-age=' . 525600 * 60 . ', private');
     }
     if (empty($modSettings['enableCompressedOutput']) || filesize($filename) > 4194304) {
         header('Content-Length: ' . filesize($filename));
     }
     // Try to buy some time...
     @set_time_limit(600);
     // Recode line endings for text files, if enabled.
     if (!empty($modSettings['attachmentRecodeLineEndings']) && !isset($_REQUEST['image']) && in_array($file_ext, array('txt', 'css', 'htm', 'html', 'php', 'xml'))) {
         $req = request();
         if (strpos($req->user_agent(), 'Windows') !== false) {
             $callback = create_function('$buffer', 'return preg_replace(\'~[\\r]?\\n~\', "\\r\\n", $buffer);');
         } elseif (strpos($req->user_agent(), 'Mac') !== false) {
             $callback = create_function('$buffer', 'return preg_replace(\'~[\\r]?\\n~\', "\\r", $buffer);');
         } else {
             $callback = create_function('$buffer', 'return preg_replace(\'~[\\r]?\\n~\', "\\n", $buffer);');
         }
     }
     // Since we don't do output compression for files this large...
     if (filesize($filename) > 4194304) {
         // Forcibly end any output buffering going on.
         while (ob_get_level() > 0) {
             @ob_end_clean();
         }
         $fp = fopen($filename, 'rb');
         while (!feof($fp)) {
             if (isset($callback)) {
                 echo $callback(fread($fp, 8192));
             } else {
                 echo fread($fp, 8192);
             }
             flush();
         }
         fclose($fp);
     } elseif (isset($callback) || @readfile($filename) === null) {
         echo isset($callback) ? $callback(file_get_contents($filename)) : file_get_contents($filename);
     }
     obExit(false);
 }