SOAP API: do not try to unserialize an invalid filter
[mantis.git] / file_download.php
blobc807f5dc57d84e41cbf984e57dbca371e3c607c5
1 <?php
2 # MantisBT - A PHP based bugtracking system
4 # MantisBT is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 2 of the License, or
7 # (at your option) any later version.
9 # MantisBT is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * Add file and redirect to the referring page
20 * @package MantisBT
21 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
22 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net
23 * @link http://www.mantisbt.org
25 * @uses core.php
26 * @uses access_api.php
27 * @uses authentication_api.php
28 * @uses bug_api.php
29 * @uses config_api.php
30 * @uses constant_inc.php
31 * @uses database_api.php
32 * @uses file_api.php
33 * @uses gpc_api.php
34 * @uses http_api.php
35 * @uses utility_api.php
38 $g_bypass_headers = true; # suppress headers as we will send our own later
39 define( 'COMPRESSION_DISABLED', true );
41 /**
42 * MantisBT Core API's
44 require_once( 'core.php' );
45 require_api( 'access_api.php' );
46 require_api( 'authentication_api.php' );
47 require_api( 'bug_api.php' );
48 require_api( 'config_api.php' );
49 require_api( 'constant_inc.php' );
50 require_api( 'database_api.php' );
51 require_api( 'file_api.php' );
52 require_api( 'gpc_api.php' );
53 require_api( 'http_api.php' );
54 require_api( 'utility_api.php' );
56 auth_ensure_user_authenticated();
58 $f_show_inline = gpc_get_bool( 'show_inline', false );
60 # To prevent cross-domain inline hotlinking to attachments we require a CSRF
61 # token from the user to show any attachment inline within the browser.
62 # Without this security in place a malicious user could upload a HTML file
63 # attachment and direct a user to file_download.php?file_id=X&type=bug&show_inline=1
64 # and the malicious HTML content would be rendered in the user's browser,
65 # violating cross-domain security.
66 if ( $f_show_inline ) {
67 # Disable errors for form_security_validate as we need to send HTTP
68 # headers prior to raising an error (the error handler within
69 # error_api.php doesn't check that headers have been sent, it just
70 # makes the assumption that they've been sent already).
71 if ( !@form_security_validate( 'file_show_inline' ) ) {
72 http_all_headers();
73 trigger_error( ERROR_FORM_TOKEN_INVALID, ERROR );
77 $f_file_id = gpc_get_int( 'file_id' );
78 $f_type = gpc_get_string( 'type' );
80 $c_file_id = (integer)$f_file_id;
82 # we handle the case where the file is attached to a bug
83 # or attached to a project as a project doc.
84 $query = '';
85 switch ( $f_type ) {
86 case 'bug':
87 $t_bug_file_table = db_get_table( 'bug_file' );
88 $query = "SELECT *
89 FROM $t_bug_file_table
90 WHERE id=" . db_param();
91 break;
92 case 'doc':
93 $t_project_file_table = db_get_table( 'project_file' );
94 $query = "SELECT *
95 FROM $t_project_file_table
96 WHERE id=" . db_param();
97 break;
98 default:
99 access_denied();
101 $result = db_query_bound( $query, Array( $c_file_id ) );
102 $row = db_fetch_array( $result );
103 extract( $row, EXTR_PREFIX_ALL, 'v' );
105 if ( $f_type == 'bug' ) {
106 $t_project_id = bug_get_field( $v_bug_id, 'project_id' );
107 } else {
108 $t_project_id = $v_project_id;
111 # Check access rights
112 switch ( $f_type ) {
113 case 'bug':
114 if ( !file_can_download_bug_attachments( $v_bug_id, (int)$v_user_id ) ) {
115 access_denied();
117 break;
118 case 'doc':
119 # Check if project documentation feature is enabled.
120 if ( OFF == config_get( 'enable_project_documentation' ) ) {
121 access_denied();
124 access_ensure_project_level( config_get( 'view_proj_doc_threshold' ), $v_project_id );
125 break;
128 # throw away output buffer contents (and disable it) to protect download
129 while ( @ob_end_clean() );
131 if ( ini_get( 'zlib.output_compression' ) && function_exists( 'ini_set' ) ) {
132 ini_set( 'zlib.output_compression', false );
135 http_security_headers();
137 # Make sure that IE can download the attachments under https.
138 header( 'Pragma: public' );
140 # To fix an IE bug which causes problems when downloading
141 # attached files via HTTPS, we disable the "Pragma: no-cache"
142 # command when IE is used over HTTPS.
143 global $g_allow_file_cache;
144 if ( ( isset( $_SERVER["HTTPS"] ) && ( "on" == utf8_strtolower( $_SERVER["HTTPS"] ) ) ) && is_browser_internet_explorer() ) {
145 # Suppress "Pragma: no-cache" header.
146 } else {
147 if ( !isset( $g_allow_file_cache ) ) {
148 header( 'Pragma: no-cache' );
151 header( 'Expires: ' . gmdate( 'D, d M Y H:i:s \G\M\T', time() ) );
153 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s \G\M\T', $v_date_added ) );
155 $t_filename = file_get_display_name( $v_filename );
157 # For Internet Explorer 8 as per http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
158 # Don't let IE second guess our content-type!
159 header( 'X-Content-Type-Options: nosniff' );
161 http_content_disposition_header( $t_filename, $f_show_inline );
163 header( 'Content-Length: ' . $v_filesize );
165 # If finfo is available (always true for PHP >= 5.3.0) we can use it to determine the MIME type of files
166 $finfo_available = false;
167 if ( class_exists( 'finfo' ) ) {
168 $t_info_file = config_get( 'fileinfo_magic_db_file' );
170 if ( is_blank( $t_info_file ) ) {
171 $finfo = new finfo( FILEINFO_MIME );
172 } else {
173 $finfo = new finfo( FILEINFO_MIME, $t_info_file );
176 if ( $finfo ) {
177 $finfo_available = true;
181 $t_content_type = $v_file_type;
183 # dump file content to the connection.
184 switch ( config_get( 'file_upload_method' ) ) {
185 case DISK:
186 $t_local_disk_file = file_normalize_attachment_path( $v_diskfile, $t_project_id );
188 if ( file_exists( $t_local_disk_file ) ) {
189 if ( $finfo_available ) {
190 $t_file_info_type = $finfo->file( $t_local_disk_file );
192 if ( $t_file_info_type !== false ) {
193 $t_content_type = $t_file_info_type;
197 header( 'Content-Type: ' . $t_content_type );
198 if ( config_get( 'file_download_xsendfile_enabled' ) ) {
199 $t_xsendfile_header_name = config_get( 'file_download_xsendfile_header_name' );
200 header( $t_xsendfile_header_name . ': ' . $t_local_disk_file );
201 } else {
202 readfile( $t_local_disk_file );
205 break;
206 case FTP:
207 $t_local_disk_file = file_normalize_attachment_path( $v_diskfile, $t_project_id );
209 if ( !file_exists( $t_local_disk_file ) ) {
210 $ftp = file_ftp_connect();
211 file_ftp_get ( $ftp, $t_local_disk_file, $v_diskfile );
212 file_ftp_disconnect( $ftp );
215 if ( $finfo_available ) {
216 $t_file_info_type = $finfo->file( $t_local_disk_file );
218 if ( $t_file_info_type !== false ) {
219 $t_content_type = $t_file_info_type;
223 header( 'Content-Type: ' . $t_content_type );
224 readfile( $t_local_disk_file );
225 break;
226 default:
227 if ( $finfo_available ) {
228 $t_file_info_type = $finfo->buffer( $v_content );
230 if ( $t_file_info_type !== false ) {
231 $t_content_type = $t_file_info_type;
235 header( 'Content-Type: ' . $t_content_type );
236 echo $v_content;