so I am making wordpress website and the idea is that I want to upload different files for the different users but I want the user to see only his files.The problem is that when I copy the url that leeds us to someones file , it can be downloaded without user to be logged in.SO how to make a restriction that only one wordpress user to have one folder that he can download files from it ? I tried with chown in the php file that is caring for the post request but it give's me an error.
-
1You could always create a url_rewrite that is public facing who's logic is to process the request and serve the file only if conditions are met. – jgraup Feb 26 '16 at 19:46
One solution might be to directly restrict access to the file on the server, but utilize a url rewrite
to display the content -- only if the id matches in the request. Obviously this doesn't answer every question in the scenario but it does provide a proof-of-concept to indirectly convert a url into a file.
When you upload a file you could store a reference in the user metadata
instead of having to track custom folders of content.
This essentially provides access to this file:
http://example.dev/wp-content/uploads/2015/12/8-1200x675.jpg
If user ID 1 is requesting access and is logged in
http://example.dev/api/file/1/2015/12/8-1200x675.jpg
<?php
if ( ! class_exists( 'FileRequest' ) ):
class FileRequest {
const ENDPOINT_QUERY_NAME = 'api/file';
const ENDPOINT_QUERY_PARAM = '__api_file';
// WordPress hooks
public function init() {
add_filter( 'query_vars', array ( $this, 'add_query_vars' ), 0 );
add_action( 'parse_request', array ( $this, 'sniff_requests' ), 0 );
add_action( 'init', array ( $this, 'add_endpoint' ), 0 );
}
// Add public query vars
public function add_query_vars( $vars ) {
// add all the things we know we'll use
$vars[] = static::ENDPOINT_QUERY_PARAM;
$vars[] = 'file';
$vars[] = 'user';
return $vars;
}
// Add API Endpoint
public function add_endpoint() {
add_rewrite_rule( '^' . static::ENDPOINT_QUERY_NAME . '/([^/]*)/(\S+)/?', 'index.php?' . static::ENDPOINT_QUERY_PARAM . '=1&user=$matches[1]&file=$matches[2]', 'top' );
//////////////////////////////////
flush_rewrite_rules( false ); //// <---------- REMOVE THIS WHEN DONE
//////////////////////////////////
}
// Sniff Requests
public function sniff_requests( $wp_query ) {
global $wp;
if ( isset(
$wp->query_vars[ static::ENDPOINT_QUERY_PARAM ],
$wp->query_vars[ 'file' ],
$wp->query_vars[ 'user' ] ) ) {
$this->handle_request(); // handle it
}
}
// Handle Requests
protected function handle_request() {
global $wp;
$file = $wp->query_vars[ 'file' ];
$user = $wp->query_vars[ 'user' ];
// make sure the request ID is the same as the logged in user
if ( ''.get_current_user_id() !== $user ){
wp_send_json_error( array (
'message' => 'Unauthorized',
'error' => '401',
) );
}
else {
// add the file request to the uploads directory
$upload_dir = wp_upload_dir();
$path = $upload_dir['basedir'].'/'.$file;
// make sure url is readable -- if not, stop!
if ( ! is_readable( $path ) ) {
wp_send_json_error( array (
'message' => 'Bad Request',
'error' => '400',
) );
}
// get files contents
$file_content = file_get_contents( $path );
// get the mime type for headers
$type = get_post_mime_type( $file_content );
// output headers
nocache_headers();
header( "Content-type: $type;" );
header( "Content-Length: " . strlen( $file_content ) );
// output file data
echo $file_content;
}
die();
}
}
$wpFileRequest = new FileRequest();
$wpFileRequest->init();
endif; // FileRequest
-
-
In your functions.php or a plugin if you want it to persist between plugins. – jgraup Feb 29 '16 at 16:38
-
Thanks a lot .I have set the folders to permission 0700 and change a little your code because if the url have space it's %20 and the file wont be found. – George Dimov Mar 1 '16 at 8:13
-
Take a look at roots.io/routing-wp-requests to better understand all these parts. – jgraup Mar 1 '16 at 20:13