Cache-Control: in file.php

Need some custom code changes to the phpBB core simple enough that you feel doesn't require an extension? Then post your request here so that community members can provide some assistance.

NOTE: NO OFFICIAL SUPPORT IS PROVIDED IN THIS SUB-FORUM
Forum rules
READ: phpBB.com Board-Wide Rules and Regulations

NOTE: NO OFFICIAL SUPPORT IS PROVIDED IN THIS SUB-FORUM
Post Reply
User avatar
thecoalman
Community Team Member
Community Team Member
Posts: 5876
Joined: Wed Dec 22, 2004 3:52 am
Location: Pennsylvania, U.S.A.
Contact:

Cache-Control: in file.php

Post by thecoalman »

I'm using Cloudlfare and by default they do not cache php files, I can configure it to cache images and files served through file.php based on the header response but it appears every file is served with Cache-Control: public so that would include files in private forums, PM's etc.

Around line 200 in includes/functions_download.php is

Code: Select all

	// Now the tricky part... let's dance
	header('Cache-Control: public');
What I need to do is something like:

Code: Select all

if ($guest_user_can_view_this_file)
{
header('Cache-Control: public');
}
else
{
header('Cache-Control: private');
}
-------edit-------

In file.php around line 220 I can see how to set a variable for PM's but I'm getting past my pay grade for the guest user.

Code: Select all

		if (!$attachment['in_message'])
		{
			phpbb_download_handle_forum_auth($db, $auth, $attachment['topic_id']);

			$sql = 'SELECT forum_id, post_visibility
				FROM ' . POSTS_TABLE . '
				WHERE post_id = ' . (int) $attachment['post_msg_id'];
			$result = $db->sql_query($sql);
			$post_row = $db->sql_fetchrow($result);
			$db->sql_freeresult($result);

			if (!$post_row || !$phpbb_content_visibility->is_visible('post', $post_row['forum_id'], $post_row))
			{
				// Attachment of a soft deleted post and the user is not allowed to see the post
				send_status_line(404, 'Not Found');
				trigger_error('ERROR_NO_ATTACHMENT');
			}
		}
		else
		{
			// Attachment is in a private message.
			$post_row = array('forum_id' => false);
			phpbb_download_handle_pm_auth($db, $auth, $user->data['user_id'], $attachment['post_msg_id']);
		}


“Results! Why, man, I have gotten a lot of results! I have found several thousand things that won’t work.”

Attributed - Thomas Edison
User avatar
thecoalman
Community Team Member
Community Team Member
Posts: 5876
Joined: Wed Dec 22, 2004 3:52 am
Location: Pennsylvania, U.S.A.
Contact:

Re: Cache-Control: in file.php

Post by thecoalman »

Unless someone has suggestion for this I'm just going to hardcore the forum ID's in an array, not ideal but better than nothing.
“Results! Why, man, I have gotten a lot of results! I have found several thousand things that won’t work.”

Attributed - Thomas Edison
User avatar
mrgoldy
Former Team Member
Posts: 1394
Joined: Tue Oct 06, 2009 7:34 pm
Location: The Netherlands
Name: Gijs
Contact:

Re: Cache-Control: in file.php

Post by mrgoldy »

well, it will require a few additional sql queries to determine if the current user is allowed to see the current attachment, so I'm not sure if that's worth it.

So, there are three options.
- Attachment that is an orphan (no post / pm)
- Attachment in a post (in_message = 0)
- Attachment in pm (in_message = 0)

Not sure how you want to handle orphaned attachments.

As for an attachment in a post, you will have to global $auth aswell.
Then you can a list of forum identifiers that the current user is allowed to read:
$authed_forums = array_keys($auth->acl_getf('f_read', true));
Unfortunately there is no forum identifier stored in the attachment table and thus not available in the $attachment array. So you'll have to query the topics table to retrieve the forum identifier and check if it's in the $authed_forums array.

As for an attachment in a pm, you can check if the current user is the poster, which results in no querying:
$user->data['user_id'] == $attachment['poster_id'].
If that's not the case, you'll have to query the privmsgs_to table.

So it might look something like this, do note that I did not test this myself and I am not sure this is what you're after. But it should atleast get you in the right direction:

Code: Select all

// Attachment that is orphaned
if ($attachment['is_orphan'])
{
	// Handle orphaned attachments

	$auth_attachment = false;
}
// Attachment in a private message
else if ($attachment['in_message'])
{
	if ($user->data['user_id'] == ANONYMOUS)
	{
		// This user is a guest and can not even send/read private messages
		$auth_attachment = false;
	}
	else if ($user->data['user_id'] == $attachment['poster_id'])
	{
		// If this user is the poster of the attachment
		$auth_attachment = true;
	}
	else
	{
		$sql = 'SELECT user_id FROM ' . PRIVMSGS_TO_TABLE . ' WHERE msg_id = ' . (int) $attachment['msg_id'];
		$result = $db->sql_query($sql);
		$row = $db->sql_fetchrow($result);
		$db->sql_freeresult($result);

		// Either a row is found, or $row === false;
		$auth_attachment = $row !== false ? true : false;
	}
}
// Attachment in a post
else
{
	// Get forum this user can read
	$authed_forums = array_keys($auth->acl_getf('f_read', true));

	// Select the forum identifier for this topic identifier
	$sql = 'SELECT forum_id FROM ' . TOPICS_TABLE . ' WHERE topic_id = ' . (int) $attachment['topic_id'];
	$result = $db->sql_query($sql);
	$forum_id = $db->sql_fetchfield('forum_id');
	$db->sql_freeresult($result);

	// Check if the forum identifier is in the authed forums
	$auth_attachment = in_array($forum_id, $authed_forums) ? true : false;
}

