1<?php 2# MantisBT - a php based bugtracking system 3 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. 8# 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. 13# 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/>. 16 17/** 18 * This upgrade moves attachments from the database to the disk 19 * @package MantisBT 20 * @copyright Copyright 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 21 * @copyright Copyright 2002 MantisBT Team - mantisbt-dev@lists.sourceforge.net 22 * @link http://www.mantisbt.org 23 */ 24 25require_once( dirname( dirname( __FILE__ ) ) . '/core.php' ); 26 27form_security_validate( 'move_attachments_project_select' ); 28 29access_ensure_global_level( config_get_global( 'admin_site_threshold' ) ); 30 31$f_file_type = gpc_get( 'type' ); 32$f_project_to_move = gpc_get( 'to_move', null ); 33 34/** 35 * Moves attachments from the specified list of projects from disk to database 36 * @param string $p_type Attachment type ('bug' or 'project') 37 * @param array $p_projects List of projects to process 38 * @return array summary of moves per project 39 */ 40function move_attachments_to_db( $p_type, $p_projects ) { 41 if( empty( $p_projects ) ) { 42 return array(); 43 } 44 45 # Build the SQL query based on attachment type 46 $t_file_table = '{' . $p_type . '_file}'; 47 switch( $p_type ) { 48 case 'project': 49 $t_query = "SELECT f.* 50 FROM {project_file} f 51 WHERE content = '' 52 AND f.project_id = " . db_param() . " 53 ORDER BY f.filename"; 54 break; 55 case 'bug': 56 $t_query = "SELECT f.* 57 FROM {bug_file} f 58 JOIN {bug} b ON b.id = f.bug_id 59 WHERE content = '' 60 AND b.project_id = " . db_param() . " 61 ORDER BY f.bug_id, f.filename"; 62 break; 63 } 64 65 # Process projects list 66 foreach( $p_projects as $t_project ) { 67 # Retrieve attachments for the project 68 $t_result = db_query( $t_query, array( $t_project ) ); 69 70 # Project upload path 71 $t_upload_path = project_get_field( $t_project, 'file_path' ); 72 if( is_blank( $t_upload_path ) ) { 73 $t_upload_path = config_get_global( 'absolute_path_default_upload_folder' ); 74 } 75 76 if( is_blank( $t_upload_path ) 77 || !file_exists( $t_upload_path ) 78 || !is_dir( $t_upload_path ) 79 ) { 80 # Invalid path 81 $t_failures = db_num_rows( $t_result ); 82 $t_data = "ERROR: Upload path '$t_upload_path' does not exist or is not accessible"; 83 } else { 84 # Process attachments 85 $t_failures = 0; 86 $t_data = array(); 87 88 while( $t_row = db_fetch_array( $t_result ) ) { 89 # read file from disk 90 $t_filename = $t_row['folder'] . $t_row['diskfile']; 91 92 if ( !file_exists( $t_filename ) ) { 93 $t_status = "Original File Not Found '$t_filename'"; 94 $t_failures++; 95 } else { 96 $c_content = db_prepare_binary_string( fread( fopen( $t_filename, 'rb' ), $t_row['filesize'] ) ); 97 98 # write file to db 99 if( db_is_oracle() ) { 100 db_update_blob( $t_file_table, 'content', $c_content, "id=" . (int)$t_row['id'] ); 101 $t_query = "UPDATE $t_file_table SET folder='' WHERE id = " . db_param(); 102 $t_result2 = db_query( $t_query, array( (int)$t_row['id'] ) ); 103 } else { 104 $t_update_query = "UPDATE $t_file_table 105 SET folder = " . db_param() . ", 106 content = " . db_param() . " 107 WHERE id = " . db_param(); 108 $t_result2 = db_query( $t_update_query, 109 array( '', $c_content, (int)$t_row['id'] ) 110 ); 111 } 112 113 if( !$t_result2 ) { 114 $t_status = 'Database update failed'; 115 $t_failures++; 116 } else { 117 $t_status = "'$t_filename' moved to database"; 118 } 119 } 120 121 # Add the file and status to the list of processed attachments 122 $t_file = array( 123 'id' => $t_row['id'], 124 'filename' => $t_row['filename'], 125 'status' => $t_status, 126 ); 127 if( $p_type == 'bug' ) { 128 $t_file['bug_id'] = $t_row['bug_id']; 129 } 130 $t_data[] = $t_file; 131 } 132 } 133 134 $t_moved[] = array( 135 'name' => project_get_name( $t_project ), 136 'path' => $t_upload_path, 137 'rows' => db_num_rows( $t_result ), 138 'failed' => $t_failures, 139 'data' => $t_data, 140 ); 141 142 } 143 return $t_moved; 144} 145 146/** 147 * Moves attachments from the specified list of projects from database to disk 148 * @param string $p_type Attachment type ('bug' or 'project'). 149 * @param array $p_projects List of projects to process. 150 * @return array summary of moves per project 151 */ 152function move_attachments_to_disk( $p_type, array $p_projects ) { 153 if( empty( $p_projects ) ) { 154 return array(); 155 } 156 157 # Build the SQL query based on attachment type 158 switch( $p_type ) { 159 case 'project': 160 $t_query = 'SELECT f.* 161 FROM {project_file} f 162 WHERE content <> \'\' 163 AND f.project_id = ' . db_param() . ' 164 ORDER BY f.filename'; 165 break; 166 case 'bug': 167 $t_query = 'SELECT f.* 168 FROM {bug_file} f 169 JOIN {bug} b ON b.id = f.bug_id 170 WHERE content <> \'\' 171 AND b.project_id = ' . db_param() . ' 172 ORDER BY f.bug_id, f.filename'; 173 break; 174 } 175 176 # Process projects list 177 foreach( $p_projects as $t_project ) { 178 # Retrieve attachments for the project 179 $t_result = db_query( $t_query, array( $t_project ) ); 180 181 # Project upload path 182 $t_upload_path = project_get_upload_path( $t_project ); 183 if( is_blank( $t_upload_path ) 184 || !file_exists( $t_upload_path ) 185 || !is_dir( $t_upload_path ) 186 || !is_writable( $t_upload_path ) 187 ) { 188 # Invalid path 189 $t_failures = db_num_rows( $t_result ); 190 $t_data = 'ERROR: Upload path \'' . $t_upload_path . '\' does not exist or is not writeable'; 191 } else { 192 # Process attachments 193 $t_failures = 0; 194 $t_data = array(); 195 196 while( $t_row = db_fetch_array( $t_result ) ) { 197 $t_disk_filename = $t_upload_path . $t_row['diskfile']; 198 if ( file_exists( $t_disk_filename ) ) { 199 $t_status = 'Disk File Already Exists \'' . $t_disk_filename . '\''; 200 $t_failures++; 201 } else { 202 # write file to disk 203 if( file_put_contents( $t_disk_filename, $t_row['content'] ) ) { 204 # successful, update database 205 # @todo do we want to check the size of data transfer matches here? 206 switch( $p_type ) { 207 case 'project': 208 $t_update_query = 'UPDATE {project_file} 209 SET folder = ' . db_param() . ', content = \'\' 210 WHERE id = ' . db_param(); 211 break; 212 case 'bug': 213 $t_update_query = 'UPDATE {bug_file} 214 SET folder = ' . db_param() . ', content = \'\' 215 WHERE id = ' . db_param(); 216 break; 217 } 218 $t_update_result = db_query( 219 $t_update_query, 220 array( $t_upload_path, $t_row['id'] ) 221 ); 222 223 if( !$t_update_result ) { 224 $t_status = 'Database update failed'; 225 $t_failures++; 226 } else { 227 $t_status = 'Moved to \'' . $t_disk_filename . '\''; 228 } 229 } else { 230 $t_status = 'Copy to \'' . $t_disk_filename . '\' failed'; 231 $t_failures++; 232 } 233 } 234 235 # Add the file and status to the list of processed attachments 236 $t_file = array( 237 'id' => $t_row['id'], 238 'filename' => $t_row['filename'], 239 'status' => $t_status, 240 ); 241 if( $p_type == 'bug' ) { 242 $t_file['bug_id'] = $t_row['bug_id']; 243 } 244 $t_data[] = $t_file; 245 } 246 } 247 248 $t_moved[] = array( 249 'name' => project_get_name( $t_project ), 250 'path' => $t_upload_path, 251 'rows' => db_num_rows( $t_result ), 252 'failed' => $t_failures, 253 'data' => $t_data, 254 ); 255 256 } 257 return $t_moved; 258} 259 260form_security_purge( 'move_attachments_project_select' ); 261 262# Page header, menu 263layout_page_header( 'MantisBT Administration - Moving Attachments' ); 264 265layout_admin_page_begin(); 266 267?> 268 269<div class="col-md-12 col-xs-12"> 270 <div class="space-10"></div> 271 272<?php 273 274if( null == $f_project_to_move ) { 275 echo '<div class="alert alert-danger">'; 276 echo '<p class="lead"><strong>Opps!</strong> Please select the project you want to move the attachment.</p>'; 277 echo '</div>'; 278} else { 279 280 $t_moved = array(); 281 282 foreach( $f_project_to_move as $t_project_to_move ) { 283 284 $t_array = explode( ':', $t_project_to_move ); 285 286 if( isset( $t_array[1] ) ) { 287 $t_project_id = $t_array[1]; 288 289 switch( $t_array[0] ) { 290 case 'disk': 291 $t_moved[] = move_attachments_to_disk( $f_file_type, array( $t_project_id ) ); 292 break; 293 case 'db': 294 $t_moved[] = move_attachments_to_db( $f_file_type, array( $t_project_id ) ); 295 break; 296 } 297 } 298 } 299 300 # Display results 301 if( empty( $t_moved ) ) { 302 echo '<div class="alert alert-danger">'; 303 echo '<p class="lead">Nothing to do.</p>'; 304 echo '</div>'; 305 } else { 306 foreach( $t_moved as $t_row ) { 307 $t_row = $t_row[0]; 308 309 echo '<div class="widget-box widget-color-blue2">'; 310 echo '<div class="widget-header widget-header-small">'; 311 echo '<h4 class="widget-title lighter">'; 312 print_icon( 'fa-paperclip', 'ace-icon' ); 313 printf( 314 "Project '%s' : %d attachments %s", 315 $t_row['name'], 316 $t_row['rows'], 317 ( 0 == $t_row['failed'] 318 ? 'moved successfully' 319 : 'to move, ' . $t_row['failed'] . ' failures') 320 ); 321 echo '</h4>'; 322 echo '</div>'; 323 echo '<div class="widget-body">'; 324 echo '<div class="widget-main no-padding">'; 325 if( is_array( $t_row['data'] ) ) { 326 # Display details of moved attachments 327 echo '<div class="table-responsive">'; 328 echo '<table class="table table-bordered table-condensed table-hover table-striped">'; 329 echo '<thead>'; 330 echo '<tr>', 331 $f_file_type == 'bug' ? '<td width="5%">Bug ID</td>' : '', 332 '<td width="3%">File ID</td><th width="15%">Filename</td><td width="25%">Status</td>', 333 '</tr>'; 334 echo '</thead>'; 335 echo '<tbody>'; 336 foreach( $t_row['data'] as $t_data ) { 337 echo '<tr>'; 338 if( $f_file_type == 'bug' ) { 339 printf( '<td>%s</td>', bug_format_id( $t_data['bug_id'] ) ); 340 } 341 printf( '<td>%s</td><td>%s</td><td>%s</td></tr>', 342 $t_data['id'], 343 $t_data['filename'], 344 $t_data['status'] ); 345 } 346 echo '</tbody>'; 347 echo '</table>'; 348 echo '</div>'; 349 350 } else { 351 # No data rows - display error message 352 echo '<div class="alert alert-danger">'; 353 echo '<p>' . $t_row['data'] . '</p>'; 354 echo '</div>'; 355 } 356 echo '</div>'; 357 echo '</div>'; 358 echo '</div>'; 359 echo '<br/>'; 360 } 361 } 362} 363echo '<br/>'; 364print_link_button( 'system_utils.php', 'Back to System Utilities' ); 365 366echo '</div>'; 367 368layout_admin_page_end(); 369