-2

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.

  • 1
    You 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
1

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
  • Thanks but where to put those lines of code ? – George Dimov Feb 29 '16 at 16:37
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.