Created
September 15, 2021 15:49
-
-
Save ideadude/01d50d496612e6d378cae509c41b52b9 to your computer and use it in GitHub Desktop.
Lock down non-WordPress files in *multiple private directories* with Paid Memberships Pro.
This file contains hidden or 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 | |
/* | |
This code handles loading a file from one or more protected directories. | |
This is a variation of the code presented here: | |
https://www.paidmembershipspro.com/locking-non-wordpress-files-folders-paid-memberships-pro/ | |
(!) Be sure to change the $protected_directories arary below. | |
(!) Add this code to a code snippet or custom plugin. | |
(!) You should have a corresponding bit of code in your Apache .htaccess file | |
to redirect files to this script. You need one line per protected dir. | |
### | |
# BEGIN protected folder lock down | |
<IfModule mod_rewrite.c> | |
RewriteBase / | |
RewriteRule ^private1/(.*)$ /index.php?pmpro_getfile=private1/$1 [L] | |
RewriteRule ^private2/(.*)$ /index.php?pmpro_getfile=private2/$1 [L] | |
</IfModule> | |
# END protected folder lock down | |
### | |
*/ | |
define( 'PROTECTED_DIR', 'private1' ); //change this to the name of the folder to protect | |
function my_pmpro_getfile() { | |
if( isset( $_REQUEST['pmpro_getfile'] ) ) { | |
global $wpdb; | |
/* | |
Define directories and the levels with access. | |
If the levels array is empty, any member will have access. | |
Directories are expected to be at the webroot. | |
CHANGE THIS! | |
*/ | |
$protected_directories = array( | |
'private1' => array(), // any member can access | |
'private2' => array( 2,3 ), // levels 2 and 3 can access | |
); | |
// Prevent loops when redirecting to .php files. | |
if( ! empty( $_REQUEST['noloop'] ) ) { | |
status_header( 500 ); | |
die( 'This file cannot be loaded through the get file script.' ); | |
} | |
$uri = $_REQUEST['pmpro_getfile']; | |
if( ! empty( $uri ) && $uri[0] == '/' ) { | |
$uri = substr( $uri, 1, strlen( $uri ) - 1); | |
} | |
/* | |
Remove ../-like strings from the URI. | |
Actually removes any combination of two or more ., /, and \. | |
This will prevent traversal attacks and loading hidden files. | |
*/ | |
$uri = preg_replace( "/[\.\/\\\\]{2,}/", "", $uri ); | |
// Make sure this file is in one of our protected directories. | |
if( strpos( $uri, "/" ) !== false ) { | |
$parts = explode( "/", $uri ); | |
$basedir = $parts[0]; | |
} else { | |
$basedir = ''; | |
} | |
if ( ! in_array( $basedir, array_keys( $protected_directories ) ) ) { | |
header( 'HTTP/1.1 503 Service Unavailable', true, 503 ); | |
die( "HTTP/1.1 503 Service Unavailable" ); | |
} | |
// Figure out the filename on the server. | |
$filename = ABSPATH . $uri; | |
$pathParts = pathinfo($filename); | |
// Remove params from the end. | |
if( strpos( $filename, "?" ) !== false ) { | |
$parts = explode( "?", $filename ); | |
$filename = $parts[0]; | |
} | |
// Add index.html if this is a directory. | |
if( is_dir( $filename ) ) { | |
$filename .= "index.html"; | |
} | |
// Only checking if the file is pulled from outside the admin. | |
if( ! is_admin() ) { | |
// Check for access based on the directory accessed. | |
if( ! pmpro_hasMembershipLevel( $protected_directories[$basedir] ) ) { | |
//header('HTTP/1.1 503 Service Unavailable', true, 503); | |
//echo "HTTP/1.1 503 Service Unavailable"; | |
if ( ! is_user_logged_in() ) { | |
wp_redirect( wp_login_url( home_url( $uri ) ) ); | |
} else { | |
wp_redirect( home_url() ); | |
} | |
exit; | |
} | |
} | |
// Get the mimetype. | |
require_once( PMPRO_DIR . '/classes/class.mimetype.php' ); | |
$mimetype = new pmpro_mimetype(); | |
$file_mimetype = $mimetype->getType( $filename ); | |
//in case we want to do something else with the file | |
do_action( 'pmpro_getfile_before_readfile', $filename, $file_mimetype ); | |
// If file is not found, die | |
if( ! file_exists( $filename ) ) { | |
status_header( 404 ); | |
nocache_headers(); | |
die( 'File not found.' ); | |
} | |
//if blacklistsed file type, redirect to it instead | |
$basename = basename( $filename ); | |
$parts = explode( '.', $basename ); | |
$ext = strtolower( $parts[count( $parts ) - 1] ); | |
//build blacklist and allow for filtering | |
$blacklist = array( "inc", "php", "php3", "php4", "php5", "phps", "phtml" ); | |
$blacklist = apply_filters( "pmpro_getfile_extension_blacklist", $blacklist ); | |
//check | |
if( in_array( $ext, $blacklist ) ) { | |
//add a noloop param to avoid infinite loops | |
$uri = add_query_arg( "noloop", 1, $uri ); | |
//guess scheme and add host back to uri | |
if( is_ssl() ) { | |
$uri = "https://" . $_SERVER['HTTP_HOST'] . "/" . $uri; | |
} else { | |
$uri = "http://" . $_SERVER['HTTP_HOST'] . "/" . $uri; | |
} | |
wp_redirect( $uri ); | |
exit; | |
} | |
require_once( PMPRO_DIR . '/classes/class.mimetype.php' ); | |
//okay show the file | |
header( "Content-type: " . $file_mimetype ); | |
readfile( $filename ); | |
exit; | |
} | |
} | |
add_action( 'init', 'my_pmpro_getfile' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment