Skip to content

Instantly share code, notes, and snippets.

@pbrocks
Last active November 19, 2020 04:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pbrocks/9da77617d1714ea6c78ba528e387c4cb to your computer and use it in GitHub Desktop.
Save pbrocks/9da77617d1714ea6c78ba528e387c4cb to your computer and use it in GitHub Desktop.
Using the getfile.php element in PMPro, you can lock down files and/or directories within the URL structure of your domain.
<?php
/*
This code handles loading a file from the /protected-directory/ directory.
Plugin Name: PMPro Access
(!) Be sure to change line 44 below to point to your protected directory if something other than /protected/
(!) Be sure to change line 64 below to check the levels you need.
(!) Add this code to your customizations 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 ^access/(.*)$ /index.php?pmpro_getfile=$1 [L]
</IfModule>
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
###
*/
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 ( $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 = 'access/' . $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() );
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' );
/**
* Redirect user after successful login.
*
* @param string $redirect_to URL to redirect to.
* @param string $request URL the user is coming from.
* @param object $user Logged user's data.
* @return string
*/
function my_login_redirect( $redirect_to, $request, $user ) {
// is there a user to check?
if ( ! empty( $user ) && ! empty( $user->ID ) && function_exists( 'pmpro_getMembershipLevelForUser' ) ) {
$level = pmpro_getMembershipLevelForUser( $user->ID );
if ( ! empty( $request ) ) {
// $redirect_to = get_permalink( $request );
$redirect_to = $request;
}
}
// if ( isset( $user->roles ) && is_array( $user->roles ) ) {
// check for subscribers
// if (in_array('subscriber', $user->roles)) {
// redirect them to another URL, in this case, the homepage
// $redirect_to = $request;
// }
// }
return $redirect_to;
}
add_filter( 'login_redirect', 'my_login_redirect', 10, 3 );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment