Commit 250bcfa8 authored by Craig Andrews's avatar Craig Andrews

Require users to login to view attachments on private sites

Thank you jeff-themovie for this implementation!
parent 7e01bb8d
...@@ -710,11 +710,21 @@ private site, but users of the private site may be able to subscribe ...@@ -710,11 +710,21 @@ private site, but users of the private site may be able to subscribe
to users on a remote site. (Or not... it's not well tested.) The to users on a remote site. (Or not... it's not well tested.) The
"proper behaviour" hasn't been defined here, so handle with care. "proper behaviour" hasn't been defined here, so handle with care.
If fancy URLs is enabled, access to file attachments can also be Access to file attachments can also be restricted to logged-in users only.
restricted to logged-in users only. Uncomment the appropriate rewrite 1. Add a directory outside the web root where your file uploads will be
rule in .htaccess or your server's httpd.conf. (This most likely will stored. Usually a command like this will work:
not work if you are using a virtual server for attachments, so consider
the performance/security tradeoff.) mkdir /var/www/mublog-files
2. Make the file uploads directory writeable by the web server. An
insecure way to do this is:
chmod a+x /var/www/mublog-files
3. Tell StatusNet to use this directory for file uploads. Add a line
like this to your config.php:
$config['attachments']['dir'] = '/var/www/mublog-files';
Upgrading Upgrading
========= =========
......
<?php <?php
/** /**
* StatusNet, the distributed open-source microblogging tool * StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2009, StatusNet, Inc.
* *
* Returns a given file attachment, allowing private sites to only allow * Return a requested file
* access to file attachments after login.
* *
* PHP version 5 * PHP version 5
* *
* LICENCE: This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
...@@ -20,28 +20,32 @@ ...@@ -20,28 +20,32 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* @category Personal * @category PrivateAttachments
* @package StatusNet * @package StatusNet
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @copyright 2008-2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/ * @link http://status.net/
*/ */
if (!defined('STATUSNET') && !defined('LACONICA')) { if (!defined('STATUSNET')) {
exit(1); exit(1);
} }
require_once 'MIME/Type.php'; require_once 'MIME/Type.php';
/** /**
* Action for getting a file attachment * An action for returning a requested file
* *
* @category Personal * The StatusNet system will do an implicit user check if the site is
* @package StatusNet * private before allowing this to continue
* @author Jeffery To <jeffery.to@gmail.com> *
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @category PrivateAttachments
* @link http://status.net/ * @package StatusNet
* @author Jeffery To <jeffery.to@gmail.com>
* @copyright 2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/ */
class GetfileAction extends Action class GetfileAction extends Action
...@@ -68,7 +72,7 @@ class GetfileAction extends Action ...@@ -68,7 +72,7 @@ class GetfileAction extends Action
$path = null; $path = null;
if ($filename) { if ($filename) {
$path = common_config('attachments', 'dir') . $filename; $path = File::path($filename);
} }
if (empty($path) or !file_exists($path)) { if (empty($path) or !file_exists($path)) {
...@@ -103,6 +107,10 @@ class GetfileAction extends Action ...@@ -103,6 +107,10 @@ class GetfileAction extends Action
function lastModified() function lastModified()
{ {
if (common_config('site', 'use_x_sendfile')) {
return null;
}
return filemtime($this->path); return filemtime($this->path);
} }
...@@ -114,8 +122,24 @@ class GetfileAction extends Action ...@@ -114,8 +122,24 @@ class GetfileAction extends Action
* *
* @return string etag http header * @return string etag http header
*/ */
function etag() function etag()
{ {
if (common_config('site', 'use_x_sendfile')) {
return null;
}
$cache = common_memcache();
if($cache) {
$key = common_cache_key('attachments:etag:' . $this->path);
$etag = $cache->get($key);
if($etag === false) {
$etag = crc32(file_get_contents($this->path));
$cache->set($key,$etag);
}
return $etag;
}
$stat = stat($this->path); $stat = stat($this->path);
return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"'; return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
} }
...@@ -133,13 +157,19 @@ class GetfileAction extends Action ...@@ -133,13 +157,19 @@ class GetfileAction extends Action
// undo headers set by PHP sessions // undo headers set by PHP sessions
$sec = session_cache_expire() * 60; $sec = session_cache_expire() * 60;
header('Expires: ' . date(DATE_RFC1123, time() + $sec)); header('Expires: ' . date(DATE_RFC1123, time() + $sec));
header('Cache-Control: public, max-age=' . $sec); header('Cache-Control: max-age=' . $sec);
header('Pragma: public');
parent::handle($args); parent::handle($args);
$path = $this->path; $path = $this->path;
header('Content-Type: ' . MIME_Type::autoDetect($path)); header('Content-Type: ' . MIME_Type::autoDetect($path));
readfile($path);
if (common_config('site', 'use_x_sendfile')) {
header('X-Sendfile: ' . $path);
} else {
header('Content-Length: ' . filesize($path));
readfile($path);
}
} }
} }
...@@ -182,25 +182,32 @@ class File extends Memcached_DataObject ...@@ -182,25 +182,32 @@ class File extends Memcached_DataObject
static function url($filename) static function url($filename)
{ {
$path = common_config('attachments', 'path'); if(common_config('site','private')) {
if ($path[strlen($path)-1] != '/') { return common_local_url('getfile',
$path .= '/'; array('filename' => $filename));
}
if ($path[0] != '/') { } else {
$path = '/'.$path; $path = common_config('attachments', 'path');
}
$server = common_config('attachments', 'server'); if ($path[strlen($path)-1] != '/') {
$path .= '/';
}
if (empty($server)) { if ($path[0] != '/') {
$server = common_config('site', 'server'); $path = '/'.$path;
} }
$server = common_config('attachments', 'server');
// XXX: protocol if (empty($server)) {
$server = common_config('site', 'server');
}
return 'http://'.$server.$path.$filename; // XXX: protocol
return 'http://'.$server.$path.$filename;
}
} }
function getEnclosure(){ function getEnclosure(){
......
...@@ -41,6 +41,20 @@ $config['site']['path'] = 'statusnet'; ...@@ -41,6 +41,20 @@ $config['site']['path'] = 'statusnet';
// Make the site invisible to non-logged-in users // Make the site invisible to non-logged-in users
// $config['site']['private'] = true; // $config['site']['private'] = true;
// If your web server supports X-Sendfile (Apache with mod_xsendfile,
// lighttpd, nginx), you can enable X-Sendfile support for better
// performance. Presently, only attachment serving when the site is
// in private mode will use X-Sendfile.
// $config['site']['X-Sendfile'] = false;
// You may also need to enable X-Sendfile support for your web server and
// allow it to access files outside of the web root. For Apache with
// mod_xsendfile, you can add these to your .htaccess or server config:
//
// XSendFile on
// XSendFileAllowAbove on
//
// See http://tn123.ath.cx/mod_xsendfile/ for mod_xsendfile.
// If you want logging sent to a file instead of syslog // If you want logging sent to a file instead of syslog
// $config['site']['logfile'] = '/tmp/statusnet.log'; // $config['site']['logfile'] = '/tmp/statusnet.log';
...@@ -265,6 +279,7 @@ $config['sphinx']['port'] = 3312; ...@@ -265,6 +279,7 @@ $config['sphinx']['port'] = 3312;
// $config['attachments']['user_quota'] = 50000000; // $config['attachments']['user_quota'] = 50000000;
// $config['attachments']['monthly_quota'] = 15000000; // $config['attachments']['monthly_quota'] = 15000000;
// $config['attachments']['uploads'] = true; // $config['attachments']['uploads'] = true;
// $config['attachments']['path'] = "/file/"; // $config['attachments']['path'] = "/file/"; //ignored if site is private
// $config['attachments']['dir'] = INSTALLDIR . '/file/';
// $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/'; // $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/';
...@@ -5,14 +5,6 @@ ...@@ -5,14 +5,6 @@
RewriteBase /mublog/ RewriteBase /mublog/
# If your site is private and want to only allow logged-in users to
# be able to download file attachments, uncomment this rule.
#
# If you have a custom attachment path
# ($config['attachments']['path']), change "file/" to match.
#
#RewriteRule ^file/(.*) getfile/$1
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?p=$1 [L,QSA] RewriteRule (.*) index.php?p=$1 [L,QSA]
......
...@@ -54,6 +54,7 @@ $default = ...@@ -54,6 +54,7 @@ $default =
'dupelimit' => 60, # default for same person saying the same thing 'dupelimit' => 60, # default for same person saying the same thing
'textlimit' => 140, 'textlimit' => 140,
'indent' => true, 'indent' => true,
'use_x_sendfile' => false,
), ),
'db' => 'db' =>
array('database' => 'YOU HAVE TO SET THIS IN config.php', array('database' => 'YOU HAVE TO SET THIS IN config.php',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment