Skip to content

Fix cache directory permissions and PHP 8+ TypeError on fopen failure#7

Open
toineenzo wants to merge 1 commit into
YOURLS:masterfrom
toineenzo:compat-php84-yourls110
Open

Fix cache directory permissions and PHP 8+ TypeError on fopen failure#7
toineenzo wants to merge 1 commit into
YOURLS:masterfrom
toineenzo:compat-php84-yourls110

Conversation

@toineenzo

Copy link
Copy Markdown

Summary

Two small, backwards-compatible fixes in plugin.php:

1. mkdir() mode 0600 -> 0755

On activation, the plugin creates a cache/ directory with mode 0600. That mode (rw- for owner only, no execute bit) prevents PHP from traversing the directory it just created, so subsequent file_exists(), filemtime(), and fopen() calls against files inside cache/ silently fail. Switching to 0755 makes the directory actually usable.

2. Guard fwrite()/fclose() against fopen() failure

ozh_ycache_shutdown() did:

$fp = fopen( $cachefile, 'w' );
$data = ob_get_contents();
fwrite($fp, $data);
fclose($fp);

If fopen() fails (cache dir missing, unwritable, full disk, etc.), it returns false. Since PHP 8.0, fwrite() and fclose() require a resource and throw TypeError when given false, which would crash the request. Added an explicit if ( $fp !== false ) check around the writes. The buffered output is still echoed to the browser either way, so a write failure now degrades gracefully instead of fatally.

No version bump, no behavior change on the happy path.

Test plan

  • Activate plugin on a fresh install; confirm cache/ is created and writable by PHP
  • Visit a stat page (+) twice, confirm second hit serves from cache (<!-- Cached ... --> marker)
  • Manually chmod 000 cache/ and visit a stat page; confirm no fatal TypeError, page still renders

- mkdir() was using mode 0600 which prevents PHP from traversing the
  directory it just created, breaking subsequent file_exists()/fopen()
  calls inside it. Use 0755 so the cache directory is actually usable.
- ozh_ycache_shutdown() called fwrite()/fclose() on the result of
  fopen() without checking for failure. Since PHP 8.0 these functions
  require a resource argument and throw TypeError when given false
  (e.g. when the cache directory is missing or unwritable). Guard the
  write with an explicit check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ozh

ozh commented Apr 28, 2026

Copy link
Copy Markdown
Member

Thanks. I think this PR fixes two problems that don't exist :

  • Minor : changing fopen() to @fopen is surely an edge case we might want to deal with, but honestly who in their right mind would activate a plugin then manually delete the folder.
  • Major : as is, the plugin works fine -- see last line of view-source:https://app.yourls.org/protonpass+ for instance -- so I don't get in what case it would silently fail. And chmoding to 0755 on shared hosting is a super bad idea : any user can see your dir content. If anything, 0700 would be a slightly better value, if there is something to fix in the first place (ie a case where 0600 would actually fail)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants