View Issue Details

IDProjectCategoryView StatusLast Update
0017758mantisbtattachmentspublic2014-10-28 16:28
ReporterKulssaka Assigned Todregad  
PrioritynormalSeveritytweakReproducibilityalways
Status closedResolutionwon't fix 
Product Version1.2.17 
Summary0017758: Moved attachment files doesn't have the correct name
Description

Hello,

After reading: http://www.mantisbt.org/bugs/view.php?id=15496
I saw it was not up to date, so I open a new bug issue.

So I have to export the attachment, and decided to change the file upload to DISK rather than DATABASE.
Until then everything is ok, but when I look the name of the file, it is not correct.

So I was wondering if the bug you corrected in the old version of "move_attachments.php" which was "move_db2disk.php" reappeared ?

The filename I get is some kind of hash, not the name of the file, and the extension is deleted.

How do I modify the script so it copy the file with the correct name and extensions ?

I tried to remove what I thought was the hash function:

line 104 was
$t_filename = $t_upload_path . file_generate_unique_name( $t_seed, $t_upload_path );
and I replaced by:
$t_filename = $t_upload_path . $t_row['filename'];

the result was that 2 files appeared instead of one.
The correct file with the correct content, but with a wrong name and no extension. The second file has the correct name and extension, but the content is only ''.

Steps To Reproduce

use move_attachments.php then see that the "filename.extension" became some "hash".

change line 104 of move_attachments.php by
$t_filename = $t_upload_path . $t_row['filename'];

TagsNo tags attached.
Attached Files
move_attachments.php (6,181 bytes)   
<?php
# MantisBT - a php based bugtracking system

# MantisBT is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# MantisBT is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MantisBT.  If not, see <http://www.gnu.org/licenses/>.

/**
 * This upgrade moves attachments from the database to the disk
 * @package MantisBT
 * @copyright Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
 * @copyright Copyright (C) 2002 - 2014  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 * @link http://www.mantisbt.org
 */


/**
 * MantisBT Core API's
 */
require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' );

form_security_validate( 'move_attachments_project_select' );

access_ensure_global_level( config_get_global( 'admin_site_threshold' ) );


$f_file_type         = gpc_get( 'type' );
$f_projects_to_disk  = gpc_get( 'to_disk', null );


/**
 * Moves attachments from the specified list of projects from database to disk
 * @param string $p_type Attachment type ('bug' or 'project')
 * @param array $p_projects List of projects to process
 * @return array summary of moves per project
 */
function move_attachments_to_disk( $p_type, $p_projects ) {
	if( empty( $p_projects ) ) {
		return array();
	}

	# Build the SQL query based on attachment type
	$t_file_table = db_get_table( "mantis_${p_type}_file_table" );
	switch( $p_type ) {
		case 'project':

			$t_query = "SELECT f.*
				FROM $t_file_table f
				WHERE content <> ''
				  AND f.project_id = " . db_param() . "
				ORDER BY f.filename";
			break;

		case 'bug':
			$t_bug_table = db_get_table( 'mantis_bug_table' );

			$t_query = "SELECT f.*
				FROM $t_file_table f
				JOIN $t_bug_table b ON b.id = f.bug_id
				WHERE content <> ''
				  AND b.project_id = " . db_param() . "
				ORDER BY f.bug_id, f.filename";
			break;
	}

	# Process projects list
	foreach( $p_projects as $t_project ) {
		# Retrieve attachments for the project
		$t_result = db_query_bound( $t_query, array( $t_project ) );

		# Project upload path
		$t_upload_path = project_get_upload_path( $t_project );
		if(    is_blank( $t_upload_path )
			|| !file_exists( $t_upload_path )
			|| !is_dir( $t_upload_path )
			|| !is_writable( $t_upload_path )
		) {
			# Invalid path
			$t_failures = db_num_rows( $t_result );
			$t_data = "ERROR: Upload path '$t_upload_path' does not exist or is not writable";
		} else {
			# Process attachments
			$t_failures = 0;
			$t_data = array();

			if( $p_type == 'project' ) {
				$t_seed = config_get( 'document_files_prefix', null, ALL_USERS, $t_project ) . $t_project;
			}

			while( $t_row = db_fetch_array( $t_result ) ) {
				if( $p_type == 'bug' ) {
					$t_seed = $t_row['bug_id'] . $t_row['filename'];
				}

				#$t_filename = $t_upload_path . file_generate_unique_name( $t_seed, $t_upload_path );
				$t_filename = $t_upload_path . $t_row['filename'];
				
				# write file to disk
				if( file_put_contents( $t_filename, $t_row['content'] ) ) {
					# successful, update database
					# @todo do we want to check the size of data transfer matches here?
					$t_update_query = "UPDATE $t_file_table
						SET diskfile = " . db_param() . ",
							folder = " . db_param() . ",
							content = ''
						WHERE id = " . db_param();
					$t_update_result = db_query_bound(
						$t_update_query,
						array( $t_filename, $t_upload_path, $t_row['id'] )
					);
					
					if( !$t_update_result ) {
						$t_status = 'Database update failed';
						$t_failures++;
					} else {
						$t_status = "Moved to '$t_filename'";
					}
				} else {
					$t_status = "Copy to '$t_filename' failed";
					$t_failures++;
				}

				# Add the file and status to the list of processed attachments
				$t_file = array(
					'id' => $t_row['id'],
					'filename' => $t_row['filename'],
					'status' => $t_status,
				);
				if( $p_type == 'bug' ) {
					$t_file['bug_id'] = $t_row['bug_id'];
				}
				$t_data[] = $t_file;
			}
		}

		$t_moved[] = array(
			'name'       => project_get_name( $t_project ),
			'path'       => $t_upload_path,
			'rows'       => db_num_rows( $t_result ),
			'failed'     => $t_failures,
			'data'       => $t_data,
		);

	}
	return $t_moved;
}


$t_moved = move_attachments_to_disk( $f_file_type, $f_projects_to_disk );

form_security_purge( 'move_attachments_project_select' );

$t_redirect_url = 'admin/system_utils.php';

# Page header, menu
html_page_top(
	'MantisBT Administration - Moving Attachments',
	empty( $t_result ) ? $t_redirect_url : null
);

?>

<div align="center">

<?php

# Display results
if( empty( $t_moved ) ) {
	echo "<p>Nothing to do.</p>\n";
} else {
	foreach( $t_moved as $t_row ) {
		printf(
			"<p class=\"bold\">Project '%s' : %d attachments %s.</p>\n",
			$t_row['name'],
			$t_row['rows'],
			( 0 == $t_row['failed']
				? 'moved successfully'
				: 'to move, ' . $t_row['failed'] . ' failures')
		);

		if( is_array( $t_row['data'] ) ) {
			# Display details of moved attachments
			echo '<div><table class="width75">', "\n",
				'<tr class="row-category">',
				$f_file_type == 'bug' ? '<th>Bug ID</th>' : '',
				'<th>File</th><th>Filename</th><th>Status</th>',
				'</tr>';
			foreach( $t_row['data'] as $t_data ) {
				echo '<tr ' . helper_alternate_class() .'>';
				if( $f_file_type == 'bug' ) {
					printf( '<td>%s</td>', bug_format_id( $t_data['bug_id'] ) );
				}
				printf( '<td class="right">%s</td><td>%s</td><td>%s</td></tr>' . "\n",
					$t_data['id'],
					$t_data['filename'],
					$t_data['status']
				);
			}
			echo '</table><br /></div>';
		} else {
			# No data rows - display error message
			echo '<p>' . $t_row['data'] . '</p>';
		}
		echo '<br />';
	}
}

print_bracket_link( $t_redirect_url, 'Back to System Utilities' );

html_page_bottom();
move_attachments.php (6,181 bytes)   

Relationships

related to 0015496 closeddregad Script to move attachments from db to disk not working 

Activities

atrol

atrol

2014-10-14 16:16

developer   ~0041571

Do you get any errors when downloading the attachments or do you just don't like the file names on disk?

dregad

dregad

2014-10-15 03:38

developer   ~0041583

The filename I get is some kind of hash, not the name of the file, and the extension is deleted.

This is by design, and guarantees that the filenames are unique.

If you wish to download all attachments, I suggest you use the file_download.php page, or write a custom script using our APIs.

Kulssaka

Kulssaka

2014-10-15 03:44

reporter   ~0041584

Where can I get file_download.php ? I don't have it in basic admin scripts.

atrol

atrol

2014-10-15 03:49

developer   ~0041585

file_download.php is in the root directory of your MantisBT installation.

Kulssaka

Kulssaka

2014-10-15 03:59

reporter   ~0041587

Ok, I am sorry for next question, but I'm really new to Mantis (and php), and I am not sure how to use the script.

I want to download all attachments, but where is the button to start file_download.php ?

Shall I modify actual code, and next to csv export, put a button calling file_download.php ? Or is there a value to set up to activate it in the config ?

Thanks for helping me :)

dregad

dregad

2014-10-15 04:05

developer   ~0041588

The script will download a single attachment, you can see an example of how it's used by hovering your mouse over an attachment (see the relevant section higher up on this very page), and looking at the generated URL.

Kulssaka

Kulssaka

2014-10-15 04:16

reporter   ~0041589

Ah I see thanks where file_download.php is used :)

Then I should write a script to download all the attachments in a row.

I will try a mix between file_download.php and move_attachments.php.

You should consider a feature for version 1.3 !

Regards,
Kevin