-
-
Save ideadude/137bb0d06f8f49fc262c2fad3010c440 to your computer and use it in GitHub Desktop.
How to protect non-WordPress files in a subdirectory of your site using 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 the /protected-directory/ directory. | |
(!) Be sure to change line 19 below to point to your protected directory if something other than /protected/ | |
(!) Be sure to change line 66 below to the level ID or array of level IDs to check for the levels you need. | |
(!) Add this code to your active theme's functions.php or a custom plugin. | |
(!) You should have a corresponding bit of code in your Apache .htaccess file to redirect files to this script. e.g. | |
### | |
# BEGIN protected folder lock down | |
<IfModule mod_rewrite.c> | |
RewriteBase / | |
RewriteRule ^protected-directory/(.*)$ /?pmpro_getfile=$1 [L] | |
</IfModule> | |
# END protected folder lock down | |
### | |
*/ | |
define('PROTECTED_DIR', 'protected-directory'); //change this to the name of the folder to protect | |
function my_pmpro_getfile() | |
{ | |
if(isset($_REQUEST['pmpro_getfile'])) | |
{ | |
global $wpdb; | |
//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); | |
//edit to point at your protected directory | |
$new_uri = PROTECTED_DIR . '/' . $uri; | |
$filename = ABSPATH . $new_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()) | |
{ | |
//non-members don't have access (checks for level 2 or 3) | |
if(!pmpro_hasMembershipLevel()) | |
{ | |
//nope | |
//header('HTTP/1.1 503 Service Unavailable', true, 503); | |
//echo "HTTP/1.1 503 Service Unavailable"; | |
wp_redirect( wp_login_url( home_url( $new_uri ) ) ); | |
exit; | |
} | |
} | |
//get 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"); |
Line 71 should be updated to redirect to the file after login
wp_redirect( wp_login_url( home_url( $new_uri ) ) );
This recipe is included in "Locking Down Non-WordPress Files and Folders with Paid Memberships Pro" at Paid Memberships Pro here: https://www.paidmembershipspro.com/locking-non-wordpress-files-folders-paid-memberships-pro/
Could this code be modified to protect and serve multiple folders?
And if so what parts would I need to change?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Needs some updates on the directions here.
Line 5 should say change Line 19 (not 44)
Line 6 should refer to 66 (not 44)
perhaps we could say add - members levels "as an array" if more then one?
Could the sample directory be the same in line 14 and 19 for clarity?