arraypress / wp-file-utils
Path containment, MIME types and filename helpers for WordPress plugins that serve files.
Requires
- php: >=8.3
Requires (Dev)
- phpcompatibility/phpcompatibility-wp: ^2.1
- phpunit/phpunit: ^12.0
- squizlabs/php_codesniffer: ^3.13.5
- wp-coding-standards/wpcs: ^3.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Path containment, MIME types and filename helpers for plugins that serve files.
What it does
If your plugin hands users a file, the important question is whether the path it was asked for is really inside the directory you meant. Getting that wrong is how a download endpoint becomes an arbitrary file read.
Path::within() answers it properly — resolving symlinks and .. before
comparing, rather than string-matching the prefix.
The rest is the surrounding work: what MIME type to send, whether a browser would render it inline instead of downloading it, and changing an extension without mangling a filename that contains dots.
Features
- Check a path is genuinely inside a directory, after resolving
..and symlinks - Look up a MIME type, and the extension a MIME type should use
- Tell which types a browser renders inline, and which are unsafe to serve that way
- Decide whether a file should be forced to download
- Change a filename's extension without breaking
archive.2024.tar.gz - Convert between a filesystem path and its uploads URL
Installation
composer require arraypress/wp-file-utils
Quick start
use ArrayPress\FileUtils\MIME; use ArrayPress\FileUtils\Path; // The check that matters: is the requested file really inside our directory? if ( ! Path::within( $requested, $downloads_dir ) ) { wp_die( 'Not found', 404 ); } // Never render an untrusted upload inline. if ( MIME::is_dangerous_inline( $file ) ) { header( 'Content-Disposition: attachment' ); } header( 'Content-Type: ' . MIME::of( $file ) );
Requirements
- PHP 8.3 or later
- WordPress 7.1 or later
License
GPL-2.0-or-later