mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-07 20:08:53 +00:00
Merge pull request #5274 from rubencm/ticket/14285
[ticket/14285] Move downloads to controller
This commit is contained in:
commit
37ebf41308
26 changed files with 1037 additions and 1335 deletions
|
@ -192,6 +192,9 @@ class phpbb_Sniffs_Namespaces_UnusedUseSniff implements Sniff
|
|||
{
|
||||
$ok = $this->check($phpcsFile, $param['type_hint'], $class_name_full, $class_name_short, $function_declaration) || $ok;
|
||||
}
|
||||
|
||||
$method_properties = $phpcsFile->getMethodProperties($function_declaration);
|
||||
$ok = $this->check($phpcsFile, $method_properties['return_type'], $class_name_full, $class_name_short, $function_declaration) || $ok;
|
||||
}
|
||||
|
||||
// Checks in catch blocks
|
||||
|
|
|
@ -56,6 +56,7 @@ services:
|
|||
class: phpbb\avatar\driver\upload
|
||||
arguments:
|
||||
- '@config'
|
||||
- '@controller.helper'
|
||||
- '%core.root_path%'
|
||||
- '%core.php_ext%'
|
||||
- '@storage.avatar'
|
||||
|
|
|
@ -82,3 +82,28 @@ services:
|
|||
arguments:
|
||||
tags:
|
||||
- { name: storage.provider }
|
||||
|
||||
# Controllers
|
||||
storage.controller.avatar:
|
||||
class: phpbb\storage\controller\avatar
|
||||
arguments:
|
||||
- '@cache'
|
||||
- '@config'
|
||||
- '@dbal.conn'
|
||||
- '@storage.avatar'
|
||||
- '@symfony_request'
|
||||
|
||||
storage.controller.attachment:
|
||||
class: phpbb\storage\controller\attachment
|
||||
arguments:
|
||||
- '@auth'
|
||||
- '@cache'
|
||||
- '@config'
|
||||
- '@content.visibility'
|
||||
- '@dbal.conn'
|
||||
- '@dispatcher'
|
||||
- '@language'
|
||||
- '@request'
|
||||
- '@storage.attachment'
|
||||
- '@symfony_request'
|
||||
- '@user'
|
||||
|
|
|
@ -35,3 +35,7 @@ phpbb_report_routing:
|
|||
phpbb_ucp_routing:
|
||||
resource: ucp.yml
|
||||
prefix: /user
|
||||
|
||||
phpbb_storage_routing:
|
||||
resource: storage.yml
|
||||
prefix: /download
|
||||
|
|
11
phpBB/config/default/routing/storage.yml
Normal file
11
phpBB/config/default/routing/storage.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
phpbb_storage_avatar:
|
||||
path: /avatar/{file}
|
||||
defaults:
|
||||
_controller: storage.controller.avatar:handle
|
||||
|
||||
phpbb_storage_attachment:
|
||||
path: /attachment/{file}
|
||||
defaults:
|
||||
_controller: storage.controller.attachment:handle
|
||||
requirements:
|
||||
id: \d+
|
|
@ -11,310 +11,45 @@
|
|||
*
|
||||
*/
|
||||
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
define('IN_PHPBB', true);
|
||||
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
|
||||
$phpEx = substr(strrchr(__FILE__, '.'), 1);
|
||||
|
||||
// Thank you sun.
|
||||
if (isset($_SERVER['CONTENT_TYPE']))
|
||||
{
|
||||
if ($_SERVER['CONTENT_TYPE'] === 'application/x-java-archive')
|
||||
{
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Java') !== false)
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_GET['avatar']))
|
||||
{
|
||||
require($phpbb_root_path . 'includes/startup.' . $phpEx);
|
||||
|
||||
require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
|
||||
$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
|
||||
$phpbb_class_loader->register();
|
||||
|
||||
$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
|
||||
extract($phpbb_config_php_file->get_all());
|
||||
|
||||
if (!defined('PHPBB_ENVIRONMENT'))
|
||||
{
|
||||
@define('PHPBB_ENVIRONMENT', 'production');
|
||||
}
|
||||
|
||||
if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
require($phpbb_root_path . 'includes/constants.' . $phpEx);
|
||||
require($phpbb_root_path . 'includes/functions.' . $phpEx);
|
||||
require($phpbb_root_path . 'includes/functions_download' . '.' . $phpEx);
|
||||
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
|
||||
|
||||
// Setup class loader first
|
||||
$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
|
||||
$phpbb_class_loader_ext->register();
|
||||
|
||||
// Set up container
|
||||
$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
|
||||
$phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
|
||||
|
||||
$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
|
||||
$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
|
||||
|
||||
// set up caching
|
||||
/* @var $cache \phpbb\cache\service */
|
||||
$cache = $phpbb_container->get('cache');
|
||||
|
||||
/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
|
||||
$phpbb_dispatcher = $phpbb_container->get('dispatcher');
|
||||
|
||||
/* @var $request \phpbb\request\request_interface */
|
||||
$request = $phpbb_container->get('request');
|
||||
|
||||
/* @var $db \phpbb\db\driver\driver_interface */
|
||||
$db = $phpbb_container->get('dbal.conn');
|
||||
|
||||
/* @var $phpbb_log \phpbb\log\log_interface */
|
||||
$phpbb_log = $phpbb_container->get('log');
|
||||
|
||||
unset($dbpasswd);
|
||||
|
||||
/* @var $config \phpbb\config\config */
|
||||
$config = $phpbb_container->get('config');
|
||||
|
||||
// load extensions
|
||||
/* @var $phpbb_extension_manager \phpbb\extension\manager */
|
||||
$phpbb_extension_manager = $phpbb_container->get('ext.manager');
|
||||
|
||||
// worst-case default
|
||||
$browser = strtolower($request->header('User-Agent', 'msie 6.0'));
|
||||
|
||||
/* @var $phpbb_avatar_manager \phpbb\avatar\manager */
|
||||
$phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
|
||||
|
||||
if (@is_file($phpbb_root_path . $config['exts_composer_vendor_dir'] . '/autoload.php'))
|
||||
{
|
||||
require_once($phpbb_root_path . $config['exts_composer_vendor_dir'] . '/autoload.php');
|
||||
}
|
||||
|
||||
$filename = $request->variable('avatar', '');
|
||||
$avatar_group = false;
|
||||
$exit = false;
|
||||
|
||||
if (isset($filename[0]) && $filename[0] === 'g')
|
||||
{
|
||||
$avatar_group = true;
|
||||
$filename = substr($filename, 1);
|
||||
}
|
||||
|
||||
// '==' is not a bug - . as the first char is as bad as no dot at all
|
||||
if (strpos($filename, '.') == false)
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
$exit = true;
|
||||
}
|
||||
|
||||
if (!$exit)
|
||||
{
|
||||
$ext = substr(strrchr($filename, '.'), 1);
|
||||
$stamp = (int) substr(stristr($filename, '_'), 1);
|
||||
$filename = (int) $filename;
|
||||
$exit = set_modified_headers($stamp, $browser);
|
||||
}
|
||||
if (!$exit && !in_array($ext, array('png', 'gif', 'jpg', 'jpeg')))
|
||||
{
|
||||
// no way such an avatar could exist. They are not following the rules, stop the show.
|
||||
send_status_line(403, 'Forbidden');
|
||||
$exit = true;
|
||||
}
|
||||
|
||||
|
||||
if (!$exit)
|
||||
{
|
||||
if (!$filename)
|
||||
{
|
||||
// no way such an avatar could exist. They are not following the rules, stop the show.
|
||||
send_status_line(403, 'Forbidden');
|
||||
}
|
||||
else
|
||||
{
|
||||
send_avatar_to_browser(($avatar_group ? 'g' : '') . $filename . '.' . $ext, $browser);
|
||||
}
|
||||
}
|
||||
file_gc();
|
||||
}
|
||||
|
||||
// implicit else: we are not in avatar mode
|
||||
include($phpbb_root_path . 'common.' . $phpEx);
|
||||
require($phpbb_root_path . 'includes/functions_download' . '.' . $phpEx);
|
||||
|
||||
// Start session management
|
||||
$user->session_begin();
|
||||
$auth->acl($user->data);
|
||||
|
||||
/** @var \phpbb\controller\helper $controller_helper */
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
if ($request->is_set('avatar'))
|
||||
{
|
||||
$response = new RedirectResponse(
|
||||
$controller_helper->route('phpbb_storage_avatar', array(
|
||||
'file' => $request->variable('avatar', ''),
|
||||
), false),
|
||||
301
|
||||
);
|
||||
$response->send();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
$attach_id = $request->variable('id', 0);
|
||||
$mode = $request->variable('mode', '');
|
||||
$thumbnail = $request->variable('t', false);
|
||||
|
||||
// Start session management, do not update session page.
|
||||
$user->session_begin(false);
|
||||
$auth->acl($user->data);
|
||||
$user->setup('viewtopic');
|
||||
|
||||
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
|
||||
|
||||
if (!$config['allow_attachments'] && !$config['allow_pm_attach'])
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED');
|
||||
}
|
||||
|
||||
if (!$attach_id)
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('NO_ATTACHMENT_SELECTED');
|
||||
}
|
||||
|
||||
$sql = 'SELECT attach_id, post_msg_id, topic_id, in_message, poster_id, is_orphan, physical_filename, real_filename, extension, mimetype, filesize, filetime
|
||||
FROM ' . ATTACHMENTS_TABLE . "
|
||||
WHERE attach_id = $attach_id";
|
||||
$result = $db->sql_query($sql);
|
||||
$attachment = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if (!$attachment)
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
else if (!download_allowed())
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error($user->lang['LINKAGE_FORBIDDEN']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$attachment['physical_filename'] = utf8_basename($attachment['physical_filename']);
|
||||
|
||||
if (!$attachment['in_message'] && !$config['allow_attachments'] || $attachment['in_message'] && !$config['allow_pm_attach'])
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED');
|
||||
}
|
||||
|
||||
if ($attachment['is_orphan'])
|
||||
{
|
||||
// We allow admins having attachment permissions to see orphan attachments...
|
||||
$own_attachment = ($auth->acl_get('a_attach') || $attachment['poster_id'] == $user->data['user_id']) ? true : false;
|
||||
|
||||
if (!$own_attachment || ($attachment['in_message'] && !$auth->acl_get('u_pm_download')) || (!$attachment['in_message'] && !$auth->acl_get('u_download')))
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
|
||||
// Obtain all extensions...
|
||||
$extensions = $cache->obtain_attach_extensions(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$attachment['in_message'])
|
||||
{
|
||||
phpbb_download_handle_forum_auth($db, $auth, $attachment['topic_id']);
|
||||
|
||||
$sql = 'SELECT forum_id, post_visibility
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $attachment['post_msg_id'];
|
||||
$result = $db->sql_query($sql);
|
||||
$post_row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if (!$post_row || !$phpbb_content_visibility->is_visible('post', $post_row['forum_id'], $post_row))
|
||||
{
|
||||
// Attachment of a soft deleted post and the user is not allowed to see the post
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attachment is in a private message.
|
||||
$post_row = array('forum_id' => false);
|
||||
phpbb_download_handle_pm_auth($db, $auth, $user->data['user_id'], $attachment['post_msg_id']);
|
||||
}
|
||||
|
||||
$extensions = array();
|
||||
if (!extension_allowed($post_row['forum_id'], $attachment['extension'], $extensions))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error(sprintf($user->lang['EXTENSION_DISABLED_AFTER_POSTING'], $attachment['extension']));
|
||||
}
|
||||
}
|
||||
|
||||
$display_cat = $extensions[$attachment['extension']]['display_cat'];
|
||||
|
||||
if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))
|
||||
{
|
||||
$display_cat = ATTACHMENT_CATEGORY_NONE;
|
||||
}
|
||||
|
||||
if ($thumbnail)
|
||||
{
|
||||
$attachment['physical_filename'] = 'thumb_' . $attachment['physical_filename'];
|
||||
}
|
||||
else if ($display_cat == ATTACHMENT_CATEGORY_NONE && !$attachment['is_orphan'] && !phpbb_http_byte_range($attachment['filesize']))
|
||||
{
|
||||
// Update download count
|
||||
phpbb_increment_downloads($db, $attachment['attach_id']);
|
||||
}
|
||||
|
||||
$redirect = '';
|
||||
|
||||
/**
|
||||
* Event to modify data before sending file to browser
|
||||
*
|
||||
* @event core.download_file_send_to_browser_before
|
||||
* @var int attach_id The attachment ID
|
||||
* @var array attachment Array with attachment data
|
||||
* @var int display_cat Attachment category
|
||||
* @var array extensions Array with file extensions data
|
||||
* @var string mode Download mode
|
||||
* @var bool thumbnail Flag indicating if the file is a thumbnail
|
||||
* @var string redirect Do a redirection instead of reading the file
|
||||
* @since 3.1.6-RC1
|
||||
* @changed 3.1.7-RC1 Fixing wrong name of a variable (replacing "extension" by "extensions")
|
||||
* @changed 3.3.0-a1 Add redirect variable
|
||||
*/
|
||||
$vars = array(
|
||||
'attach_id',
|
||||
'attachment',
|
||||
'display_cat',
|
||||
'extensions',
|
||||
'mode',
|
||||
'thumbnail',
|
||||
'redirect',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.download_file_send_to_browser_before', compact($vars)));
|
||||
|
||||
if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && (strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7))
|
||||
{
|
||||
wrap_img_in_html(append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'id=' . $attachment['attach_id']), $attachment['real_filename']);
|
||||
file_gc();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!empty($redirect))
|
||||
{
|
||||
redirect($redirect, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_file_to_browser($attachment, $display_cat);
|
||||
}
|
||||
|
||||
file_gc();
|
||||
}
|
||||
}
|
||||
$response = new RedirectResponse(
|
||||
$controller_helper->route('phpbb_storage_attachment', array(
|
||||
'file' => $attach_id,
|
||||
't' => $thumbnail,
|
||||
), false),
|
||||
301
|
||||
);
|
||||
$response->send();
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
/**
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
use phpbb\attachment\manager;
|
||||
use phpbb\config\config;
|
||||
use phpbb\controller\helper;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\filesystem\filesystem_interface;
|
||||
use phpbb\language\language;
|
||||
use phpbb\template\template;
|
||||
use phpbb\user;
|
||||
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
|
@ -21,30 +31,33 @@ if (!defined('IN_PHPBB'))
|
|||
|
||||
class acp_attachments
|
||||
{
|
||||
/** @var \phpbb\db\driver\driver_interface */
|
||||
/** @var driver_interface */
|
||||
protected $db;
|
||||
|
||||
/** @var \phpbb\config\config */
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
/** @var \phpbb\language\language */
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var ContainerBuilder */
|
||||
protected $phpbb_container;
|
||||
|
||||
/** @var \phpbb\template\template */
|
||||
/** @var template */
|
||||
protected $template;
|
||||
|
||||
/** @var \phpbb\user */
|
||||
/** @var user */
|
||||
protected $user;
|
||||
|
||||
/** @var \phpbb\filesystem\filesystem_interface */
|
||||
/** @var filesystem_interface */
|
||||
protected $filesystem;
|
||||
|
||||
/** @var \phpbb\attachment\manager */
|
||||
/** @var manager */
|
||||
protected $attachment_manager;
|
||||
|
||||
/** @var helper */
|
||||
protected $controller_helper;
|
||||
|
||||
public $id;
|
||||
public $u_action;
|
||||
protected $new_config;
|
||||
|
@ -63,6 +76,7 @@ class acp_attachments
|
|||
$this->phpbb_container = $phpbb_container;
|
||||
$this->filesystem = $phpbb_filesystem;
|
||||
$this->attachment_manager = $phpbb_container->get('attachment.manager');
|
||||
$this->controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
$user->add_lang(array('posting', 'viewtopic', 'acp/attachments'));
|
||||
|
||||
|
@ -1082,8 +1096,8 @@ class acp_attachments
|
|||
'PHYSICAL_FILENAME' => utf8_basename($row['physical_filename']),
|
||||
'ATTACH_ID' => $row['attach_id'],
|
||||
'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '',
|
||||
'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id']))
|
||||
);
|
||||
'U_FILE' => $this->controller_helper->route('phpbb_storage_attachment', ['file' => (int) $row['attach_id']])
|
||||
));
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
|
@ -1270,8 +1284,8 @@ class acp_attachments
|
|||
'S_IN_MESSAGE' => (bool) $row['in_message'],
|
||||
|
||||
'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_id']}&p={$row['post_msg_id']}") . "#p{$row['post_msg_id']}",
|
||||
'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id']))
|
||||
);
|
||||
'U_FILE' => $this->controller_helper->route('phpbb_storage_attachment', ['file' => $row['attach_id']])
|
||||
));
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
/**
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
use phpbb\controller\helper;
|
||||
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
|
@ -36,6 +39,9 @@ class acp_users
|
|||
global $phpbb_dispatcher, $request;
|
||||
global $phpbb_container, $phpbb_log;
|
||||
|
||||
/** @var helper $controller_helper */
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
$user->add_lang(array('posting', 'ucp', 'acp/users'));
|
||||
$this->tpl_name = 'acp_users';
|
||||
|
||||
|
@ -2126,9 +2132,6 @@ class acp_users
|
|||
$decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_flags);
|
||||
}
|
||||
|
||||
/** @var \phpbb\controller\helper $controller_helper */
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_SIGNATURE' => true,
|
||||
|
||||
|
@ -2298,7 +2301,7 @@ class acp_users
|
|||
|
||||
'S_IN_MESSAGE' => $row['in_message'],
|
||||
|
||||
'U_DOWNLOAD' => append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . $row['attach_id']),
|
||||
'U_DOWNLOAD' => $controller_helper->route('phpbb_storage_attachment', ['file' => (int) $row['attach_id']]),
|
||||
'U_VIEW_TOPIC' => $view_topic)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -927,7 +927,7 @@ function parse_cfg_file($filename, $lines = false)
|
|||
}
|
||||
else if (($value[0] == "'" && $value[strlen($value) - 1] == "'") || ($value[0] == '"' && $value[strlen($value) - 1] == '"'))
|
||||
{
|
||||
$value = htmlspecialchars(substr($value, 1, strlen($value)-2), ENT_COMPAT);
|
||||
$value = htmlspecialchars(substr($value, 1, strlen($value) - 2), ENT_COMPAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -944,3 +944,27 @@ function parse_cfg_file($filename, $lines = false)
|
|||
|
||||
return $parsed_items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an url into a simple html page. Used to display attachments in IE.
|
||||
* this is a workaround for now; might be moved to template system later
|
||||
* direct any complaints to 1 Microsoft Way, Redmond
|
||||
*
|
||||
* @deprecated: 3.3.0-dev (To be removed: 4.0.0)
|
||||
*/
|
||||
function wrap_img_in_html($src, $title)
|
||||
{
|
||||
echo '<!DOCTYPE html>';
|
||||
echo '<html>';
|
||||
echo '<head>';
|
||||
echo '<meta charset="utf-8">';
|
||||
echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
|
||||
echo '<title>' . $title . '</title>';
|
||||
echo '</head>';
|
||||
echo '<body>';
|
||||
echo '<div>';
|
||||
echo '<img src="' . $src . '" alt="' . $title . '" />';
|
||||
echo '</div>';
|
||||
echo '</body>';
|
||||
echo '</html>';
|
||||
}
|
||||
|
|
|
@ -1124,6 +1124,9 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count_a
|
|||
|
||||
$storage_attachment = $phpbb_container->get('storage.attachment');
|
||||
|
||||
/** @var \phpbb\controller\helper */
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
//
|
||||
$compiled_attachments = array();
|
||||
|
||||
|
@ -1283,15 +1286,14 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count_a
|
|||
$display_cat = ATTACHMENT_CATEGORY_NONE;
|
||||
}
|
||||
|
||||
$download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']);
|
||||
$download_link = $controller_helper->route('phpbb_storage_attachment', ['file' => (int) $attachment['attach_id']]);
|
||||
$l_downloaded_viewed = 'VIEWED_COUNTS';
|
||||
|
||||
switch ($display_cat)
|
||||
{
|
||||
// Images
|
||||
case ATTACHMENT_CATEGORY_IMAGE:
|
||||
$inline_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']);
|
||||
$download_link .= '&mode=view';
|
||||
$inline_link = $controller_helper->route('phpbb_storage_attachment', ['file' => (int) $attachment['attach_id']]);
|
||||
|
||||
$block_array += array(
|
||||
'S_IMAGE' => true,
|
||||
|
@ -1303,8 +1305,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count_a
|
|||
|
||||
// Images, but display Thumbnail
|
||||
case ATTACHMENT_CATEGORY_THUMB:
|
||||
$thumbnail_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id'] . '&t=1');
|
||||
$download_link .= '&mode=view';
|
||||
$thumbnail_link = $controller_helper->route('phpbb_storage_attachment', ['file' => (int) $attachment['attach_id'], 't' => 1]);
|
||||
|
||||
$block_array += array(
|
||||
'S_THUMBNAIL' => true,
|
||||
|
|
|
@ -1,738 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simplified function to deliver avatars
|
||||
* The argument needs to be checked before calling this function.
|
||||
*/
|
||||
function send_avatar_to_browser($file, $browser)
|
||||
{
|
||||
global $config, $phpbb_container;
|
||||
|
||||
$storage = $phpbb_container->get('storage.avatar');
|
||||
|
||||
$prefix = $config['avatar_salt'] . '_';
|
||||
$file_path = $prefix . $file;
|
||||
|
||||
if ($storage->exists($file_path) && !headers_sent())
|
||||
{
|
||||
$file_info = $storage->file_info($file_path);
|
||||
|
||||
header('Cache-Control: public');
|
||||
|
||||
try
|
||||
{
|
||||
header('Content-Type: ' . $file_info->mimetype);
|
||||
}
|
||||
catch (\phpbb\storage\exception\exception $e)
|
||||
{
|
||||
// Just don't send this header
|
||||
}
|
||||
|
||||
if ((strpos(strtolower($browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7))
|
||||
{
|
||||
header('Content-Disposition: attachment; ' . header_filename($file));
|
||||
|
||||
if (strpos(strtolower($browser), 'msie 6.0') !== false)
|
||||
{
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Content-Disposition: inline; ' . header_filename($file));
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
header('Content-Length: ' . $file_info->size);
|
||||
}
|
||||
catch (\phpbb\storage\exception\exception $e)
|
||||
{
|
||||
// Just don't send this header
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$fp = $storage->read_stream($file_path);
|
||||
$output = fopen('php://output', 'w+b');
|
||||
stream_copy_to_stream($fp, $output);
|
||||
fclose($fp);
|
||||
fclose($output);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
// Send nothing
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an url into a simple html page. Used to display attachments in IE.
|
||||
* this is a workaround for now; might be moved to template system later
|
||||
* direct any complaints to 1 Microsoft Way, Redmond
|
||||
*/
|
||||
function wrap_img_in_html($src, $title)
|
||||
{
|
||||
echo '<!DOCTYPE html>';
|
||||
echo '<html>';
|
||||
echo '<head>';
|
||||
echo '<meta charset="utf-8">';
|
||||
echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
|
||||
echo '<title>' . $title . '</title>';
|
||||
echo '</head>';
|
||||
echo '<body>';
|
||||
echo '<div>';
|
||||
echo '<img src="' . $src . '" alt="' . $title . '" />';
|
||||
echo '</div>';
|
||||
echo '</body>';
|
||||
echo '</html>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send file to browser
|
||||
*/
|
||||
function send_file_to_browser($attachment, $category)
|
||||
{
|
||||
global $user, $db, $phpbb_dispatcher, $request, $phpbb_container;
|
||||
|
||||
$storage = $phpbb_container->get('storage.attachment');
|
||||
|
||||
$filename = $attachment['physical_filename'];
|
||||
|
||||
if (!$storage->exists($filename))
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
|
||||
// Correct the mime type - we force application/octetstream for all files, except images
|
||||
// Please do not change this, it is a security precaution
|
||||
if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0)
|
||||
{
|
||||
$attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream';
|
||||
}
|
||||
|
||||
if (@ob_get_length())
|
||||
{
|
||||
@ob_end_clean();
|
||||
}
|
||||
|
||||
// Now send the File Contents to the Browser
|
||||
try
|
||||
{
|
||||
$file_info = $storage->file_info($filename);
|
||||
$size = $file_info->size;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event to alter attachment before it is sent to browser.
|
||||
*
|
||||
* @event core.send_file_to_browser_before
|
||||
* @var array attachment Attachment data
|
||||
* @var int category Attachment category
|
||||
* @var string filename Path to file, including filename
|
||||
* @var int size File size
|
||||
* @since 3.1.11-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'attachment',
|
||||
'category',
|
||||
'filename',
|
||||
'size',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.send_file_to_browser_before', compact($vars)));
|
||||
|
||||
// To correctly display further errors we need to make sure we are using the correct headers for both (unsetting content-length may not work)
|
||||
|
||||
// Check if headers already sent or not able to get the file contents.
|
||||
if (headers_sent())
|
||||
{
|
||||
send_status_line(500, 'Internal Server Error');
|
||||
trigger_error('UNABLE_TO_DELIVER_FILE');
|
||||
}
|
||||
|
||||
// Make sure the database record for the filesize is correct
|
||||
if ($size > 0 && $size != $attachment['filesize'] && strpos($attachment['physical_filename'], 'thumb_') === false)
|
||||
{
|
||||
// Update database record
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET filesize = ' . (int) $size . '
|
||||
WHERE attach_id = ' . (int) $attachment['attach_id'];
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
// Now the tricky part... let's dance
|
||||
header('Cache-Control: private');
|
||||
|
||||
// Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
|
||||
header('Content-Type: ' . $attachment['mimetype']);
|
||||
|
||||
if (phpbb_is_greater_ie_version($user->browser, 7))
|
||||
{
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
}
|
||||
|
||||
if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
|
||||
{
|
||||
header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'], ENT_COMPAT)));
|
||||
if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
|
||||
{
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'], ENT_COMPAT)));
|
||||
if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
|
||||
{
|
||||
header('X-Download-Options: noopen');
|
||||
}
|
||||
}
|
||||
|
||||
if (!set_modified_headers($attachment['filetime'], $user->browser))
|
||||
{
|
||||
if ($size)
|
||||
{
|
||||
header("Content-Length: $size");
|
||||
}
|
||||
|
||||
// Try to deliver in chunks
|
||||
@set_time_limit(0);
|
||||
|
||||
$fp = $storage->read_stream($filename);
|
||||
|
||||
// Close the db connection before sending the file etc.
|
||||
file_gc(false);
|
||||
|
||||
if ($fp !== false)
|
||||
{
|
||||
$output = fopen('php://output', 'w+b');
|
||||
stream_copy_to_stream($fp, $output);
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a browser friendly UTF-8 encoded filename
|
||||
*/
|
||||
function header_filename($file)
|
||||
{
|
||||
global $request;
|
||||
|
||||
$user_agent = $request->header('User-Agent');
|
||||
|
||||
// There be dragons here.
|
||||
// Not many follows the RFC...
|
||||
if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Konqueror') !== false)
|
||||
{
|
||||
return "filename=" . rawurlencode($file);
|
||||
}
|
||||
|
||||
// follow the RFC for extended filename for the rest
|
||||
return "filename*=UTF-8''" . rawurlencode($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if downloading item is allowed
|
||||
*/
|
||||
function download_allowed()
|
||||
{
|
||||
global $config, $user, $db, $request;
|
||||
|
||||
if (!$config['secure_downloads'])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$url = htmlspecialchars_decode($request->header('Referer'), ENT_COMPAT);
|
||||
|
||||
if (!$url)
|
||||
{
|
||||
return ($config['secure_allow_empty_referer']) ? true : false;
|
||||
}
|
||||
|
||||
// Split URL into domain and script part
|
||||
$url = @parse_url($url);
|
||||
|
||||
if ($url === false)
|
||||
{
|
||||
return ($config['secure_allow_empty_referer']) ? true : false;
|
||||
}
|
||||
|
||||
$hostname = $url['host'];
|
||||
unset($url);
|
||||
|
||||
$allowed = ($config['secure_allow_deny']) ? false : true;
|
||||
$iplist = array();
|
||||
|
||||
if (($ip_ary = @gethostbynamel($hostname)) !== false)
|
||||
{
|
||||
foreach ($ip_ary as $ip)
|
||||
{
|
||||
if ($ip)
|
||||
{
|
||||
$iplist[] = $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for own server...
|
||||
$server_name = $user->host;
|
||||
|
||||
// Forcing server vars is the only way to specify/override the protocol
|
||||
if ($config['force_server_vars'] || !$server_name)
|
||||
{
|
||||
$server_name = $config['server_name'];
|
||||
}
|
||||
|
||||
if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
|
||||
{
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
// Get IP's and Hostnames
|
||||
if (!$allowed)
|
||||
{
|
||||
$sql = 'SELECT site_ip, site_hostname, ip_exclude
|
||||
FROM ' . SITELIST_TABLE;
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$site_ip = trim($row['site_ip']);
|
||||
$site_hostname = trim($row['site_hostname']);
|
||||
|
||||
if ($site_ip)
|
||||
{
|
||||
foreach ($iplist as $ip)
|
||||
{
|
||||
if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
|
||||
{
|
||||
if ($row['ip_exclude'])
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? false : true;
|
||||
break 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($site_hostname)
|
||||
{
|
||||
if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
|
||||
{
|
||||
if ($row['ip_exclude'])
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? false : true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the browser has the file already and set the appropriate headers-
|
||||
* @returns false if a resend is in order.
|
||||
*/
|
||||
function set_modified_headers($stamp, $browser)
|
||||
{
|
||||
global $request;
|
||||
|
||||
// let's see if we have to send the file at all
|
||||
$last_load = $request->header('If-Modified-Since') ? strtotime(trim($request->header('If-Modified-Since'))) : false;
|
||||
|
||||
if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
|
||||
{
|
||||
if ($last_load !== false && $last_load >= $stamp)
|
||||
{
|
||||
send_status_line(304, 'Not Modified');
|
||||
// seems that we need those too ... browsers
|
||||
header('Cache-Control: private');
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param bool $exit Whether to die or not.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function file_gc($exit = true)
|
||||
{
|
||||
global $cache, $db;
|
||||
|
||||
if (!empty($cache))
|
||||
{
|
||||
$cache->unload();
|
||||
}
|
||||
|
||||
$db->sql_close();
|
||||
|
||||
if ($exit)
|
||||
{
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP range support (RFC 2616 Section 14.35)
|
||||
*
|
||||
* Allows browsers to request partial file content
|
||||
* in case a download has been interrupted.
|
||||
*
|
||||
* @param int $filesize the size of the file in bytes we are about to deliver
|
||||
*
|
||||
* @return mixed false if the whole file has to be delivered
|
||||
* associative array on success
|
||||
*/
|
||||
function phpbb_http_byte_range($filesize)
|
||||
{
|
||||
// Only call find_range_request() once.
|
||||
static $request_array;
|
||||
|
||||
if (!$filesize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($request_array))
|
||||
{
|
||||
$request_array = phpbb_find_range_request();
|
||||
}
|
||||
|
||||
return (empty($request_array)) ? false : phpbb_parse_range_request($request_array, $filesize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for HTTP range request in request headers.
|
||||
*
|
||||
* @return mixed false if no request found
|
||||
* array of strings containing the requested ranges otherwise
|
||||
* e.g. array(0 => '0-0', 1 => '123-125')
|
||||
*/
|
||||
function phpbb_find_range_request()
|
||||
{
|
||||
global $request;
|
||||
|
||||
$value = $request->header('Range');
|
||||
|
||||
// Make sure range request starts with "bytes="
|
||||
if (strpos($value, 'bytes=') === 0)
|
||||
{
|
||||
// Strip leading 'bytes='
|
||||
// Multiple ranges can be separated by a comma
|
||||
return explode(',', substr($value, 6));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyses a range request array.
|
||||
*
|
||||
* A range request can contain multiple ranges,
|
||||
* we however only handle the first request and
|
||||
* only support requests from a given byte to the end of the file.
|
||||
*
|
||||
* @param array $request_array array of strings containing the requested ranges
|
||||
* @param int $filesize the full size of the file in bytes that has been requested
|
||||
*
|
||||
* @return mixed false if the whole file has to be delivered
|
||||
* associative array on success
|
||||
* byte_pos_start the first byte position, can be passed to fseek()
|
||||
* byte_pos_end the last byte position
|
||||
* bytes_requested the number of bytes requested
|
||||
* bytes_total the full size of the file
|
||||
*/
|
||||
function phpbb_parse_range_request($request_array, $filesize)
|
||||
{
|
||||
$first_byte_pos = -1;
|
||||
$last_byte_pos = -1;
|
||||
|
||||
// Go through all ranges
|
||||
foreach ($request_array as $range_string)
|
||||
{
|
||||
$range = explode('-', trim($range_string));
|
||||
|
||||
// "-" is invalid, "0-0" however is valid and means the very first byte.
|
||||
if (count($range) != 2 || $range[0] === '' && $range[1] === '')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute defaults
|
||||
if ($range[0] === '')
|
||||
{
|
||||
$range[0] = 0;
|
||||
}
|
||||
|
||||
if ($range[1] === '')
|
||||
{
|
||||
$range[1] = $filesize - 1;
|
||||
}
|
||||
|
||||
if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
|
||||
{
|
||||
// We only support contiguous ranges, no multipart stuff :(
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($range[1] && $range[1] < $range[0])
|
||||
{
|
||||
// The requested range contains 0 bytes.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Return bytes from $range[0] to $range[1]
|
||||
if ($first_byte_pos < 0)
|
||||
{
|
||||
$first_byte_pos = (int) $range[0];
|
||||
}
|
||||
|
||||
$last_byte_pos = (int) $range[1];
|
||||
|
||||
if ($first_byte_pos >= $filesize)
|
||||
{
|
||||
// Requested range not satisfiable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust last-byte-pos if it is absent or greater than the content.
|
||||
if ($range[1] === '' || $last_byte_pos >= $filesize)
|
||||
{
|
||||
$last_byte_pos = $filesize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($first_byte_pos < 0 || $last_byte_pos < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'byte_pos_start' => $first_byte_pos,
|
||||
'byte_pos_end' => $last_byte_pos,
|
||||
'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
|
||||
'bytes_total' => $filesize,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the download count of all provided attachments
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param array|int $ids The attach_id of each attachment
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_increment_downloads($db, $ids)
|
||||
{
|
||||
if (!is_array($ids))
|
||||
{
|
||||
$ids = array($ids);
|
||||
}
|
||||
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET download_count = download_count + 1
|
||||
WHERE ' . $db->sql_in_set('attach_id', $ids);
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authentication when downloading attachments from a post or topic
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param \phpbb\auth\auth $auth The authentication object
|
||||
* @param int $topic_id The id of the topic that we are downloading from
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
$sql_array = array(
|
||||
'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id',
|
||||
'FROM' => array(
|
||||
TOPICS_TABLE => 't',
|
||||
FORUMS_TABLE => 'f',
|
||||
),
|
||||
'WHERE' => 't.topic_id = ' . (int) $topic_id . '
|
||||
AND t.forum_id = f.forum_id',
|
||||
);
|
||||
|
||||
$sql = $db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
|
||||
|
||||
if ($row && !$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row))
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
else if ($row && $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']))
|
||||
{
|
||||
if ($row['forum_password'])
|
||||
{
|
||||
// Do something else ... ?
|
||||
login_forum_box($row);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error('SORRY_AUTH_VIEW_ATTACH');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authentication when downloading attachments from PMs
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param \phpbb\auth\auth $auth The authentication object
|
||||
* @param int $user_id The user id
|
||||
* @param int $msg_id The id of the PM that we are downloading from
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id)
|
||||
{
|
||||
global $phpbb_dispatcher;
|
||||
|
||||
if (!$auth->acl_get('u_pm_download'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error('SORRY_AUTH_VIEW_ATTACH');
|
||||
}
|
||||
|
||||
$allowed = phpbb_download_check_pm_auth($db, $user_id, $msg_id);
|
||||
|
||||
/**
|
||||
* Event to modify PM attachments download auth
|
||||
*
|
||||
* @event core.modify_pm_attach_download_auth
|
||||
* @var bool allowed Whether the user is allowed to download from that PM or not
|
||||
* @var int msg_id The id of the PM to download from
|
||||
* @var int user_id The user id for auth check
|
||||
* @since 3.1.11-RC1
|
||||
*/
|
||||
$vars = array('allowed', 'msg_id', 'user_id');
|
||||
extract($phpbb_dispatcher->trigger_event('core.modify_pm_attach_download_auth', compact($vars)));
|
||||
|
||||
if (!$allowed)
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a user can download from a particular PM
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param int $user_id The user id
|
||||
* @param int $msg_id The id of the PM that we are downloading from
|
||||
*
|
||||
* @return bool Whether the user is allowed to download from that PM or not
|
||||
*/
|
||||
function phpbb_download_check_pm_auth($db, $user_id, $msg_id)
|
||||
{
|
||||
// Check if the attachment is within the users scope...
|
||||
$sql = 'SELECT msg_id
|
||||
FROM ' . PRIVMSGS_TO_TABLE . '
|
||||
WHERE msg_id = ' . (int) $msg_id . '
|
||||
AND (
|
||||
user_id = ' . (int) $user_id . '
|
||||
OR author_id = ' . (int) $user_id . '
|
||||
)';
|
||||
$result = $db->sql_query_limit($sql, 1);
|
||||
$allowed = (bool) $db->sql_fetchfield('msg_id');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the browser is internet explorer version 7+
|
||||
*
|
||||
* @param string $user_agent User agent HTTP header
|
||||
* @param int $version IE version to check against
|
||||
*
|
||||
* @return bool true if internet explorer version is greater than $version
|
||||
*/
|
||||
function phpbb_is_greater_ie_version($user_agent, $version)
|
||||
{
|
||||
if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
|
||||
{
|
||||
$ie_version = (int) $matches[1];
|
||||
return ($ie_version > $version);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -817,7 +817,7 @@ function posting_gen_inline_attachments(&$attachment_data)
|
|||
*/
|
||||
function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true)
|
||||
{
|
||||
global $template, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher;
|
||||
global $template, $config, $phpbb_root_path, $phpEx, $user, $phpbb_dispatcher, $phpbb_container;
|
||||
|
||||
// Some default template variables
|
||||
$template->assign_vars(array(
|
||||
|
@ -845,7 +845,7 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a
|
|||
$hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />';
|
||||
}
|
||||
|
||||
$download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false);
|
||||
$download_link = $phpbb_container->get('controller.helper')->route('phpbb_storage_attachment', ['file' => (int) $attach_row['attach_id']]);
|
||||
|
||||
$attachrow_template_vars[(int) $attach_row['attach_id']] = array(
|
||||
'FILENAME' => utf8_basename($attach_row['real_filename']),
|
||||
|
|
|
@ -1073,6 +1073,7 @@ class bbcode_firstpass extends bbcode
|
|||
if ($pos_domain !== false && $pos_path >= $pos_domain && $pos_ext >= $pos_path)
|
||||
{
|
||||
// Ok, actually we allow linking to some files (this may be able to be extended in some way later...)
|
||||
// @deprecated
|
||||
if (strpos($url, '/' . $check_path . '/download/file.' . $phpEx) !== 0)
|
||||
{
|
||||
return false;
|
||||
|
@ -1534,6 +1535,8 @@ class parse_message extends bbcode_firstpass
|
|||
global $config, $auth, $user, $phpbb_root_path, $phpEx, $db, $request;
|
||||
global $phpbb_container, $phpbb_dispatcher;
|
||||
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
$error = array();
|
||||
|
||||
$num_attachments = count($this->attachment_data);
|
||||
|
@ -1776,7 +1779,7 @@ class parse_message extends bbcode_firstpass
|
|||
|
||||
if (isset($this->plupload) && $this->plupload->is_active())
|
||||
{
|
||||
$download_url = append_sid("{$phpbb_root_path}download/file.{$phpEx}", 'mode=view&id=' . $new_entry['attach_id']);
|
||||
$download_url = $controller_helper->route('phpbb_storage_attachment', ['file' => (int) $new_entry['attach_id']]);
|
||||
|
||||
// Send the client the attachment data to maintain state
|
||||
$json_response->send(array('data' => $this->attachment_data, 'download_url' => $download_url));
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
/**
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
use phpbb\controller\helper;
|
||||
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
|
@ -31,6 +34,9 @@ class ucp_attachments
|
|||
{
|
||||
global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request, $auth;
|
||||
|
||||
/** @var helper $controller_helper */
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
$start = $request->variable('start', 0);
|
||||
$sort_key = $request->variable('sk', 'a');
|
||||
$sort_dir = $request->variable('sd', 'a');
|
||||
|
@ -179,7 +185,7 @@ class ucp_attachments
|
|||
'S_IN_MESSAGE' => $row['in_message'],
|
||||
'S_LOCKED' => !$row['in_message'] && !$auth->acl_get('m_edit', $row['forum_id']) && ($row['forum_status'] == ITEM_LOCKED || $row['topic_status'] == ITEM_LOCKED || $row['post_edit_locked']),
|
||||
|
||||
'U_VIEW_ATTACHMENT' => append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $row['attach_id']),
|
||||
'U_VIEW_ATTACHMENT' => $controller_helper->route('phpbb_storage_attachment', ['file' => (int) $row['attach_id']]),
|
||||
'U_VIEW_TOPIC' => $view_topic)
|
||||
);
|
||||
|
||||
|
|
|
@ -14,7 +14,13 @@
|
|||
namespace phpbb\avatar\driver;
|
||||
|
||||
use bantu\IniGetWrapper\IniGetWrapper;
|
||||
use phpbb\config\config;
|
||||
use phpbb\controller\helper;
|
||||
use phpbb\event\dispatcher_interface;
|
||||
use phpbb\files\factory;
|
||||
use phpbb\path_helper;
|
||||
use phpbb\storage\exception\exception as storage_exception;
|
||||
use phpbb\storage\storage;
|
||||
|
||||
/**
|
||||
* Handles avatars uploaded to the board
|
||||
|
@ -22,17 +28,22 @@ use phpbb\storage\exception\exception as storage_exception;
|
|||
class upload extends \phpbb\avatar\driver\driver
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\storage\storage
|
||||
* @var helper
|
||||
*/
|
||||
private $controller_helper;
|
||||
|
||||
/**
|
||||
* @var storage
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* @var \phpbb\event\dispatcher_interface
|
||||
* @var dispatcher_interface
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* @var \phpbb\files\factory
|
||||
* @var factory
|
||||
*/
|
||||
protected $files_factory;
|
||||
|
||||
|
@ -44,18 +55,20 @@ class upload extends \phpbb\avatar\driver\driver
|
|||
/**
|
||||
* Construct a driver object
|
||||
*
|
||||
* @param \phpbb\config\config $config phpBB configuration
|
||||
* @param config $config phpBB configuration
|
||||
* @param helper $controller_helper
|
||||
* @param string $phpbb_root_path Path to the phpBB root
|
||||
* @param string $php_ext PHP file extension
|
||||
* @param \phpbb\storage\storage phpBB avatar storage
|
||||
* @param \phpbb\path_helper $path_helper phpBB path helper
|
||||
* @param \phpbb\event\dispatcher_interface $dispatcher phpBB Event dispatcher object
|
||||
* @param \phpbb\files\factory $files_factory File classes factory
|
||||
* @param storage $storage phpBB avatar storage
|
||||
* @param path_helper $path_helper phpBB path helper
|
||||
* @param dispatcher_interface $dispatcher phpBB Event dispatcher object
|
||||
* @param factory $files_factory File classes factory
|
||||
* @param IniGetWrapper $php_ini ini_get() wrapper
|
||||
*/
|
||||
public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\storage\storage $storage, \phpbb\path_helper $path_helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\files\factory $files_factory, IniGetWrapper $php_ini)
|
||||
public function __construct(config $config, helper $controller_helper, string $phpbb_root_path, string $php_ext, storage $storage, path_helper $path_helper, dispatcher_interface $dispatcher, factory $files_factory, IniGetWrapper $php_ini)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->controller_helper = $controller_helper;
|
||||
$this->phpbb_root_path = $phpbb_root_path;
|
||||
$this->php_ext = $php_ext;
|
||||
$this->storage = $storage;
|
||||
|
@ -70,10 +83,8 @@ class upload extends \phpbb\avatar\driver\driver
|
|||
*/
|
||||
public function get_data($row)
|
||||
{
|
||||
$root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $this->path_helper->get_web_root_path();
|
||||
|
||||
return array(
|
||||
'src' => $root_path . 'download/file.' . $this->php_ext . '?avatar=' . $row['avatar'],
|
||||
'src' => $this->controller_helper->route('phpbb_storage_avatar', ['file' => $row['avatar']]),
|
||||
'width' => $row['avatar_width'],
|
||||
'height' => $row['avatar_height'],
|
||||
);
|
||||
|
|
|
@ -167,7 +167,9 @@ class helper
|
|||
$content .= implode('<br />', $post_attachments);
|
||||
|
||||
// Convert attachments' relative path to absolute path
|
||||
$content = str_replace($this->path_helper->get_web_root_path() . 'download/file.' . $this->path_helper->get_php_ext(), $this->get_board_url() . '/download/file.' . $this->path_helper->get_php_ext(), $content);
|
||||
$pattern = '#(/app.php)?/download/attachment/#';
|
||||
$replacement = $this->get_board_url() . '\1/download/attachment/';
|
||||
$content = preg_replace($pattern, $replacement, $content);
|
||||
}
|
||||
|
||||
// Remove Comments from inline attachments [ia]
|
||||
|
|
532
phpBB/phpbb/storage/controller/attachment.php
Normal file
532
phpBB/phpbb/storage/controller/attachment.php
Normal file
|
@ -0,0 +1,532 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\storage\controller;
|
||||
|
||||
use phpbb\auth\auth;
|
||||
use phpbb\cache\service;
|
||||
use phpbb\config\config;
|
||||
use phpbb\content_visibility;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\event\dispatcher_interface;
|
||||
use phpbb\exception\http_exception;
|
||||
use phpbb\language\language;
|
||||
use phpbb\request\request;
|
||||
use phpbb\storage\storage;
|
||||
use phpbb\user;
|
||||
use Symfony\Component\HttpFoundation\Request as symfony_request;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Controller for /download/attachment/{id} routes
|
||||
*/
|
||||
class attachment extends controller
|
||||
{
|
||||
/** @var auth */
|
||||
protected $auth;
|
||||
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
/** @var content_visibility */
|
||||
protected $content_visibility;
|
||||
|
||||
/** @var dispatcher_interface */
|
||||
protected $dispatcher;
|
||||
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var request */
|
||||
protected $request;
|
||||
|
||||
/** @var user */
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param auth $auth
|
||||
* @param service $cache
|
||||
* @param config $config
|
||||
* @param content_visibility $content_visibility
|
||||
* @param driver_interface $db
|
||||
* @param dispatcher_interface $dispatcher
|
||||
* @param language $language
|
||||
* @param request $request
|
||||
* @param storage $storage
|
||||
* @param symfony_request $symfony_request
|
||||
* @param user $user
|
||||
*/
|
||||
public function __construct(auth $auth, service $cache, config $config, content_visibility $content_visibility, driver_interface $db, dispatcher_interface $dispatcher, language $language, request $request, storage $storage, symfony_request $symfony_request, user $user)
|
||||
{
|
||||
parent::__construct($cache, $db, $storage, $symfony_request);
|
||||
|
||||
$this->auth = $auth;
|
||||
$this->config = $config;
|
||||
$this->content_visibility = $content_visibility;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->language = $language;
|
||||
$this->request = $request;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(string $file): Response
|
||||
{
|
||||
$attach_id = (int) $file;
|
||||
$thumbnail = $this->request->variable('t', false);
|
||||
|
||||
$this->language->add_lang('viewtopic');
|
||||
|
||||
if (!$this->config['allow_attachments'] && !$this->config['allow_pm_attach'])
|
||||
{
|
||||
throw new http_exception(404, 'ATTACHMENT_FUNCTIONALITY_DISABLED');
|
||||
}
|
||||
|
||||
if (!$attach_id)
|
||||
{
|
||||
throw new http_exception(404, 'NO_ATTACHMENT_SELECTED');
|
||||
}
|
||||
|
||||
$sql = 'SELECT attach_id, post_msg_id, topic_id, in_message, poster_id,
|
||||
is_orphan, physical_filename, real_filename, extension, mimetype,
|
||||
filesize, filetime
|
||||
FROM ' . ATTACHMENTS_TABLE . "
|
||||
WHERE attach_id = $attach_id";
|
||||
$result = $this->db->sql_query($sql);
|
||||
$attachment = $this->db->sql_fetchrow($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (!$attachment)
|
||||
{
|
||||
throw new http_exception(404, 'ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
else if (!$this->download_allowed())
|
||||
{
|
||||
throw new http_exception(403, 'LINKAGE_FORBIDDEN');
|
||||
}
|
||||
|
||||
$attachment['physical_filename'] = utf8_basename($attachment['physical_filename']);
|
||||
|
||||
if ((!$attachment['in_message'] && !$this->config['allow_attachments']) ||
|
||||
($attachment['in_message'] && !$this->config['allow_pm_attach']))
|
||||
{
|
||||
throw new http_exception(404, 'ATTACHMENT_FUNCTIONALITY_DISABLED');
|
||||
}
|
||||
|
||||
if ($attachment['is_orphan'])
|
||||
{
|
||||
// We allow admins having attachment permissions to see orphan attachments...
|
||||
$own_attachment = $this->auth->acl_get('a_attach') || $attachment['poster_id'] == $this->user->data['user_id'];
|
||||
|
||||
if (!$own_attachment || ($attachment['in_message'] && !$this->auth->acl_get('u_pm_download')) ||
|
||||
(!$attachment['in_message'] && !$this->auth->acl_get('u_download')))
|
||||
{
|
||||
throw new http_exception(404, 'ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
|
||||
// Obtain all extensions...
|
||||
$extensions = $this->cache->obtain_attach_extensions(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$attachment['in_message'])
|
||||
{
|
||||
$this->phpbb_download_handle_forum_auth($attachment['topic_id']);
|
||||
|
||||
$sql = 'SELECT forum_id, post_visibility
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $attachment['post_msg_id'];
|
||||
$result = $this->db->sql_query($sql);
|
||||
$post_row = $this->db->sql_fetchrow($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (!$post_row || !$this->content_visibility->is_visible('post', $post_row['forum_id'], $post_row))
|
||||
{
|
||||
// Attachment of a soft deleted post and the user is not allowed to see the post
|
||||
throw new http_exception(404, 'ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attachment is in a private message.
|
||||
$post_row = array('forum_id' => false);
|
||||
$this->phpbb_download_handle_pm_auth( $attachment['post_msg_id']);
|
||||
}
|
||||
|
||||
$extensions = array();
|
||||
if (!extension_allowed($post_row['forum_id'], $attachment['extension'], $extensions))
|
||||
{
|
||||
throw new http_exception(403, 'EXTENSION_DISABLED_AFTER_POSTING', [$attachment['extension']]);
|
||||
}
|
||||
}
|
||||
|
||||
$display_cat = $extensions[$attachment['extension']]['display_cat'];
|
||||
|
||||
if ($thumbnail)
|
||||
{
|
||||
$attachment['physical_filename'] = 'thumb_' . $attachment['physical_filename'];
|
||||
}
|
||||
else if ($display_cat == ATTACHMENT_CATEGORY_NONE && !$attachment['is_orphan'])
|
||||
{
|
||||
if (!(($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$this->user->optionget('viewimg')))
|
||||
{
|
||||
// Update download count
|
||||
$this->phpbb_increment_downloads($attachment['attach_id']);
|
||||
}
|
||||
}
|
||||
|
||||
$redirect = '';
|
||||
|
||||
/**
|
||||
* Event to modify data before sending file to browser
|
||||
*
|
||||
* @event core.download_file_send_to_browser_before
|
||||
* @var int attach_id The attachment ID
|
||||
* @var array attachment Array with attachment data
|
||||
* @var array extensions Array with file extensions data
|
||||
* @var bool thumbnail Flag indicating if the file is a thumbnail
|
||||
* @var string redirect Do a redirection instead of reading the file
|
||||
* @since 3.1.6-RC1
|
||||
* @changed 3.1.7-RC1 Fixing wrong name of a variable (replacing "extension" by "extensions")
|
||||
* @changed 3.3.0-a1 Add redirect variable
|
||||
* @changed 3.3.0-a1 Remove display_cat variable
|
||||
* @changed 3.3.0-a1 Remove mode variable
|
||||
*/
|
||||
$vars = array(
|
||||
'attach_id',
|
||||
'attachment',
|
||||
'extensions',
|
||||
'thumbnail',
|
||||
'redirect',
|
||||
);
|
||||
extract($this->dispatcher->trigger_event('core.download_file_send_to_browser_before', compact($vars)));
|
||||
|
||||
// If the redirect variable have been overwritten, do redirect there
|
||||
if (!empty($redirect))
|
||||
{
|
||||
return new RedirectResponse($redirect);
|
||||
}
|
||||
|
||||
// Check if the file exists in the storage table too
|
||||
if (!$this->storage->exists($attachment['physical_filename']))
|
||||
{
|
||||
throw new http_exception(404, 'ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Event to alter attachment before it is sent to browser.
|
||||
*
|
||||
* @event core.send_file_to_browser_before
|
||||
* @var array attachment Attachment data
|
||||
* @since 3.1.11-RC1
|
||||
* @changed 3.3.0-a1 Removed category variable
|
||||
* @changed 3.3.0-a1 Removed size variable
|
||||
* @changed 3.3.0-a1 Removed filename variable
|
||||
*/
|
||||
$vars = array(
|
||||
'attachment',
|
||||
);
|
||||
extract($this->dispatcher->trigger_event('core.send_file_to_browser_before', compact($vars)));
|
||||
|
||||
// TODO: The next lines should go better in prepare, also the mimetype is handled by the storage table
|
||||
// so probably can be removed
|
||||
|
||||
$response = new StreamedResponse();
|
||||
|
||||
// Content-type header
|
||||
$response->headers->set('Content-Type', $attachment['mimetype']);
|
||||
|
||||
// Display images in browser and force download for other file types
|
||||
if (strpos($attachment['mimetype'], 'image') !== false)
|
||||
{
|
||||
$disposition = $response->headers->makeDisposition(
|
||||
ResponseHeaderBag::DISPOSITION_INLINE,
|
||||
$attachment['real_filename'],
|
||||
$this->filenameFallback($attachment['real_filename'])
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$disposition = $response->headers->makeDisposition(
|
||||
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
||||
$attachment['real_filename'],
|
||||
$this->filenameFallback($attachment['real_filename'])
|
||||
);
|
||||
}
|
||||
|
||||
$response->headers->set('Content-Disposition', $disposition);
|
||||
|
||||
// Set expires header for browser cache
|
||||
$time = new \Datetime();
|
||||
$response->setExpires($time->modify('+1 year'));
|
||||
|
||||
return parent::handle($attachment['physical_filename']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove non valid characters https://github.com/symfony/http-foundation/commit/c7df9082ee7205548a97031683bc6550b5dc9551
|
||||
*/
|
||||
protected function filenameFallback($filename)
|
||||
{
|
||||
$filename = preg_replace(['/[^\x20-\x7e]/', '/%/', '/\//', '/\\\/'], '', $filename);
|
||||
|
||||
return (!empty($filename)) ?: 'File';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepare(StreamedResponse $response, string $file): void
|
||||
{
|
||||
$response->setPrivate(); // By default should be private, but make sure of it
|
||||
|
||||
parent::prepare($response, $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authentication when downloading attachments from a post or topic
|
||||
*
|
||||
* @param int $topic_id The id of the topic that we are downloading from
|
||||
*
|
||||
* @return void
|
||||
* @throws http_exception If attachment is not found
|
||||
* If user don't have permission to download the attachment
|
||||
*/
|
||||
protected function phpbb_download_handle_forum_auth(int $topic_id): void
|
||||
{
|
||||
$sql_array = array(
|
||||
'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id',
|
||||
'FROM' => array(
|
||||
TOPICS_TABLE => 't',
|
||||
FORUMS_TABLE => 'f',
|
||||
),
|
||||
'WHERE' => 't.topic_id = ' . (int) $topic_id . '
|
||||
AND t.forum_id = f.forum_id',
|
||||
);
|
||||
|
||||
$sql = $this->db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $this->db->sql_query($sql);
|
||||
$row = $this->db->sql_fetchrow($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if ($row && !$this->content_visibility->is_visible('topic', $row['forum_id'], $row))
|
||||
{
|
||||
throw new http_exception(404, 'ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
else if ($row && $this->auth->acl_get('u_download') && $this->auth->acl_get('f_download', $row['forum_id']))
|
||||
{
|
||||
if ($row['forum_password'])
|
||||
{
|
||||
// Do something else ... ?
|
||||
login_forum_box($row);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new http_exception(403, 'SORRY_AUTH_VIEW_ATTACH');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authentication when downloading attachments from PMs
|
||||
*
|
||||
* @param int $msg_id The id of the PM that we are downloading from
|
||||
*
|
||||
* @return void
|
||||
* @throws http_exception If attachment is not found
|
||||
*/
|
||||
protected function phpbb_download_handle_pm_auth(int $msg_id): void
|
||||
{
|
||||
if (!$this->auth->acl_get('u_pm_download'))
|
||||
{
|
||||
throw new http_exception(403, 'SORRY_AUTH_VIEW_ATTACH');
|
||||
}
|
||||
|
||||
$allowed = $this->phpbb_download_check_pm_auth($msg_id);
|
||||
|
||||
/**
|
||||
* Event to modify PM attachments download auth
|
||||
*
|
||||
* @event core.modify_pm_attach_download_auth
|
||||
* @var bool allowed Whether the user is allowed to download from that PM or not
|
||||
* @var int msg_id The id of the PM to download from
|
||||
* @var int user_id The user id for auth check
|
||||
* @since 3.1.11-RC1
|
||||
*/
|
||||
$vars = array('allowed', 'msg_id', 'user_id');
|
||||
extract($this->dispatcher->trigger_event('core.modify_pm_attach_download_auth', compact($vars)));
|
||||
|
||||
if (!$allowed)
|
||||
{
|
||||
throw new http_exception(403, 'ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a user can download from a particular PM
|
||||
*
|
||||
* @param int $msg_id The id of the PM that we are downloading from
|
||||
*
|
||||
* @return bool Whether the user is allowed to download from that PM or not
|
||||
*/
|
||||
protected function phpbb_download_check_pm_auth(int $msg_id): bool
|
||||
{
|
||||
$user_id = $this->user->data['user_id'];
|
||||
|
||||
// Check if the attachment is within the users scope...
|
||||
$sql = 'SELECT msg_id
|
||||
FROM ' . PRIVMSGS_TO_TABLE . '
|
||||
WHERE msg_id = ' . (int) $msg_id . '
|
||||
AND (
|
||||
user_id = ' . (int) $user_id . '
|
||||
OR author_id = ' . (int) $user_id . '
|
||||
)';
|
||||
$result = $this->db->sql_query_limit($sql, 1);
|
||||
$allowed = (bool) $this->db->sql_fetchfield('msg_id');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the download count of all provided attachments
|
||||
*
|
||||
* @param int $id The attach_id of the attachment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function phpbb_increment_downloads(int $id): void
|
||||
{
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET download_count = download_count + 1
|
||||
WHERE attach_id = ' . $id;
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if downloading item is allowed
|
||||
* FIXME (See: https://tracker.phpbb.com/browse/PHPBB3-15264 and http://area51.phpbb.com/phpBB/viewtopic.php?f=81&t=51921)
|
||||
*/
|
||||
protected function download_allowed(): bool
|
||||
{
|
||||
if (!$this->config['secure_downloads'])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$url = htmlspecialchars_decode($this->request->header('Referer'));
|
||||
|
||||
if (!$url)
|
||||
{
|
||||
return ($this->config['secure_allow_empty_referer']) ? true : false;
|
||||
}
|
||||
|
||||
// Split URL into domain and script part
|
||||
$url = @parse_url($url);
|
||||
|
||||
if ($url === false)
|
||||
{
|
||||
return ($this->config['secure_allow_empty_referer']) ? true : false;
|
||||
}
|
||||
|
||||
$hostname = $url['host'];
|
||||
unset($url);
|
||||
|
||||
$allowed = ($this->config['secure_allow_deny']) ? false : true;
|
||||
$iplist = array();
|
||||
|
||||
if (($ip_ary = @gethostbynamel($hostname)) !== false)
|
||||
{
|
||||
foreach ($ip_ary as $ip)
|
||||
{
|
||||
if ($ip)
|
||||
{
|
||||
$iplist[] = $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for own server...
|
||||
$server_name = $this->user->host;
|
||||
|
||||
// Forcing server vars is the only way to specify/override the protocol
|
||||
if ($this->config['force_server_vars'] || !$server_name)
|
||||
{
|
||||
$server_name = $this->config['server_name'];
|
||||
}
|
||||
|
||||
if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
|
||||
{
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
// Get IP's and Hostnames
|
||||
if (!$allowed)
|
||||
{
|
||||
$sql = 'SELECT site_ip, site_hostname, ip_exclude
|
||||
FROM ' . SITELIST_TABLE;
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$site_ip = trim($row['site_ip']);
|
||||
$site_hostname = trim($row['site_hostname']);
|
||||
|
||||
if ($site_ip)
|
||||
{
|
||||
foreach ($iplist as $ip)
|
||||
{
|
||||
if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
|
||||
{
|
||||
if ($row['ip_exclude'])
|
||||
{
|
||||
$allowed = ($this->config['secure_allow_deny']) ? false : true;
|
||||
break 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
$allowed = ($this->config['secure_allow_deny']) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($site_hostname)
|
||||
{
|
||||
if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
|
||||
{
|
||||
if ($row['ip_exclude'])
|
||||
{
|
||||
$allowed = ($this->config['secure_allow_deny']) ? false : true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$allowed = ($this->config['secure_allow_deny']) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
}
|
115
phpBB/phpbb/storage/controller/avatar.php
Normal file
115
phpBB/phpbb/storage/controller/avatar.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\storage\controller;
|
||||
|
||||
use phpbb\cache\service;
|
||||
use phpbb\config\config;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\storage\storage;
|
||||
use Symfony\Component\HttpFoundation\Request as symfony_request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Controller for /download/avatar/{file} routes
|
||||
*/
|
||||
class avatar extends controller
|
||||
{
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
/** @var array */
|
||||
protected $allowed_extensions = ['png', 'gif', 'jpg', 'jpeg'];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param service $cache
|
||||
* @param config $config
|
||||
* @param driver_interface $db
|
||||
* @param storage $storage
|
||||
* @param symfony_request $symfony_request
|
||||
*/
|
||||
public function __construct(service $cache, config $config, driver_interface $db, storage $storage, symfony_request $symfony_request)
|
||||
{
|
||||
parent::__construct($cache, $db, $storage, $symfony_request);
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(string $file): Response
|
||||
{
|
||||
$file = $this->decode_filename($file);
|
||||
|
||||
return parent::handle($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function is_allowed(string $file): bool
|
||||
{
|
||||
$ext = substr(strrchr($file, '.'), 1);
|
||||
|
||||
// If filename have point and have an allowed extension
|
||||
return strpos($file, '.') && in_array($ext, $this->allowed_extensions, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode avatar filename
|
||||
*
|
||||
* @param string $file Filename
|
||||
*
|
||||
* @return string Filename in filesystem
|
||||
*/
|
||||
protected function decode_filename(string $file): string
|
||||
{
|
||||
$avatar_group = false;
|
||||
|
||||
if (isset($file[0]) && $file[0] === 'g')
|
||||
{
|
||||
$avatar_group = true;
|
||||
$file = substr($file, 1);
|
||||
}
|
||||
|
||||
$ext = substr(strrchr($file, '.'), 1);
|
||||
$file = (int) $file;
|
||||
|
||||
return $this->config['avatar_salt'] . '_' . ($avatar_group ? 'g' : '') . $file . '.' . $ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepare(StreamedResponse $response, string $file): void
|
||||
{
|
||||
$response->setPublic();
|
||||
|
||||
$disposition = $response->headers->makeDisposition(
|
||||
ResponseHeaderBag::DISPOSITION_INLINE,
|
||||
rawurlencode($file)
|
||||
);
|
||||
|
||||
$response->headers->set('Content-Disposition', $disposition);
|
||||
|
||||
$time = new \Datetime();
|
||||
$response->setExpires($time->modify('+1 year'));
|
||||
|
||||
parent::prepare($response, $file);
|
||||
}
|
||||
}
|
188
phpBB/phpbb/storage/controller/controller.php
Normal file
188
phpBB/phpbb/storage/controller/controller.php
Normal file
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\storage\controller;
|
||||
|
||||
use phpbb\cache\service;
|
||||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\exception\http_exception;
|
||||
use phpbb\storage\exception\exception;
|
||||
use phpbb\storage\storage;
|
||||
use Symfony\Component\HttpFoundation\Request as symfony_request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* Generic controller for storage
|
||||
*/
|
||||
class controller
|
||||
{
|
||||
/** @var service */
|
||||
protected $cache;
|
||||
|
||||
/** @var driver_interface */
|
||||
protected $db;
|
||||
|
||||
/** @var storage */
|
||||
protected $storage;
|
||||
|
||||
/** @var symfony_request */
|
||||
protected $symfony_request;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param service $cache
|
||||
* @param driver_interface $db
|
||||
* @param storage $storage
|
||||
* @param symfony_request $symfony_request
|
||||
*/
|
||||
public function __construct(service $cache, driver_interface $db, storage $storage, symfony_request $symfony_request)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
$this->db = $db;
|
||||
$this->storage = $storage;
|
||||
$this->symfony_request = $symfony_request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler
|
||||
*
|
||||
* @param string $file File path
|
||||
*
|
||||
* @return Response a Symfony response object
|
||||
*
|
||||
* @throws http_exception when can't access $file
|
||||
* @throws exception when there is an error reading the file
|
||||
*/
|
||||
public function handle(string $file): Response
|
||||
{
|
||||
$response = new StreamedResponse();
|
||||
|
||||
if (!static::is_allowed($file))
|
||||
{
|
||||
throw new http_exception(403, 'Forbidden');
|
||||
}
|
||||
|
||||
if (!static::file_exists($file))
|
||||
{
|
||||
throw new http_exception(404, 'Not Found');
|
||||
}
|
||||
|
||||
static::prepare($response, $file);
|
||||
|
||||
if (headers_sent())
|
||||
{
|
||||
throw new http_exception(500, 'Headers already sent');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user is allowed to download the file
|
||||
*
|
||||
* @param string $file File path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_allowed(string $file): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if file exists
|
||||
*
|
||||
* @param string $file File path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function file_exists(string $file): bool
|
||||
{
|
||||
return $this->storage->exists($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare response
|
||||
*
|
||||
* @param StreamedResponse $response
|
||||
* @param string $file File path
|
||||
*
|
||||
* @return void
|
||||
* @throws exception when there is an error reading the file
|
||||
*/
|
||||
protected function prepare(StreamedResponse $response, string $file): void
|
||||
{
|
||||
$file_info = $this->storage->file_info($file);
|
||||
|
||||
// Add Content-Type header
|
||||
if (!$response->headers->has('Content-Type'))
|
||||
{
|
||||
try
|
||||
{
|
||||
$content_type = $file_info->get('mimetype');
|
||||
}
|
||||
catch (exception $e)
|
||||
{
|
||||
$content_type = 'application/octet-stream';
|
||||
}
|
||||
|
||||
$response->headers->set('Content-Type', $content_type);
|
||||
}
|
||||
|
||||
// Add Content-Length header if we have the file size
|
||||
if (!$response->headers->has('Content-Length'))
|
||||
{
|
||||
try
|
||||
{
|
||||
$response->headers->set('Content-Length', $file_info->get('size'));
|
||||
}
|
||||
catch (exception $e)
|
||||
{
|
||||
// Just don't send this header
|
||||
}
|
||||
}
|
||||
|
||||
@set_time_limit(0);
|
||||
|
||||
$fp = $this->storage->read_stream($file);
|
||||
|
||||
// Close db connection
|
||||
$this->file_gc();
|
||||
|
||||
$output = fopen('php://output', 'w+b');
|
||||
|
||||
$response->setCallback(function () use ($fp, $output) {
|
||||
stream_copy_to_stream($fp, $output);
|
||||
fclose($fp);
|
||||
fclose($output);
|
||||
flush();
|
||||
|
||||
// Terminate script to avoid the execution of terminate events
|
||||
// This avoid possible errors with db connection closed
|
||||
exit;
|
||||
});
|
||||
|
||||
$response->isNotModified($this->symfony_request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage Collection
|
||||
*/
|
||||
protected function file_gc(): void
|
||||
{
|
||||
$this->cache->unload(); // Equivalent to $this->cache->get_driver()->unload();
|
||||
$this->db->sql_close();
|
||||
}
|
||||
}
|
|
@ -56,6 +56,8 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
|
|||
|
||||
$dispatcher = new phpbb_mock_event_dispatcher();
|
||||
|
||||
$controller_helper = $this->createMock('\phpbb\controller\helper');
|
||||
|
||||
// $this->avatar_foobar will be needed later on
|
||||
$this->avatar_foobar = $this->getMockBuilder('\phpbb\avatar\driver\foobar')
|
||||
->setMethods(array('get_name'))
|
||||
|
@ -93,7 +95,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
|
|||
{
|
||||
$cur_avatar = $this->getMockBuilder('\phpbb\avatar\driver\\' . $driver)
|
||||
->setMethods(array('get_name'))
|
||||
->setConstructorArgs(array($this->config, $phpbb_root_path, $phpEx, $storage, $path_helper, $dispatcher, $files_factory, $php_ini))
|
||||
->setConstructorArgs(array($this->config, $controller_helper, $phpbb_root_path, $phpEx, $storage, $path_helper, $dispatcher, $files_factory, $php_ini))
|
||||
->getMock();
|
||||
}
|
||||
$cur_avatar->expects($this->any())
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../phpBB/includes/functions_download.php';
|
||||
|
||||
class phpbb_download_http_byte_range_test extends phpbb_test_case
|
||||
{
|
||||
public function test_find_range_request()
|
||||
{
|
||||
// Missing 'bytes=' prefix
|
||||
$GLOBALS['request'] = new phpbb_mock_request();
|
||||
$GLOBALS['request']->set_header('Range', 'bztes=');
|
||||
$this->assertEquals(false, phpbb_find_range_request());
|
||||
unset($GLOBALS['request']);
|
||||
|
||||
$GLOBALS['request'] = new phpbb_mock_request();
|
||||
$_ENV['HTTP_RANGE'] = 'bztes=';
|
||||
$this->assertEquals(false, phpbb_find_range_request());
|
||||
unset($_ENV['HTTP_RANGE']);
|
||||
|
||||
$GLOBALS['request'] = new phpbb_mock_request();
|
||||
$GLOBALS['request']->set_header('Range', 'bytes=0-0,123-125');
|
||||
$this->assertEquals(array('0-0', '123-125'), phpbb_find_range_request());
|
||||
unset($GLOBALS['request']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider parse_range_request_data()
|
||||
*/
|
||||
public function test_parse_range_request($request_array, $filesize, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, phpbb_parse_range_request($request_array, $filesize));
|
||||
}
|
||||
|
||||
public function parse_range_request_data()
|
||||
{
|
||||
return array(
|
||||
// Valid request
|
||||
array(
|
||||
array('3-4'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 3,
|
||||
'byte_pos_end' => 4,
|
||||
'bytes_requested' => 2,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Get the beginning
|
||||
array(
|
||||
array('-5'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 0,
|
||||
'byte_pos_end' => 5,
|
||||
'bytes_requested' => 6,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Get the end
|
||||
array(
|
||||
array('5-'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 5,
|
||||
'byte_pos_end' => 9,
|
||||
'bytes_requested' => 5,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Overlong request
|
||||
array(
|
||||
array('3-20'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 3,
|
||||
'byte_pos_end' => 9,
|
||||
'bytes_requested' => 7,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Multiple, contiguous range
|
||||
array(
|
||||
array('10-20', '21-30'),
|
||||
125,
|
||||
array(
|
||||
'byte_pos_start' => 10,
|
||||
'byte_pos_end' => 30,
|
||||
'bytes_requested' => 21,
|
||||
'bytes_total' => 125,
|
||||
)
|
||||
),
|
||||
|
||||
// We don't do multiple, non-contiguous range
|
||||
array(
|
||||
array('0-0', '120-125'),
|
||||
125,
|
||||
false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../phpBB/includes/functions_download.php';
|
||||
|
||||
class phpbb_download_http_user_agent_test extends phpbb_test_case
|
||||
{
|
||||
public function user_agents_check_greater_ie_version()
|
||||
{
|
||||
return array(
|
||||
// user agent
|
||||
// IE version
|
||||
// expected
|
||||
array(
|
||||
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
|
||||
7,
|
||||
true,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
|
||||
7,
|
||||
true,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)',
|
||||
7,
|
||||
true,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 6.0)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (Windows NT 6.2; Win64; x64;) Gecko/20100101 Firefox/20.0',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1464.0 Safari/537.36',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Googlebot-Image/1.0',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Googlebot/2.1 ( http://www.google.com/bot.html)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Lynx/2.8.3dev.9 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Links (0.9x; Linux 2.4.7-10 i686)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Opera/9.60 (Windows NT 5.1; U; de) Presto/2.1.1',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT;)',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 6.01 [en]',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.24',
|
||||
7,
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
|
||||
8,
|
||||
true,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
|
||||
9,
|
||||
true,
|
||||
),
|
||||
array(
|
||||
'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)',
|
||||
10,
|
||||
false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider user_agents_check_greater_ie_version
|
||||
*/
|
||||
public function test_is_greater_ie_version($user_agent, $version, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, phpbb_is_greater_ie_version($user_agent, $version));
|
||||
}
|
||||
}
|
|
@ -83,7 +83,7 @@ class phpbb_functional_download_test extends phpbb_functional_test_case
|
|||
));
|
||||
|
||||
// Download attachment as guest
|
||||
$crawler = self::request('GET', "download/file.php?id={$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
$crawler = self::request('GET', "download/attachment/{$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
self::assert_response_status_code(200);
|
||||
$content = self::$client->getResponse()->getContent();
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
|
@ -141,7 +141,7 @@ class phpbb_functional_download_test extends phpbb_functional_test_case
|
|||
$this->add_lang('viewtopic');
|
||||
|
||||
// No download attachment as guest
|
||||
$crawler = self::request('GET', "download/file.php?id={$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
$crawler = self::request('GET', "download/attachment/{$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
self::assert_response_html(404);
|
||||
$this->assertContainsLang('ERROR_NO_ATTACHMENT', $crawler->filter('#message')->text());
|
||||
|
||||
|
@ -149,7 +149,7 @@ class phpbb_functional_download_test extends phpbb_functional_test_case
|
|||
$this->login();
|
||||
|
||||
// Download attachment as admin
|
||||
$crawler = self::request('GET', "download/file.php?id={$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
$crawler = self::request('GET', "download/attachment/{$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
self::assert_response_status_code(200);
|
||||
$content = self::$client->getResponse()->getContent();
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
|
@ -208,7 +208,7 @@ class phpbb_functional_download_test extends phpbb_functional_test_case
|
|||
$this->add_lang('viewtopic');
|
||||
|
||||
// No download attachment as guest
|
||||
$crawler = self::request('GET', "download/file.php?id={$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
$crawler = self::request('GET', "download/attachment/{$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
self::assert_response_html(404);
|
||||
$this->assertContainsLang('ERROR_NO_ATTACHMENT', $crawler->filter('#message')->text());
|
||||
|
||||
|
@ -216,7 +216,7 @@ class phpbb_functional_download_test extends phpbb_functional_test_case
|
|||
$this->login();
|
||||
|
||||
// Download attachment as admin
|
||||
$crawler = self::request('GET', "download/file.php?id={$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
$crawler = self::request('GET', "download/attachment/{$this->data['attachments'][$this->data['posts']['Re: Download Topic #1-#2']]}", array(), false);
|
||||
self::assert_response_status_code(200);
|
||||
$content = self::$client->getResponse()->getContent();
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
|
|
|
@ -1417,7 +1417,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case
|
|||
$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();
|
||||
foreach ($attachments as $i => $attachment)
|
||||
{
|
||||
$url = self::$root_url . "download/file.php?id={$attachment['id']}";
|
||||
$url = self::$root_url . "app.php/download/attachment/{$attachment['id']}";
|
||||
$string = "Attachment #{$i}";
|
||||
|
||||
if ($attachment['displayed'])
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
use phpbb\controller\helper;
|
||||
|
||||
require_once __DIR__ . '/template_test_case.php';
|
||||
|
||||
class phpbb_template_extension_test extends phpbb_template_template_test_case
|
||||
|
@ -66,10 +68,17 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
|
|||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$controller_helper = $this->createMock(helper::class);
|
||||
$controller_helper
|
||||
->method('route')
|
||||
->willReturnCallback(function($route, $params) {
|
||||
return 'download/avatar/' . $params['file'];
|
||||
});
|
||||
|
||||
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
|
||||
$phpbb_container = new phpbb_mock_container_builder();
|
||||
$files = new phpbb\files\factory($phpbb_container);
|
||||
$upload_avatar_driver = new phpbb\avatar\driver\upload($config, $phpbb_root_path, $phpEx, $storage, $phpbb_path_helper, $phpbb_dispatcher, $files, new \bantu\IniGetWrapper\IniGetWrapper());
|
||||
$upload_avatar_driver = new phpbb\avatar\driver\upload($config, $controller_helper, $phpbb_root_path, $phpEx, $storage, $phpbb_path_helper, $phpbb_dispatcher, $files, new \bantu\IniGetWrapper\IniGetWrapper());
|
||||
$upload_avatar_driver->set_name('avatar.driver.upload');
|
||||
$phpbb_container->set('avatar.manager', new \phpbb\avatar\manager($config, $phpbb_dispatcher, [
|
||||
$upload_avatar_driver,
|
||||
|
@ -141,7 +150,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
|
|||
],
|
||||
[],
|
||||
[],
|
||||
'<img class="avatar" src="phpBB/download/file.php?avatar=great_avatar.png" width="90" height="90" alt="foo" />',
|
||||
'<img class="avatar" src="download/avatar/great_avatar.png" width="90" height="90" alt="foo" />',
|
||||
[]
|
||||
],
|
||||
[
|
||||
|
@ -159,7 +168,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
|
|||
],
|
||||
[],
|
||||
[],
|
||||
'<img class="avatar" src="phpBB/styles//theme/images/no_avatar.gif" data-src="phpBB/download/file.php?avatar=great_avatar.png" width="90" height="90" alt="foo" />',
|
||||
'<img class="avatar" src="phpBB/styles//theme/images/no_avatar.gif" data-src="download/avatar/great_avatar.png" width="90" height="90" alt="foo" />',
|
||||
[]
|
||||
],
|
||||
[
|
||||
|
|
|
@ -47,7 +47,6 @@ class phpbb_functional_test_case extends phpbb_test_case
|
|||
parent::setUpBeforeClass();
|
||||
|
||||
self::$config = phpbb_test_case_helpers::get_test_config();
|
||||
self::$root_url = self::$config['phpbb_functional_url'];
|
||||
|
||||
// Important: this is used both for installation and by
|
||||
// test cases for querying the tables.
|
||||
|
@ -60,6 +59,8 @@ class phpbb_functional_test_case extends phpbb_test_case
|
|||
self::markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.');
|
||||
}
|
||||
|
||||
self::$root_url = self::$config['phpbb_functional_url'];
|
||||
|
||||
if (!self::$already_installed)
|
||||
{
|
||||
self::install_board();
|
||||
|
|
Loading…
Add table
Reference in a new issue