News:

Bored?  Looking to kill some time?  Want to chat with other SMF users?  Join us in IRC chat or Discord

Main Menu

[SMF 2.0.x] How to make image attachments visible to guests?

Started by dodos26, November 27, 2022, 07:57:09 AM

Previous topic - Next topic

dodos26

How to make image attachments visible to guests?
A topic to publish my solution, maybe I'll create a modification soon.

Open Sources/display.php and:

# STEP 1
Code (find) Select
        // Fetch attachments.
        if (!empty($modSettings['attachmentEnable']) && allowedTo('view_attachments'))
        {
            $request = $smcFunc['db_query']('', '
                SELECT
                    a.id_attach, a.id_folder, a.id_msg, a.filename, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved,
                    a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ',
                    IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . '
                FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : '
                    LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . '
                WHERE a.id_msg IN ({array_int:message_list})
                    AND a.attachment_type = {int:attachment_type}',
                array(
                    'message_list' => $messages,
                    'attachment_type' => 0,
                    'is_approved' => 1,
                )
            );
            $temp = array();
            while ($row = $smcFunc['db_fetch_assoc']($request))
            {
                if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id']))
                    continue;

                $temp[$row['id_attach']] = $row;

                if (!isset($attachments[$row['id_msg']]))
                    $attachments[$row['id_msg']] = array();
            }
            $smcFunc['db_free_result']($request);

            // This is better than sorting it with the query...
            ksort($temp);

            foreach ($temp as $row)
                $attachments[$row['id_msg']][] = $row;
        }

This snippet will only load image attachments for guest. According to tests, this allows you to display the image from the attachment in the post if it is placed. However, I recommend that you also use step two.
Code (replace) Select
        // Fetch attachments.
        if (!empty($modSettings['attachmentEnable']))
        {
            if (allowedTo('view_attachments'))
            {
                $request = $smcFunc['db_query']('', '
                    SELECT
                        a.id_attach, a.id_folder, a.id_msg, a.filename, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved,
                        a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ',
                        IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . '
                    FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : '
                        LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . '
                    WHERE a.id_msg IN ({array_int:message_list})
                        AND a.attachment_type = {int:attachment_type}',
                    array(
                        'message_list' => $messages,
                        'attachment_type' => 0,
                        'is_approved' => 1,
                    )
                );
                $temp = array();
                while ($row = $smcFunc['db_fetch_assoc']($request))
                {
                    if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id']))
                        continue;

                    $temp[$row['id_attach']] = $row;

                    if (!isset($attachments[$row['id_msg']]))
                        $attachments[$row['id_msg']] = array();
                }
                $smcFunc['db_free_result']($request);

                // This is better than sorting it with the query...
                ksort($temp);

                foreach ($temp as $row)
                    $attachments[$row['id_msg']][] = $row;
            }
            else
            {
                $request = $smcFunc['db_query']('', '
                    SELECT
                        a.id_attach, a.id_folder, a.id_msg, a.filename, a.fileext, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved,
                        a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ',
                        IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . '
                    FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : '
                        LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . '
                    WHERE a.id_msg IN ({array_int:message_list})
                        AND a.fileext IN ("jpg", "gif", "jpeg", "x-ms-bmp", "png", "psd", "tiff", "iff")
                        AND a.attachment_type = {int:attachment_type}',
                    array(
                        'message_list' => $messages,
                        'attachment_type' => 0,
                        'is_approved' => 1,
                    )
                );
                $temp = array();
                while ($row = $smcFunc['db_fetch_assoc']($request))
                {
                    if (!$row['approved'] && $modSettings['postmod_active'] && !allowedTo('approve_posts') && (!isset($all_posters[$row['id_msg']]) || $all_posters[$row['id_msg']] != $user_info['id']))
                        continue;

                    $temp[$row['id_attach']] = $row;

                    if (!isset($attachments[$row['id_msg']]))
                        $attachments[$row['id_msg']] = array();
                }
                $smcFunc['db_free_result']($request);

                // This is better than sorting it with the query...
                ksort($temp);

                foreach ($temp as $row)
                    $attachments[$row['id_msg']][] = $row;
            }
        }

# STEP 2
Code (find) Select
        // This checks only the current board for $board/$topic's permissions.
        isAllowedTo('view_attachments');

        // Make sure this attachment is on this board.
        // NOTE: We must verify that $topic is the attachment's topic, or else the permission check above is broken.
        $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, m.id_member
            FROM {db_prefix}attachments AS a
                INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
                INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
            WHERE a.id_attach = {int:attach}
            LIMIT 1',
            array(
                'attach' => $_REQUEST['attach'],
                'current_topic' => $topic,
            )
        );
    }
    if ($smcFunc['db_num_rows']($request) == 0)
        fatal_lang_error('no_access', false);

