File: //wordpress/mu-plugins/pressable.php
<?php
/**
Plugin Name: Pressable
Plugin URI: https://github.com/pressable
Version: 0.8.6
Author: <a href="http://pressable.com/">Pressable</a> <code@pressable.com>
Description: Pressable Plugin for WordPress
*/
/**
* Fix for nextgen-gallery plugin which attempts to use ABSPATH as the
* document root for the site which, in pressables case, ends up being
* /htdocs/__wp__/ and is not what nextgen-gallery is looking for.
*/
if ( ! defined( 'NGG_GALLERY_ROOT_TYPE' ) )
define( 'NGG_GALLERY_ROOT_TYPE', 'content' );
/**
* Fix for nextcellent-gallery-nextgen-legacy which does this
* define('WINABSPATH', str_replace("\\", "/", ABSPATH) );
*/
if ( ! defined( 'WINABSPATH' ) )
define( 'WINABSPATH', trailingslashit( $_SERVER['DOCUMENT_ROOT'] ) );
// allow overriding this plugin via the sites mu-plugins for dev purposes.
if ( ! defined( 'PRESSABLE_MU_DEV_LOADED' ) || ! PRESSABLE_MU_DEV_LOADED ) :
define( 'PRESSABLE_MU_DEV_LOADED', true );
// Hot-fix for bwp-minify plugin if it is activated with another file name:
// it won't load itself if its class already exists.
final class BWP_MINIFY {}
final class Pressable_Mu_Plugin {
// Users which may only access the site via a proxied IP Address
private $admin_restrict_users = array(
'pressable',
'zippykid',
);
private $cdn_site_domain;
private $cdn_site_domain_regex;
private $cdn_old_domains_regex;
private $cdn_domain;
private $cdn_upload_dir;
private $cdn_extensions = 'jpe?g|jpeg|gif|png|css|bmp|js|ico|woff2|webp';
private $cdn_protocol = "http";
function __construct() {
// CDN for sites in production mode (non wp-admin requests)
$do_pressable_cdn_init = true;
// Never in wp-admin
if ( is_admin() ) {
$do_pressable_cdn_init = false;
}
// Never if development mode is enabled
if ( defined( 'AT_DEVELOPMENT_MODE' ) && 'on' == AT_DEVELOPMENT_MODE ) {
$do_pressable_cdn_init = false;
}
if ( true === $do_pressable_cdn_init ) {
add_action( 'init', array( $this, 'cdn_init' ), 10, 999 );
}
// Analytics for all sites
if ( defined( 'AT_GAUGES_ID' ) && AT_GAUGES_ID && !is_admin() )
add_action( 'wp_footer', array( $this, 'gauges_init' ), 99 );
// Restrict Pressable Support User
add_filter( 'wp_authenticate_user', array( $this, 'restrict_pressable_authentication' ) );
add_action( 'auth_cookie_valid', array( $this, 'auth_cookie_valid' ) );
// Remove dashboard widgets
add_action( 'wp_dashboard_setup', array( $this, 'remove_extraneous_dashboard_widgets' ) );
// Fix for bugs like https://github.com/reduxframework/redux-framework/issues/2912
if ( 'cli' !== php_sapi_name() ) {
add_filter( 'template_directory', array( $this, 'template_directory' ) );
add_filter( 'stylesheet_directory', array( $this, 'stylesheet_directory' ) );
}
// Global fix for a family of commercial themes with resizing functionality that doesn't work properly
// themes based on "ePanel" -- http://www.elegantthemes.com/features/
add_filter( 'et_resize_image_site_dir', array( $this, 'et_resize_image_site_dir' ) );
// SportPress doesn't work well with advanced-post-cache
add_filter( 'advanced_post_cache_skip_for_post_type', array( $this, 'filter_sportspress_post_types' ), 10, 2 );
// Add managed plugin & theme labels
add_filter( 'atomic_managed_plugin_row_auto_update_label', array( $this, 'atomic_managed_plugin_row_auto_update_label' ) );
add_filter( 'atomic_managed_theme_template_auto_update_label', array( $this, 'atomic_managed_theme_template_auto_update_label' ) );
add_filter( 'atomic_managed_plugin_auto_update_debug_label', array( $this, 'atomic_managed_plugin_auto_update_debug_label' ) );
add_filter( 'atomic_managed_theme_auto_update_debug_label', array( $this, 'atomic_managed_theme_auto_update_debug_label' ) );
}
// Specific fix for image resizing functionality for "ePanel" based themes http://www.elegantthemes.com/features/
function et_resize_image_site_dir( $path ) {
if ( !is_string( $path ) )
return $path;
return $_SERVER['DOCUMENT_ROOT'];
}
// Given a username can the username be accessed via the current remote address?
function can_user_access( $username ) {
if ( !in_array( $username, $this->admin_restrict_users ) )
return true;
if ( defined('AT_PROXIED_REQUEST') && AT_PROXIED_REQUEST )
return true;
return false;
}
// For already logged in requests: Can the given auth cookie access the site? For example if you
// previously logged in as pressable support via proxy but then leave the proxy and come back
// you should no longer have access to the site as the pressable user
function auth_cookie_valid( $user ) {
if ( is_array( $user ) && array_key_exists( 'username', $user ) ) {
if ( !$this->can_user_access( $user['username'] ) ) {
remove_action( 'auth_cookie_valid', array( $this, 'auth_cookie_valid' ) );
wp_logout();
}
}
}
// During login check to make sure that pressable support user login attempts are coming invia
// a proxied connection. If not the login attempt should be completely denied.
function restrict_pressable_authentication( $user ) {
if ( get_class( $user ) !== 'WP_User' )
return $user;
if ( !$this->can_user_access( $user->data->user_login ) )
return new WP_Error( "access-denied", "Proxy Access Required For This Account" );
return $user;
}
/**
* inspired by http://codex.wordpress.org/Dashboard_Widgets_API
**/
function remove_extraneous_dashboard_widgets() {
remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
}
function template_directory( $template_dir ) {
return realpath( $template_dir );
}
function stylesheet_directory( $stylesheet_dir ) {
return realpath( $stylesheet_dir );
}
function gauges_init() {
?>
<script type="text/javascript">
(function() {
var t = document.createElement( 'script' );
t.type = 'text/javascript';
t.async = true;
t.id = 'gauges-tracker';
t.setAttribute( 'data-site-id', '<?php echo esc_js( AT_GAUGES_ID ); ?>' );
t.src = '//secure.gaug.es/track.js';
var s = document.getElementsByTagName( 'script' )[0];
s.parentNode.insertBefore( t, s );
})();
</script>
<?php
}
function cdn_init() {
add_action( 'template_redirect', array( $this, 'cdn_template_redirect' ), 10, 999 );
add_action( 'wp_stack_cdn_content', array( $this, 'cdn_filter' ), 10, 999 );
$this->cdn_site_domain = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST );
$this->cdn_site_domain_regex = preg_quote( parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ) );
$this->cdn_old_domains_regex = '[a-z0-9]{16}(?:\-zippykid\.netdna\-ssl\.com|\.zippykid\.netdna\-cdn\.com)';
// DB_NAME == site_id
$this->cdn_domain = DB_NAME . '.v2.pressablecdn.com';
if ( is_ssl() )
$this->cdn_protocol = "https";
}
function cdn_fix_srcsets( $content ) {
// Step #1 find all srcset={{something}} attributes in the content. This isn't great (what would be best
// would be actual html/ parsing, but this is what we have and it matches the existing plugin code... so
// we'll go with it for now.
if ( preg_match_all( "# srcset=([\"'])(.+)\\1#U", $content, $srcsets ) ) {
foreach( $srcsets[0] as $match_id => $srcset ) {
// make a copy of the entire srcset so that we can search and replace *just* within
// this particular srcset tag
$new_srcset = $srcset;
// Pull out all the srcset pieces (used https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img
// as a reference for what a srcset could look like, and what pieces could constitute it.
if ( preg_match_all( '#(?:https?://[^ ]+(?: [0-9]+[wx])?)#', $srcsets[2][$match_id], $m ) ) {
foreach( $m[0] as $match ) {
// Replace, within our copy of the original srcset, the original srcset part
// with a reconstructed srcset part. Which methos we use to recreate this
// depends on how we were called.
$new_srcset = str_replace(
$match,
preg_replace(
"#^(https?://(?:{$this->cdn_site_domain_regex}|$this->cdn_old_domains_regex}))?/([^ ]+)\.({$this->cdn_extensions})(.*)( [0-9]+[wx])?$#",
$this->cdn_protocol . '://' . $this->cdn_domain . '/$2.$3$4 $5',
$match ),
$new_srcset
);
}
}
// Now within the content replace the original srcset with the mutated srcset. The reason we
// used the temporary variable was so that, in the case of very large blocks of content, we
// avoid operating on the majority of the data except when there is no choice. Which should
// help avoid memory and speed issues with these heavy operations...
$content = str_replace( $srcset, $new_srcset, $content );
}
}
// All done. hand back the freshly mutated content
return $content;
}
function cdn_fix_link_attributes( $content ) {
return preg_replace(
"#(?<=[(\"'])(https?://)({$this->cdn_site_domain_regex}|{$this->cdn_old_domains_regex})(?:(/[^\"')]+\.({$this->cdn_extensions})))#",
$this->cdn_protocol . '://' . $this->cdn_domain . '$3',
$content
);
}
// svg is not safe to serve from cdn urls but some sites have svg files served from old cdn urls.
function cdn_fix_oldcdn_svg( $content ) {
return preg_replace(
"#(?<=[(\"'])(https?://)({$this->cdn_old_domains_regex})(?:(/[^\"')]+\.(svg)))#",
$this->cdn_protocol . '://' . $this->cdn_site_domain . '$3',
$content
);
}
function cdn_filter( $content ) {
return $this->cdn_fix_oldcdn_svg(
$this->cdn_fix_link_attributes(
$this->cdn_fix_srcsets( $content )
)
);
}
function cdn_template_redirect() {
ob_start( array( $this, 'cdn_ob' ) );
}
function cdn_ob( $contents ) {
return apply_filters( 'wp_stack_cdn_content', $contents, $this );
}
function filter_sportspress_post_types( $return_me, $post_type ) {
if ( function_exists( 'sp_post_types' ) ) {
if ( in_array( $post_type, sp_post_types() ) ) {
return true;
}
}
return $return_me;
}
function atomic_managed_plugin_row_auto_update_label() {
return 'Managed by Host';
}
function atomic_managed_theme_template_auto_update_label() {
return 'Updates managed by Host';
}
function atomic_managed_plugin_auto_update_debug_label() {
return 'Updates managed by Host';
}
function atomic_managed_theme_auto_update_debug_label() {
return 'Updates managed by Host';
}
}
new Pressable_Mu_Plugin();
endif; // if ( !defined( 'PRESSABLE_MU_DEV_LOADED' ) || !PRESSABLE_MU_DEV_LOADED ):