if ($auth_attachment)
{
	header('Cache-Control: public');
}
else
{
	header('Cache-Control: private');
}
phpBB Studio / Member of the Studio

Contributing: You can do it too! Including testing Pull Requests (PR).
phpBB Development and Testing made easy.
User avatar
3Di
I've Been Banned!
Posts: 17538
Joined: Mon Apr 04, 2005 11:09 pm
Location: I'm with Ukraine 🇺🇦
Name: Marco
Contact:

Re: Cache-Control: in file.php

Post by 3Di »

mrgoldy wrote: Tue Feb 19, 2019 5:22 pm - Attachment in a post (in_message = 0)
- Attachment in pm (in_message = 0)
A typo I believe: If attachments are used inside pm = 1, inside post = 0.
🆓 Free support for our extensions also provided here: phpBB Studio
🚀 Looking for a specific feature or alternative option? We will rock you!
Please PM me only to request paid works. Thx. Buy me a coffee -> Image
My development's activity º PhpStorm's proud user º Extensions, Scripts, MOD porting, Update/Upgrades
User avatar
thecoalman
Community Team Member
Community Team Member
Posts: 5876
Joined: Wed Dec 22, 2004 3:52 am
Location: Pennsylvania, U.S.A.
Contact:

Re: Cache-Control: in file.php

Post by thecoalman »

mrgoldy wrote: Tue Feb 19, 2019 5:22 pm well, it will require a few additional sql queries to determine if the current user is allowed to see the current attachment, so I'm not sure if that's worth it.
This is one of those short term loss for long term gain situations. The bulk of the requests will never hit my server once cached on Cloudflare.

Then you can a list of forum identifiers that the current user is allowed to read:
The issue is when a registered user who can view an attachment in a private forum requests the attachment Cloudflare would cache it because it's set to public. I need to set the cache control to private for those forums. In fact it would appear this is a bit buggy how phpBB is handling this, it should be set to private, yes?

In any event what you posted should set me off in the right direction, once I have an example of something I can usually work through it. Thanks.
“Results! Why, man, I have gotten a lot of results! I have found several thousand things that won’t work.”

Attributed - Thomas Edison
User avatar
mrgoldy
Former Team Member
Posts: 1394
Joined: Tue Oct 06, 2009 7:34 pm
Location: The Netherlands
Name: Gijs
Contact:

Re: Cache-Control: in file.php

Post by mrgoldy »

thecoalman wrote: Tue Feb 19, 2019 10:24 pm The issue is when a registered user who can view an attachment in a private forum requests the attachment Cloudflare would cache it because it's set to public. I need to set the cache control to private for those forums. In fact it would appear this is a bit buggy how phpBB is handling this, it should be set to private, yes?
Not sure if I understand you correctly, but apart from the above you also want to distinguish users who have access to specific forums that regular registered users do not?
I do have to admit, I have rather limited knowledge of the attachment / download system so I would not know how the caching is done / works. If that is for all users or on a per user basis. If it's per user, it should be fine in my provided example, if it's for all users, I do not see a way to cache it properly.

The $auth->acl_getf('f_read') gets you an array with forum_id => permissions => true for all the forums the current user (current user is always $user) has that permission for.

Code: Select all

$array = array(
	5 => array(
		'f_read' => true,
	),
	7 => array(
		'f_read' => true,
	),
);
Et cetera.

Now after re-reading your post, it looks like the caching should not be done on a per-user basis but on a per-forum basis?
That might be possible aswell but what is distinguishable for those private forums. For example; can registered users not read them? Or are all forum names starting with "Private ..." etc. As we need someway to determine if it's considered a "private" forum.

Oh, I think I am starting to better understand your question now.
Then always set cache control to private for Orphaned and Private Message attachments.
And for attachments in posts, I would do something like this:

Code: Select all

if ($user->data['user_id'] != ANONYMOUS)
{
	$userdata = $auth->obtain_user_data(ANONYMOUS);
	$auth->acl($userdata);
}
	
$authed_forums = array_keys($auth->acl_getf('f_read'));
The above mimicks the 'auth' function for the Guests group, if the current user is not a guest already.
Then you can get all the forums a guest can read. Then obtain the forum id as shown in my earlier example.
If it's in the $authed_forums array, you can set it to "public", otherwise set it to "private".
phpBB Studio / Member of the Studio

Contributing: You can do it too! Including testing Pull Requests (PR).
phpBB Development and Testing made easy.
User avatar
thecoalman
Community Team Member
Community Team Member
Posts: 5876
Joined: Wed Dec 22, 2004 3:52 am
Location: Pennsylvania, U.S.A.
Contact:

Re: Cache-Control: in file.php

Post by thecoalman »

mrgoldy wrote: Tue Feb 19, 2019 11:31 pm Now after re-reading your post, it looks like the caching should not be done on a per-user basis but on a per-forum basis?
Correct.


Code: Select all

if ($user->data['user_id'] != ANONYMOUS)
{
	$userdata = $auth->obtain_user_data(ANONYMOUS);
	$auth->acl($userdata);
}
	
$authed_forums = array_keys($auth->acl_getf('f_read'));
This appears to be exactly what I needed, thanks.
“Results! Why, man, I have gotten a lot of results! I have found several thousand things that won’t work.”

Attributed - Thomas Edison
Post Reply

Return to “phpBB Custom Coding”