PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/phpBB/download/file.php

https://github.com/Jipem/phpbb
PHP | 471 lines | 360 code | 68 blank | 43 comment | 100 complexity | 0bb74c70da841590157f0c0062c2ea34 MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * This file is part of the phpBB Forum Software package.
  5. *
  6. * @copyright (c) phpBB Limited <https://www.phpbb.com>
  7. * @license GNU General Public License, version 2 (GPL-2.0)
  8. *
  9. * For full copyright and license information, please see
  10. * the docs/CREDITS.txt file.
  11. *
  12. */
  13. use Symfony\Component\Config\FileLocator;
  14. use Symfony\Component\DependencyInjection\ContainerBuilder;
  15. use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
  16. /**
  17. * @ignore
  18. */
  19. define('IN_PHPBB', true);
  20. $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
  21. $phpEx = substr(strrchr(__FILE__, '.'), 1);
  22. // Thank you sun.
  23. if (isset($_SERVER['CONTENT_TYPE']))
  24. {
  25. if ($_SERVER['CONTENT_TYPE'] === 'application/x-java-archive')
  26. {
  27. exit;
  28. }
  29. }
  30. else if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Java') !== false)
  31. {
  32. exit;
  33. }
  34. if (isset($_GET['avatar']))
  35. {
  36. require($phpbb_root_path . 'includes/startup.' . $phpEx);
  37. require($phpbb_root_path . 'config.' . $phpEx);
  38. if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
  39. {
  40. exit;
  41. }
  42. require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
  43. require($phpbb_root_path . 'includes/constants.' . $phpEx);
  44. require($phpbb_root_path . 'includes/functions.' . $phpEx);
  45. require($phpbb_root_path . 'includes/functions_container.' . $phpEx);
  46. require($phpbb_root_path . 'includes/functions_download' . '.' . $phpEx);
  47. require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
  48. // Setup class loader first
  49. $phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
  50. $phpbb_class_loader->register();
  51. $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
  52. $phpbb_class_loader_ext->register();
  53. // Set up container
  54. $phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx);
  55. $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
  56. $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
  57. // set up caching
  58. $cache = $phpbb_container->get('cache');
  59. $phpbb_dispatcher = $phpbb_container->get('dispatcher');
  60. $request = $phpbb_container->get('request');
  61. $db = $phpbb_container->get('dbal.conn');
  62. $phpbb_log = $phpbb_container->get('log');
  63. // Connect to DB
  64. if (!@$db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false))
  65. {
  66. exit;
  67. }
  68. unset($dbpasswd);
  69. request_var('', 0, false, false, $request);
  70. $config = $phpbb_container->get('config');
  71. set_config(null, null, null, $config);
  72. set_config_count(null, null, null, $config);
  73. // load extensions
  74. $phpbb_extension_manager = $phpbb_container->get('ext.manager');
  75. $phpbb_subscriber_loader = $phpbb_container->get('event.subscriber_loader');
  76. // worst-case default
  77. $browser = strtolower($request->header('User-Agent', 'msie 6.0'));
  78. $phpbb_avatar_manager = $phpbb_container->get('avatar.manager');
  79. $filename = request_var('avatar', '');
  80. $avatar_group = false;
  81. $exit = false;
  82. if (isset($filename[0]) && $filename[0] === 'g')
  83. {
  84. $avatar_group = true;
  85. $filename = substr($filename, 1);
  86. }
  87. // '==' is not a bug - . as the first char is as bad as no dot at all
  88. if (strpos($filename, '.') == false)
  89. {
  90. send_status_line(403, 'Forbidden');
  91. $exit = true;
  92. }
  93. if (!$exit)
  94. {
  95. $ext = substr(strrchr($filename, '.'), 1);
  96. $stamp = (int) substr(stristr($filename, '_'), 1);
  97. $filename = (int) $filename;
  98. $exit = set_modified_headers($stamp, $browser);
  99. }
  100. if (!$exit && !in_array($ext, array('png', 'gif', 'jpg', 'jpeg')))
  101. {
  102. // no way such an avatar could exist. They are not following the rules, stop the show.
  103. send_status_line(403, 'Forbidden');
  104. $exit = true;
  105. }
  106. if (!$exit)
  107. {
  108. if (!$filename)
  109. {
  110. // no way such an avatar could exist. They are not following the rules, stop the show.
  111. send_status_line(403, 'Forbidden');
  112. }
  113. else
  114. {
  115. send_avatar_to_browser(($avatar_group ? 'g' : '') . $filename . '.' . $ext, $browser);
  116. }
  117. }
  118. file_gc();
  119. }
  120. // implicit else: we are not in avatar mode
  121. include($phpbb_root_path . 'common.' . $phpEx);
  122. require($phpbb_root_path . 'includes/functions_download' . '.' . $phpEx);
  123. $download_id = request_var('id', 0);
  124. $topic_id = $request->variable('topic_id', 0);
  125. $post_id = $request->variable('post_id', 0);
  126. $msg_id = $request->variable('msg_id', 0);
  127. $archive = $request->variable('archive', '.tar');
  128. $mode = request_var('mode', '');
  129. $thumbnail = request_var('t', false);
  130. // Start session management, do not update session page.
  131. $user->session_begin(false);
  132. $auth->acl($user->data);
  133. $user->setup('viewtopic');
  134. if (!$config['allow_attachments'] && !$config['allow_pm_attach'])
  135. {
  136. send_status_line(404, 'Not Found');
  137. trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED');
  138. }
  139. if ($download_id)
  140. {
  141. // Attachment id (only 1 attachment)
  142. $sql_where = 'attach_id = ' . $download_id;
  143. }
  144. else if ($msg_id)
  145. {
  146. // Private message id (multiple attachments)
  147. $sql_where = 'is_orphan = 0 AND in_message = 1 AND post_msg_id = ' . $msg_id;
  148. }
  149. else if ($post_id)
  150. {
  151. // Post id (multiple attachments)
  152. $sql_where = 'is_orphan = 0 AND in_message = 0 AND post_msg_id = ' . $post_id;
  153. }
  154. else if ($topic_id)
  155. {
  156. // Topic id (multiple attachments)
  157. $sql_where = 'is_orphan = 0 AND topic_id = ' . $topic_id;
  158. }
  159. else
  160. {
  161. send_status_line(404, 'Not Found');
  162. trigger_error('NO_ATTACHMENT_SELECTED');
  163. }
  164. $sql = 'SELECT attach_id, post_msg_id, topic_id, in_message, poster_id, is_orphan, physical_filename, real_filename, extension, mimetype, filesize, filetime
  165. FROM ' . ATTACHMENTS_TABLE . "
  166. WHERE $sql_where";
  167. $result = $db->sql_query($sql);
  168. $attachments = $attachment_ids = array();
  169. while ($row = $db->sql_fetchrow($result))
  170. {
  171. $attachment_id = (int) $row['attach_id'];
  172. $row['physical_filename'] = utf8_basename($row['physical_filename']);
  173. $attachment_ids[$attachment_id] = $attachment_id;
  174. $attachments[$attachment_id] = $row;
  175. }
  176. $db->sql_freeresult($result);
  177. // Make $attachment the first of the attachments we fetched.
  178. $attachment = current($attachments);
  179. if (empty($attachments))
  180. {
  181. send_status_line(404, 'Not Found');
  182. trigger_error('ERROR_NO_ATTACHMENT');
  183. }
  184. else if (!download_allowed())
  185. {
  186. send_status_line(403, 'Forbidden');
  187. trigger_error($user->lang['LINKAGE_FORBIDDEN']);
  188. }
  189. else if ($download_id)
  190. {
  191. // sizeof($attachments) == 1
  192. if (!$attachment['in_message'] && !$config['allow_attachments'] || $attachment['in_message'] && !$config['allow_pm_attach'])
  193. {
  194. send_status_line(404, 'Not Found');
  195. trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED');
  196. }
  197. if ($attachment['is_orphan'])
  198. {
  199. // We allow admins having attachment permissions to see orphan attachments...
  200. $own_attachment = ($auth->acl_get('a_attach') || $attachment['poster_id'] == $user->data['user_id']) ? true : false;
  201. if (!$own_attachment || ($attachment['in_message'] && !$auth->acl_get('u_pm_download')) || (!$attachment['in_message'] && !$auth->acl_get('u_download')))
  202. {
  203. send_status_line(404, 'Not Found');
  204. trigger_error('ERROR_NO_ATTACHMENT');
  205. }
  206. // Obtain all extensions...
  207. $extensions = $cache->obtain_attach_extensions(true);
  208. }
  209. else
  210. {
  211. if (!$attachment['in_message'])
  212. {
  213. phpbb_download_handle_forum_auth($db, $auth, $attachment['topic_id']);
  214. $sql = 'SELECT forum_id, post_visibility
  215. FROM ' . POSTS_TABLE . '
  216. WHERE post_id = ' . (int) $attachment['post_msg_id'];
  217. $result = $db->sql_query($sql);
  218. $post_row = $db->sql_fetchrow($result);
  219. $db->sql_freeresult($result);
  220. if (!$post_row || ($post_row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $post_row['forum_id'])))
  221. {
  222. // Attachment of a soft deleted post and the user is not allowed to see the post
  223. send_status_line(404, 'Not Found');
  224. trigger_error('ERROR_NO_ATTACHMENT');
  225. }
  226. }
  227. else
  228. {
  229. // Attachment is in a private message.
  230. $row['forum_id'] = false;
  231. phpbb_download_handle_pm_auth($db, $auth, $user->data['user_id'], $attachment['post_msg_id']);
  232. }
  233. $extensions = array();
  234. if (!extension_allowed($row['forum_id'], $attachment['extension'], $extensions))
  235. {
  236. send_status_line(403, 'Forbidden');
  237. trigger_error(sprintf($user->lang['EXTENSION_DISABLED_AFTER_POSTING'], $attachment['extension']));
  238. }
  239. }
  240. $download_mode = (int) $extensions[$attachment['extension']]['download_mode'];
  241. $display_cat = $extensions[$attachment['extension']]['display_cat'];
  242. if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))
  243. {
  244. $display_cat = ATTACHMENT_CATEGORY_NONE;
  245. }
  246. if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !$user->optionget('viewflash'))
  247. {
  248. $display_cat = ATTACHMENT_CATEGORY_NONE;
  249. }
  250. if ($thumbnail)
  251. {
  252. $attachment['physical_filename'] = 'thumb_' . $attachment['physical_filename'];
  253. }
  254. else if ($display_cat == ATTACHMENT_CATEGORY_NONE && !$attachment['is_orphan'] && !phpbb_http_byte_range($attachment['filesize']))
  255. {
  256. // Update download count
  257. phpbb_increment_downloads($db, $attachment['attach_id']);
  258. }
  259. 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))
  260. {
  261. wrap_img_in_html(append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'id=' . $attachment['attach_id']), $attachment['real_filename']);
  262. file_gc();
  263. }
  264. else
  265. {
  266. // Determine the 'presenting'-method
  267. if ($download_mode == PHYSICAL_LINK)
  268. {
  269. // This presenting method should no longer be used
  270. if (!@is_dir($phpbb_root_path . $config['upload_path']))
  271. {
  272. send_status_line(500, 'Internal Server Error');
  273. trigger_error($user->lang['PHYSICAL_DOWNLOAD_NOT_POSSIBLE']);
  274. }
  275. redirect($phpbb_root_path . $config['upload_path'] . '/' . $attachment['physical_filename']);
  276. file_gc();
  277. }
  278. else
  279. {
  280. send_file_to_browser($attachment, $config['upload_path'], $display_cat);
  281. file_gc();
  282. }
  283. }
  284. }
  285. else
  286. {
  287. // sizeof($attachments) >= 1
  288. if ($attachment['in_message'])
  289. {
  290. phpbb_download_handle_pm_auth($db, $auth, $user->data['user_id'], $attachment['post_msg_id']);
  291. }
  292. else
  293. {
  294. phpbb_download_handle_forum_auth($db, $auth, $attachment['topic_id']);
  295. }
  296. if (!class_exists('compress'))
  297. {
  298. require $phpbb_root_path . 'includes/functions_compress.' . $phpEx;
  299. }
  300. if (!in_array($archive, compress::methods()))
  301. {
  302. $archive = '.tar';
  303. }
  304. $post_visibility = array();
  305. if ($msg_id)
  306. {
  307. $sql = 'SELECT message_subject AS attach_subject
  308. FROM ' . PRIVMSGS_TABLE . "
  309. WHERE msg_id = $msg_id";
  310. }
  311. else if ($post_id)
  312. {
  313. $sql = 'SELECT post_subject AS attach_subject, forum_id, post_visibility
  314. FROM ' . POSTS_TABLE . "
  315. WHERE post_id = $post_id";
  316. }
  317. else
  318. {
  319. $sql = 'SELECT post_id, post_visibility
  320. FROM ' . POSTS_TABLE . "
  321. WHERE topic_id = $topic_id
  322. AND post_attachment = 1";
  323. $result = $db->sql_query($sql);
  324. while ($row = $db->sql_fetchrow($result))
  325. {
  326. $post_visibility[(int) $row['post_id']] = (int) $row['post_visibility'];
  327. }
  328. $db->sql_freeresult($result);
  329. $sql = 'SELECT topic_title AS attach_subject, forum_id
  330. FROM ' . TOPICS_TABLE . "
  331. WHERE topic_id = $topic_id";
  332. }
  333. $result = $db->sql_query($sql);
  334. $row = $db->sql_fetchrow($result);
  335. $db->sql_freeresult($result);
  336. if (empty($row))
  337. {
  338. send_status_line(404, 'Not Found');
  339. trigger_error('ERROR_NO_ATTACHMENT');
  340. }
  341. $clean_name = phpbb_download_clean_filename($row['attach_subject']);
  342. $suffix = '_' . (($msg_id) ? 'm' . $msg_id : (($post_id) ? 'p' . $post_id : 't' . $topic_id)) . '_' . $clean_name;
  343. $archive_name = 'attachments' . $suffix;
  344. $store_name = 'att_' . time() . '_' . unique_id();
  345. $archive_path = "{$phpbb_root_path}store/{$store_name}{$archive}";
  346. if ($archive === '.zip')
  347. {
  348. $compress = new compress_zip('w', $archive_path);
  349. }
  350. else
  351. {
  352. $compress = new compress_tar('w', $archive_path, $archive);
  353. }
  354. $extensions = array();
  355. $files_added = 0;
  356. $forum_id = ($attachment['in_message']) ? false : (int) $row['forum_id'];
  357. $disallowed_extension = array();
  358. foreach ($attachments as $attach)
  359. {
  360. if (!extension_allowed($forum_id, $attach['extension'], $extensions))
  361. {
  362. $disallowed_extension[$attach['extension']] = $attach['extension'];
  363. continue;
  364. }
  365. if ($post_id && $row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $forum_id))
  366. {
  367. // Attachment of a soft deleted post and the user is not allowed to see the post
  368. continue;
  369. }
  370. if ($topic_id && (!isset($post_visibility[$attach['post_msg_id']]) || $post_visibility[$attach['post_msg_id']] != ITEM_APPROVED) && !$auth->acl_get('m_approve', $forum_id))
  371. {
  372. // Attachment of a soft deleted post and the user is not allowed to see the post
  373. continue;
  374. }
  375. $prefix = '';
  376. if ($topic_id)
  377. {
  378. $prefix = $attach['post_msg_id'] . '_';
  379. }
  380. $compress->add_custom_file("{$phpbb_root_path}files/{$attach['physical_filename']}", "{$prefix}{$attach['real_filename']}");
  381. $files_added++;
  382. }
  383. $compress->close();
  384. if ($files_added)
  385. {
  386. phpbb_increment_downloads($db, $attachment_ids);
  387. $compress->download($store_name, $archive_name);
  388. }
  389. unlink($archive_path);
  390. if (!$files_added && !empty($disallowed_extension))
  391. {
  392. // None of the attachments had a valid extension
  393. $disallowed_extension = implode($user->lang['COMMA_SEPARATOR'], $disallowed_extension);
  394. send_status_line(403, 'Forbidden');
  395. trigger_error($user->lang('EXTENSION_DISABLED_AFTER_POSTING', $disallowed_extension));
  396. }
  397. else if (!$files_added)
  398. {
  399. send_status_line(404, 'Not Found');
  400. trigger_error('ERROR_NO_ATTACHMENT');
  401. }
  402. file_gc();
  403. }