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.
-If fancy URLs is enabled, access to file attachments can also be
-restricted to logged-in users only. Uncomment the appropriate rewrite
-rule in .htaccess or your server's httpd.conf. (This most likely will
-not work if you are using a virtual server for attachments, so consider
-the performance/security tradeoff.)
+Access to file attachments can also be restricted to logged-in users only.
+1. Add a directory outside the web root where your file uploads will be
+ stored. Usually a command like this will work:
+
+ 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
=========
<?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
- * access to file attachments after login.
+ * Return a requested file
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 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/>.
*
- * @category Personal
+ * @category PrivateAttachments
* @package StatusNet
* @author Jeffery To <jeffery.to@gmail.com>
- * @copyright 2008-2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
-if (!defined('STATUSNET') && !defined('LACONICA')) {
+if (!defined('STATUSNET')) {
exit(1);
}
require_once 'MIME/Type.php';
/**
- * Action for getting a file attachment
+ * An action for returning a requested file
*
- * @category Personal
- * @package StatusNet
- * @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
- * @link http://status.net/
+ * The StatusNet system will do an implicit user check if the site is
+ * private before allowing this to continue
+ *
+ * @category PrivateAttachments
+ * @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
$path = null;
if ($filename) {
- $path = common_config('attachments', 'dir') . $filename;
+ $path = File::path($filename);
}
if (empty($path) or !file_exists($path)) {
function lastModified()
{
+ if (common_config('site', 'use_x_sendfile')) {
+ return null;
+ }
+
return filemtime($this->path);
}
*
* @return string etag http header
*/
+
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);
return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
}
// undo headers set by PHP sessions
$sec = session_cache_expire() * 60;
header('Expires: ' . date(DATE_RFC1123, time() + $sec));
- header('Cache-Control: public, max-age=' . $sec);
- header('Pragma: public');
+ header('Cache-Control: max-age=' . $sec);
parent::handle($args);
$path = $this->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);
+ }
}
}
static function url($filename)
{
- $path = common_config('attachments', 'path');
+ if(common_config('site','private')) {
- if ($path[strlen($path)-1] != '/') {
- $path .= '/';
- }
+ return common_local_url('getfile',
+ array('filename' => $filename));
- if ($path[0] != '/') {
- $path = '/'.$path;
- }
+ } else {
+ $path = common_config('attachments', 'path');
- $server = common_config('attachments', 'server');
+ if ($path[strlen($path)-1] != '/') {
+ $path .= '/';
+ }
- if (empty($server)) {
- $server = common_config('site', 'server');
- }
+ if ($path[0] != '/') {
+ $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(){
// Make the site invisible to non-logged-in users
// $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
// $config['site']['logfile'] = '/tmp/statusnet.log';
// $config['attachments']['user_quota'] = 50000000;
// $config['attachments']['monthly_quota'] = 15000000;
// $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/';
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} !-d
RewriteRule (.*) index.php?p=$1 [L,QSA]
'dupelimit' => 60, # default for same person saying the same thing
'textlimit' => 140,
'indent' => true,
+ 'use_x_sendfile' => false,
),
'db' =>
array('database' => 'YOU HAVE TO SET THIS IN config.php',