Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a multisite which I use for sharing private information (and files like pdf etc). Each client has its own 'site' example.com/client1, example.com/client2 etc

I already set permissions to subscriber of its own 'blog' only using a variety of plugins like more privacy options, multisite user management etc...

This works very well, every client can only access its own blog. People without login information cant access any blog, not even the mainsite. So this works correctly.

Then I adapted the Twenty eleven theme so that under every post/page there's a list of all uploaded media to that post (pdf, jpg, png...).

    <table class="filelist" width="100%" border="0" cellspacing="5" cellpadding="0">

<?php

$args = array(
    'post_type' => 'attachment',
    'numberposts' => -1,
    'post_status' => null,
    'orderby'         => 'title',
    'order'           => 'ASC',
    'post_parent' => $post->ID
    ); 
$attachments = get_posts($args);
if ($attachments) {
    foreach ($attachments as $post) {
        setup_postdata($post);

        $docsize = @filesize( wp_get_attachment_url($post->ID) );
        if (FALSE === $docsize)
            $docsize = 0;
        else
            $docsize = size_format($docsize);

         echo '<tr><td width="90%"><a href="' . wp_get_attachment_url($post->ID) . '" target="_blank">' . $post->post_title . '</a></td><td witdh="10%">'.  getFileExt(wp_get_attachment_url($post->ID, false)) . '</a></td></tr>';
    }
}

?>
</table>

But it prints the direct link: http://example.tld/client/wp-content/someotherdirs/file.pdf.

Not every client is that smart not to share those links with other people... So I want a check if a user is logged in before the file gets served. It gives a 403 if access denied etc etc...

So I tried various options with .htaccess redirects, dl-file.php and dl-files.php, modified ms-files.php etc...

rewrite rules:

RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.+) dl-file.php?file=$1 [QSA,L]
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-content/uploads/(.+) dl-file.php?file=$1 [QSA,L]

dl-file.php

<?php
/*
 * dl-file.php
 *
 * Protect uploaded files with login.
 * 
 * @link http://wordpress.stackexchange.com/questions/37144/protect-wordpress-uploads-if-user-is-not-logged-in
 * 
 * @author hakre <http://hakre.wordpress.com/>
 * @license GPL-3.0+
 * @registry SPDX
 */

require_once('wp-load.php');

is_user_logged_in() ||  auth_redirect();

list($basedir) = array_values(array_intersect_key(wp_upload_dir(), array('basedir' => 1)))+array(NULL);

$file =  rtrim($basedir,'/').'/'.str_replace('..', '', isset($_GET[ 'file' ])?$_GET[ 'file' ]:'');
if (!$basedir || !is_file($file)) {
    status_header(404);
    die('404 &#8212; File not found....');
}

$mime = wp_check_filetype($file);
if( false === $mime[ 'type' ] && function_exists( 'mime_content_type' ) )
    $mime[ 'type' ] = mime_content_type( $file );

if( $mime[ 'type' ] )
    $mimetype = $mime[ 'type' ];
else
    $mimetype = 'image/' . substr( $file, strrpos( $file, '.' ) + 1 );

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

$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( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 100000000 ) . ' GMT' );

// 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;
}

// If we made it this far, just serve the file
readfile( $file );

I have read multiple questions and answers on the site... But nothing works for 3.5+ at least...

maybe someone can help because I think i'm quite close as every file in the wp-content/uploads dir gets processed by file.php first.

But it gives a 404 error when i'm logged in (this is bad;)) and redirects to the loginpage if i'm logged out (this is good)

thanks

share|improve this question
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.