Created
September 29, 2020 18:43
-
-
Save nullvariable/2bad7687be2cf2897d86aebc82003d3f to your computer and use it in GitHub Desktop.
Private Files Example for Pantheon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Example Private Files | |
* Author: Doug Cone | |
* Description: Auth for Pantheon Private files | |
* Version: 0.1.0 | |
*/ | |
/** | |
* This doesn't protect direct access, you must move your files to a folder not accessible to the public, but accessible to this script. | |
* On Pantheon, that location is: `/wp-content/uploads/private` (See docs: https://pantheon.io/docs/private-paths) | |
* | |
* You will need to move any files uploaded prior to adding this plugin, or fallback to checking the old upload path. | |
* | |
* This plugin is all or nothing, you could likely add a per file option leveraging different filters/hooks and the file meta data. | |
*/ | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; | |
} | |
// location that private files will live in. | |
define( 'PF_UPLOADS', WP_CONTENT_DIR . '/uploads/private' ); | |
// Modify the upload folder to ensure that files cannot be accessed directly. | |
add_filter( 'upload_dir', 'pf_upload_dir' ); | |
add_action( | |
'init', | |
function () { | |
add_feed( 'priv_files', 'pf_handle' ); | |
} | |
); | |
/** | |
* Filter the upload directory to our private files location. | |
* | |
* @param array $uploads the uploads array, see web/wp-includes/functions.php. | |
* @return array | |
*/ | |
function pf_upload_dir( $uploads ) { | |
$path = str_replace( $uploads['basedir'], '', $uploads['path'] ); | |
$uploads['basedir'] = PF_UPLOADS; | |
$uploads['path'] = PF_UPLOADS . $path; | |
$uploads['url'] = site_url( '/priv_files?file=' . $path ); | |
$uploads['baseurl'] = site_url( '/priv_files?file=' ); | |
return $uploads; | |
} | |
/** | |
* Add feed handler. Checks auth status and responds accordingly. | |
* | |
* @return void | |
*/ | |
function pf_handle() { | |
// Something like `current_user_can( 'manage_options' )` here would restrict all file access to admins. `is_user_logged_in()` would just require a user to be logged in. | |
if ( true === true ) { | |
$file_to_check = isset( $_GET['file'] ) ? PF_UPLOADS . sanitize_text_field( $_GET[ 'file' ] ) : ''; | |
if ( file_exists( $file_to_check ) ) { | |
header( 'Content-Type: ' . mime_content_type( $file_to_check ), true, 200 ); | |
// you could/should add a caching header here to encourage the browser to hold on to this file longer. | |
readfile( $file_to_check ); // phpcs:ignore | |
exit; | |
} else { | |
global $wp_query; | |
status_header( 404 ); | |
$wp_query->set_404(); | |
nocache_headers(); | |
$template = get_query_template( '404' ); | |
if ( $template ) { | |
header( 'Content-Type: text/html' ); | |
include $template; | |
} | |
exit; | |
} | |
} else { | |
status_header( 403 ); | |
nocache_headers(); | |
// or maybe `wp_safe_redirect( wp_login_url(), 302, 'Private Files' );` instead. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that on Pantheon static assets don't count towards your traffic, but requests to php scripts like this do.