This snippet will display the attachment and allow you to download it.
Code (replace) Select
        // Make sure this attachment is on this board.
        // NOTE: We must verify that $topic is the attachment's topic, or else the permission check above is broken.
        if (allowedTo('view_attachments'))
        {
            $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, m.id_member
                FROM {db_prefix}attachments AS a
                    INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
                    INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
                WHERE a.id_attach = {int:attach}
                LIMIT 1',
                array(
                    'attach' => $_REQUEST['attach'],
                    'current_topic' => $topic,
                )
            );
        }
        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, m.id_member
                FROM {db_prefix}attachments AS a
                    INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
                    INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
                WHERE a.id_attach = {int:attach}
                    AND a.fileext IN ("jpg", "gif", "jpeg", "x-ms-bmp", "png", "psd", "tiff", "iff")
                LIMIT 1',
                array(
                    'attach' => $_REQUEST['attach'],
                    'current_topic' => $topic,
                )
            );
        }
    }
    if ($smcFunc['db_num_rows']($request) == 0)
    {
        // This checks only the current board for $board/$topic's permissions.
        isAllowedTo('view_attachments');
        fatal_lang_error('no_access', false);
    }

Steve

To the coders, will his tip work the way it's written for what he wants it to do (allow only image attachments to guests)?
DO NOT pm me for support!

Diego Andrés

#2
Yes it works. Just needs to add a note somewhere indicating that this tip is for SMF 2.0.x.
Also, you don't need to replace and duplicate that much code, just move the condition to the query, as a ternary.
#1
// Fetch attachments.
if (!empty($modSettings['attachmentEnable']))
{
$request = $smcFunc['db_query']('', '
SELECT
a.id_attach, a.id_folder, a.id_msg, a.filename, a.fileext, a.file_hash, IFNULL(a.size, 0) AS filesize, a.downloads, a.approved,
a.width, a.height' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : ',
IFNULL(thumb.id_attach, 0) AS id_thumb, thumb.width AS thumb_width, thumb.height AS thumb_height') . '
FROM {db_prefix}attachments AS a' . (empty($modSettings['attachmentShowImages']) || empty($modSettings['attachmentThumbnails']) ? '' : '
LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb)') . '
WHERE a.id_msg IN ({array_int:message_list})' . (allowedTo('view_attachments') ? '' : '
AND a.fileext IN ({array_string:image_extensions})') . '
AND a.attachment_type = {int:attachment_type}',
array(
'message_list' => $messages,
'attachment_type' => 0,
'is_approved' => 1,
'image_extensions' => array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff'),
)
);

#2
// This is just a regular attachment...
else
{
// Make sure this attachment is on this board.
// NOTE: We must verify that $topic is the attachment's topic, or else the permission check above is broken.
$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, m.id_member
FROM {db_prefix}attachments AS a
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
WHERE a.id_attach = {int:attach}' . (allowedTo('view_attachments') ? '' : '
AND a.fileext IN ({array_string:image_extensions})') . '
LIMIT 1',
array(
'attach' => $_REQUEST['attach'],
'current_topic' => $topic,
'image_extensions' => array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff'),
)
);
}
if ($smcFunc['db_num_rows']($request) == 0)
{
// This checks only the current board for $board/$topic's permissions.
isAllowedTo('view_attachments');
fatal_lang_error('no_access', false);
}

SMF Tricks - Free & Premium Responsive Themes for SMF.

dodos26

#3
It makes sense to follow this lead, I don't know if it should not also be added for "SELECT --> a.fileext"

Because purely theoretically, a large number of files and a subsequent query in the database gives more calculations than one query in a php script.

Mby also for "'image_extensions' => array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff'),"
In this case 3x allowedTo('view_attachments') > 1 x allowedTo('view_attachments')
Code length doesn't always equate to performance.

And yes can add image_extensions in array:
'image_extensions' => array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff'),
provided that the user would like to edit this part of the code, otherwise it probably doesn't affect anything.
This is a good step to create a modification with the option of selecting an attachment extension that can be displayed to the guest in the event of blocking attachments in permissions.

Steve

DO NOT pm me for support!

Advertisement: