Simple Machines Community Forum

Customizing SMF => Tips and Tricks => Topic started by: dodos26 on November 27, 2022, 07:57:09 AM

Title: [SMF 2.0.x] How to make image attachments visible to guests?
Post by: dodos26 on November 27, 2022, 07:57:09 AM
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);
    }
Title: Re: How to make image attachments visible to guests?
Post by: Steve on December 01, 2022, 06:48:27 AM
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)?
Title: Re: How to make image attachments visible to guests?
Post by: Diego Andrés on December 01, 2022, 07:43:51 PM
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);
}
Title: Re: How to make image attachments visible to guests?
Post by: dodos26 on December 02, 2022, 02:47:44 PM
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.
Title: Re: [SMF 2.0.x] How to make image attachments visible to guests?
Post by: Steve on December 02, 2022, 02:54:09 PM
Topic cleaned up.