WordPress.org

Plugin Reviews

Media Vault

Protect attachment files from direct access using powerful and flexible restrictions. Offer safe download links for any file in your uploads folder.

21 reviews
Average Rating
4.7 out of 5 stars
You are currently viewing the reviews that provided a rating of 5 stars. Click here to see all reviews.
Great Work
By , for WP 4.5.3

Use it to secure some of my contents on a mid sized Page.
Did some additional stuff to it:

  • Woocommerce membership (checks if a user already payed for chosen content or is subscriber)
  • Add options to the Divi theme&Builder to restrict access to sections/blocks the same way as the media vault would do
  • rewritten file serve code to handle ranged/streamed video and or other big data packages
  • action added to use an s3 as primary file delivery as private links and the media vault as fallback (fileOnS3?header location s3:serve file)

If requested i'll assist on similar topics.
If anybody is interested in the rewritten file serving php thing:
the following code is a part of the "mv-file-handler.php" file - there where no actions to overrule so i had to modify the original source:

function mgjp_mv_get_file($rel_file, $action = ''){

	// $rel_file = path to the file to view/download,
	// relative to the WP uploads folder
	// (eg:'/media-vault/2013/10/media-vault-150x150.jpg')

	$upload_dir = wp_upload_dir();

	// only files in the WP uploads directory are allowed to be accessed:
	$file = rtrim($upload_dir['basedir'], '/').str_replace('..', '', isset($rel_file)?$rel_file:'');

	//---Basic Checks----------------------------------------------------//

	if(!$upload_dir['basedir'] || !is_file($file)){
		status_header(404);
		wp_die('404. File not found.');
	}

	$mime = wp_check_filetype($file); // Check filetype against allowed filetypes

	if(isset($mime['type']) && $mime['type']){
		$mimetype = $mime['type'];
	}else{
		status_header(403);
		wp_die(__('403. Forbidden.<br/>You cannot directly access files of this type in this directory on this server. Please contact the website administrator.'));
	}

	//---Permission Checks-----------------------------------------------//

	$file_info = pathinfo($rel_file);

	// check if file is protected by checking
	// if it is in the protected folder before
	// doing any permission checks
	if(0 === stripos($file_info['dirname'].'/', mgjp_mv_upload_dir('/', true))){

		// disable caching of this page by caching plugins ------//
		if(!defined('DONOTCACHEPAGE'))
			define('DONOTCACHEPAGE', 1);

		if(!defined('DONOTCACHEOBJECT'))
			define('DONOTCACHEOBJECT', 1);

		if(!defined('DONOTMINIFY'))
			define('DONOTMINIFY', 1);

		//-------------------------------------------------------//

		// try and get attachment id from url -------------------//
		global $wpdb;
		$attachments = $wpdb->get_results(
			$wpdb->prepare(
				"
        SELECT      post_id, meta_value
        FROM        $wpdb->postmeta
        WHERE       meta_key = %s
                    AND meta_value LIKE %s
        ",
				'_wp_attachment_metadata',
				'%'.$file_info['basename'].'%'
			), ARRAY_A
		);

		$attachment_id = false;
		foreach($attachments as $attachment){

			$meta_value = unserialize($attachment['meta_value']);

			if(ltrim(dirname($meta_value['file']), '/') == ltrim($file_info['dirname'], '/')){
				$attachment_id = $attachment['post_id'];
				break;
			}
		}
		// ------------------------------------------------------//

		if(!$permission = mgjp_mv_get_the_permission($attachment_id))
			$permission = get_option('mgjp_mv_default_permission', 'logged-in');

		$permissions = mgjp_mv_get_the_permissions();

		// permission set up error detection
		$standard_error_txt = ' '.esc_html__('Therefore for safety and privacy reasons this file is unavailable. Please contact the website administrator.', 'media-vault').'<p><a href="'.home_url().'">&larr;'.esc_html__('Return to homepage', 'media-vault').'</a></p>';

		if(!isset($permissions[$permission]))
			wp_die(__('The permissions set for this file are not recognized.', 'media-vault').$standard_error_txt);

		if(!isset($permissions[$permission]['logged_in']))
			$errors[] = 'logged_in';
		if(!isset($permissions[$permission]['cb']))
			$errors[] = 'cb';
		if(isset($errors)){
			$error_txt = __('The permissions set for this file have left the following important parameters undefined:', 'media-vault')
				.'<ul><li>\''.implode('\'</li><li>\'', $errors).'\'</li></ul>'
				.'<p>'.$standard_error_txt.'</p>';
			wp_die($error_txt);
		}

		if($permissions[$permission]['logged_in'])
			is_user_logged_in() || auth_redirect(); // using is_user_logged_in is lighter than using just auth_redirect

		if(false !== $permissions[$permission]['cb']){

			if(!is_callable($permissions[$permission]['cb']))
				wp_die(__('The permission checking function set in this file\'s permissions is not callable.', 'media-vault').$standard_error_txt);

			$permission_check = call_user_func_array($permissions[$permission]['cb'], array($attachment_id, $rel_file, $file));

			if(is_wp_error($permission_check))
				wp_die($permission_check->get_error_message().$standard_error_txt);

			if(true !== $permission_check)
				wp_die(__('You do not have sufficient permissions to view this file.', 'media-vault').$standard_error_txt);
		}

		if(function_exists('attachment_get_remote_url') && $remote_url = attachment_get_remote_url($attachment_id)){
			header("Location: ".$remote_url,TRUE,307);
		}

	} // end of permission checks

	//-------------------------------------------------------------------//

	$filesize = filesize($file);
	header('Content-Type: '.$mimetype); // always send this
	if(false === strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS'))
		header('Content-Length: '.$filesize);

	if('safeforce' !== $action){
		//--OPEN FILE IN BROWSER functions-------------//

		$last_modified = gmdate('D, d M Y H:i:s', filemtime($file));
		$etag = '"'.md5($last_modified).'"';
		header("Last-Modified: $last_modified GMT");
		header('ETag: '.$etag);
		header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP 1.1.
		header('Pragma: no-cache'); // HTTP 1.0.
		header('Expires: Thu, 01 Dec 1994 16:00:00 GMT'); // Proxies

		// Support for Conditional GET
		$client_etag = isset($_SERVER['HTTP_IF_NONE_MATCH'])?stripslashes($_SERVER['HTTP_IF_NONE_MATCH']):false;

		if(!isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
			$_SERVER['HTTP_IF_MODIFIED_SINCE'] = false;

		$client_last_modified = trim($_SERVER['HTTP_IF_MODIFIED_SINCE']);
		// If string is empty, return 0. If not, attempt to parse into a timestamp
		$client_modified_timestamp = $client_last_modified?strtotime($client_last_modified):0;

		// Make a timestamp for our most recent modification...
		$modified_timestamp = strtotime($last_modified);

		if(($client_last_modified && $client_etag)
			?(($client_modified_timestamp >= $modified_timestamp) && ($client_etag == $etag))
			:(($client_modified_timestamp >= $modified_timestamp) || ($client_etag == $etag))
		){
			status_header(304);
			exit;
		}

	}else{
		//--FORCE DOWNLOAD Functions-----------------------//

		// required for IE, otherwise Content-disposition is ignored
		if(ini_get('zlib.output_compression'))
			ini_set('zlib.output_compression', 'Off');

		header('Pragma: public'); // required
		header('Expires: 0');
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
		header('Cache-Control: private', false); // required for certain browsers
		header('Content-Disposition: attachment; filename="'.$file_info['basename'].'";');
		header('Content-Transfer-Encoding: binary');

	}

	// If we made it this far, just serve the file
	if(ob_get_length())
		ob_clean();
	$filesize = filesize($file);
	//Handel partial request
	header("Accept-Ranges: 0-$filesize");
	$buffer_size = 1024 * 1024; //1MB #bigger = more ram usage but less cpu
	if(isset($_SERVER['HTTP_RANGE'])){
		preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
		$offset = intval($matches[1]);
		$length = intval(isset($matches[2])?intval($matches[2]) - $offset:$filesize - $offset);
		if($length < 1) $length = $filesize - $offset;
		if($length > $buffer_size*10) $length = $buffer_size*10;//limit max partial *will trigger a ERR_CONTENT_LENGTH_MISMATCH on client but will perform better...
		header('HTTP/1.1 206 Partial Content');
		header('Content-Range: bytes '.$offset.'-'.($offset + $length).'/'.$filesize);
		$file = fopen($file, 'r');

		// seek to the requested offset, this is 0 if it's not a partial content request
		fseek($file, $offset);
		//split the file so we could <code>stream</code> just the range we need
		while($length > 0 && !feof($file)){
			if($length > $buffer_size)
				$bytes_to_read = $buffer_size;
			else
				$bytes_to_read = $length;
			$length -= $bytes_to_read;
			echo fread($file, $bytes_to_read);
			flush();
		}
		fclose($file);
		exit;
	}
	flush();
	readfile($file);
	exit;
}
Very useful
By , for WP 4.3.1

Found it while looking for restriction view access - it's just what I needed, thanks a lot!

Great, but the future?
By , for WP 4.4

Recently installed and started using this plugin and it works wonderfully. But, seeing how long it has been since last being updated, I do worry if it will break in some future WP update. For now, all good. Let's hope someone keeps this plugin active as I didn't see any other plugin trying to solve this problem (which, itself, was a huge surprise).

Looks great
By , for WP 4.3.1

I installed this plug-in 2 minutes ago, it was absolutely straigh forward and does exactly what I expected. This plug-in deserves more attention from the WordPress community since it solves a major security problem of WordPress. Hopefully the developer continues his work. And yes: We would pay for this plug-in as well!

Best content protection going!
By , for WP 4.2.3

Everyone has this problem, you want to actually truly hide images or pdfs or other binary files and frankly, wordpress is terrible at this.

Not anymore, Media Vault nails it.

It takes a little bit to get in the groove of how it works but once you experiment with it for 10m you will be happily protecting all of your content!

I use the custom role type hooks to do specially checking before I provide access which has been fantastic since we do a ton of custom theme and wordpress application development.

Well worth it.

Great plugin
By , for WP 4.2.2

Does exactly what is says and does exactly what I need. Thanks

this plugin rocks
By , for WP 4.1.1

very easy and customizable easy like 1,2,3

I like the plug in
By , for WP 4.1.1

I'm glad that I tried this plugin! Its nice to know that you can click a button and all uploaded files to wp-content/uploads will be secured as they upload. Its also nice to have a selection option for files already in the library. My Zip files and mp4 files can be protected using another plugin and I can restrict these types of files from being viewed by different membership levels for each page I protect but before I found this plug in... uploading to the library was not secure! All anyone has to do is just access your wordpress library and there is the photo or video! So thanks so much for that and well... I am giving you an excellent review!
(There is always a but)

In my case, I have different levels of members and each level can view different photos. It sure would be nice to be able to integrate those levels into the protection scheme. As it stands now, all you have to be is a "logged on member" and doing so... level 1 members can view the files available for levels 2, 3, 4, ect. That is the only downside I have seen. Other than that... great plug in and so nice to be able to trust it... it seems like everything else wordpress related often has an issue and waking up the next morning and turning on my computer to see what exploded overnight is always an experience. Thanks ~Kelly

Excellent
By , for WP 4.1

This plug-in provides what I really want to do.
I can create secure closed community site.

Use
By , for WP 4.1

Very simple to use.

You must log in to submit a review. You can also log in or register using the form near the top of this page.