View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0011687 | mantisbt | attachments | public | 2010-03-19 18:23 | 2014-09-23 18:05 |
Reporter | jchoover | Assigned To | dregad | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Product Version | 1.2.0 | ||||
Target Version | 1.2.12 | Fixed in Version | 1.2.12 | ||
Summary | 0011687: Bugs with attachments that are moved will lose attachments | ||||
Description | When a bug is logged and assigned to a project which has a project path assigned, and later a mantis "administrator" moves the bug from the initial project to a new project, the attachments are lost. | ||||
Steps To Reproduce | Configure an instance of Mantis 1.2.0 with 2+ projects, each having a custom data folder for uploads. Log an issue in one project, attach a file, and then move the attachment to another project. The bug page reports the attachment as missing. | ||||
Additional Information | The file is never moved on disk, so it is still sitting in the initial project folder. From my crash course on Mantis debugging I came up with: <Moves the bug, but not the attachments on disk.> <returns the list of visible attachments> function file_get_visible_attachments( $p_bug_id ) { function file_normalize_attachment_path( $p_diskfile, $p_project_id ) { | ||||
Tags | patch | ||||
Attached Files | file_api.mod.txt (3,138 bytes)
/** * Move a single file named $p_basename from $p_file_path_from to $p_file_path_to */ function file_move_bug_attachment( $p_basename, $p_file_path_from, $p_file_path_to ) { $t_method = config_get( 'file_upload_method' ); $t_disk_file_name_from = file_path_combine( $p_file_path_from, $p_basename ); $t_disk_file_name_to = file_path_combine( $p_file_path_to, $p_basename ); switch( $t_method ) { case FTP: case DISK: file_ensure_valid_upload_path( $p_file_path_from ); file_ensure_valid_upload_path( $p_file_path_to ); if( !file_exists( $t_disk_file_name_to ) ) { if ( function_exists('link') ) { if( !link( $t_disk_file_name_from, $t_disk_file_name_to ) ) { trigger_error( FILE_MOVE_FAILED, ERROR ); } chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) ); file_delete_local( $t_disk_file_name_from ); } else { // Windows doesn't support link, so simulate a link if ( !rename( $t_disk_file_name_from, $t_disk_file_name_to ) ) { if ( !copy( $t_disk_file_name_from, $t_disk_file_name_to ) ) { trigger_error( FILE_MOVE_FAILED, ERROR ); } file_delete_local( $t_disk_file_name_from ); } chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) ); } } else { trigger_error( ERROR_FILE_DUPLICATE, ERROR ); } break; case DATABASE: break; default: trigger_error( ERROR_GENERIC, ERROR ); } return true; } /** * Move any attachements as needed when a bug is moved from project to project * * @param integer $p_bug_id the bug id * @param integer $p_project_id_from the project id the bug was in * @param integer $p_project_id_to the project id the bug was moved to */ function file_move_bug_attachments( $p_bug_id, $p_project_id_from, $p_project_id_to ) { if ( $p_project_id_from == $p_project_id_to ) { return true; } if ( file_bug_has_attachments($p_bug_id) == true && config_get( 'file_upload_method' ) != DATABASE ){ $t_path_from = project_get_field( $p_project_id_from, 'file_path' ); if ( is_blank( $t_path_from ) ) { $t_path_from = config_get( 'absolute_path_default_upload_folder' ); } $t_path_to = project_get_field( $p_project_id_to, 'file_path' ); if ( is_blank( $t_path_to ) ) { $t_path_to = config_get( 'absolute_path_default_upload_folder' ); } if ( $t_path_from == $t_path_to ) { return true; } $t_attachment_rows = bug_get_attachments( $p_bug_id ); $t_attachments_count = count( $t_attachment_rows ); $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); $c_bug_id = db_prepare_int( $p_bug_id ); for( $i = 0;$i < $t_attachments_count;$i++ ) { $t_row = $t_attachment_rows[$i]; $t_basename = basename( $t_row['diskfile'] ); file_move_bug_attachment( $t_basename, $t_path_from, $t_path_to); # Update the corresponding db record $query = "UPDATE $t_bug_file_table SET folder=" . db_param() . " WHERE bug_id=" . db_param() . " AND id =" . db_param(); db_query_bound( $query, Array( db_prepare_string( $t_path_to ), $c_bug_id, db_prepare_int( $t_row['id'] ) ) ); } } } 0001-Mantis-11687-Disk-based-attachments-get-lost-when-a-.patch (4,851 bytes)
From 3c1beba557d23ef496f6b26de7eee284e99450e1 Mon Sep 17 00:00:00 2001 From: unknown <Hoover@.greenops.com> Date: Sun, 4 Apr 2010 11:44:01 -0500 Subject: [PATCH] Mantis #11687 - Disk based attachments get lost when a bug is moved across projects --- bug_actiongroup.php | 3 ++ core/file_api.php | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 0 deletions(-) diff --git a/bug_actiongroup.php b/bug_actiongroup.php index 4e70bb1..aafb28e 100644 --- a/bug_actiongroup.php +++ b/bug_actiongroup.php @@ -53,6 +53,7 @@ require_api( 'config_api.php' ); require_api( 'constant_inc.php' ); require_api( 'custom_field_api.php' ); require_api( 'event_api.php' ); +require_api( 'file_api.php' ); require_api( 'form_api.php' ); require_api( 'gpc_api.php' ); require_api( 'helper_api.php' ); @@ -136,7 +137,9 @@ foreach( $f_bug_arr as $t_bug_id ) { if ( access_has_bug_level( config_get( 'move_bug_threshold' ), $t_bug_id ) ) { /** @todo we need to issue a helper_call_custom_function( 'issue_update_validate', array( $t_bug_id, $t_bug_data, $f_bugnote_text ) ); */ $f_project_id = gpc_get_int( 'project_id' ); + $t_origional_bug_project = bug_get_field( $t_bug_id, 'project_id' ); bug_set_field( $t_bug_id, 'project_id', $f_project_id ); + file_move_bug_attachments( $t_bug_id, $t_origional_bug_project, $f_project_id ); helper_call_custom_function( 'issue_update_notify', array( $t_bug_id ) ); } else { $t_failed_ids[$t_bug_id] = lang_get( 'bug_actiongroup_access' ); diff --git a/core/file_api.php b/core/file_api.php index 4ead250..1555ca8 100644 --- a/core/file_api.php +++ b/core/file_api.php @@ -870,3 +870,82 @@ function file_get_extension( $p_filename ) { } return $t_extension; } + +/** + * Move any attachements as needed when a bug is moved from project to project + * + * @param integer $p_bug_id the bug id + * @param integer $p_project_id_from the project id the bug was in + * @param integer $p_project_id_to the project id the bug was moved to + */ +function file_move_bug_attachments( $p_bug_id, $p_project_id_from, $p_project_id_to ) { + if ( $p_project_id_from == $p_project_id_to ) { + return true; + } + + $t_method = config_get( 'file_upload_method' ); + + # Optimization here, as DB atachments don't need to be moved. + if ( file_bug_has_attachments($p_bug_id) == true && $t_method != DATABASE ){ + $t_path_from = project_get_field( $p_project_id_from, 'file_path' ); + if ( is_blank( $t_path_from ) ) { + $t_path_from = config_get( 'absolute_path_default_upload_folder' ); + } + $t_path_to = project_get_field( $p_project_id_to, 'file_path' ); + if ( is_blank( $t_path_to ) ) { + $t_path_to = config_get( 'absolute_path_default_upload_folder' ); + } + if ( $t_path_from == $t_path_to ) { + return true; + } + + $t_attachment_rows = bug_get_attachments( $p_bug_id ); + $t_attachments_count = count( $t_attachment_rows ); + $t_bug_file_table = db_get_table( 'bug_file' ); + $c_bug_id = db_prepare_int( $p_bug_id ); + + # Initialize the update query to update a single row + $query_disk_attachment_update = "UPDATE $t_bug_file_table + SET folder=" . db_param() . " + WHERE bug_id=" . db_param() . " + AND id =" . db_param(); + + file_ensure_valid_upload_path( $t_path_from ); + file_ensure_valid_upload_path( $t_path_to ); + + for( $i = 0;$i < $t_attachments_count;$i++ ) { + $t_row = $t_attachment_rows[$i]; + $t_basename = basename( $t_row['diskfile'] ); + + $t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename ); + $t_disk_file_name_to = file_path_combine( $t_path_to, $t_basename ); + + switch( $t_method ) { + case FTP: + case DISK: + # In the case of FTP storage, it's my understanding that all the files are stored + # in a single folder, so we don't need to do anything with the remote ftp backup + if( !file_exists( $t_disk_file_name_to ) ) { + chmod( $t_disk_file_name_from, 0775 ); + if ( !rename( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + if ( !copy( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + trigger_error( FILE_MOVE_FAILED, ERROR ); + } + file_delete_local( $t_disk_file_name_from ); + } + chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) ); + db_query_bound( $query_disk_attachment_update, Array( db_prepare_string( $t_path_to ), $c_bug_id, db_prepare_int( $t_row['id'] ) ) ); + } else { + trigger_error( ERROR_FILE_DUPLICATE, ERROR ); + } + break; + case DATABASE: + # Nothing to do with DB storage, but if we needed to update any meta data, we would remove the upper + # optimization, and then update here + break; + default: + trigger_error( ERROR_GENERIC, ERROR ); + } + } + } +} -- 1.7.0.2.msysgit.0 0001-Fix-11687-Bugs-with-attachments-(1.2.1).patch (4,559 bytes)
From 66bf62296c075da741877e54efba4ab63633a0fc Mon Sep 17 00:00:00 2001 From: Jacob Hoover <jacob.hoover@greenheck.com> Date: Mon, 3 May 2010 23:45:42 -0500 Subject: [PATCH] Fix #11687: Bugs with attachments that are moved will lose attachments --- bug_actiongroup.php | 2 + core/file_api.php | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 0 deletions(-) diff --git a/bug_actiongroup.php b/bug_actiongroup.php index 7d72793..fb68327 100644 --- a/bug_actiongroup.php +++ b/bug_actiongroup.php @@ -101,7 +101,9 @@ if ( access_has_bug_level( config_get( 'move_bug_threshold' ), $t_bug_id ) ) { /** @todo we need to issue a helper_call_custom_function( 'issue_update_validate', array( $t_bug_id, $t_bug_data, $f_bugnote_text ) ); */ $f_project_id = gpc_get_int( 'project_id' ); + $t_origional_bug_project = bug_get_field( $t_bug_id, 'project_id' ); bug_set_field( $t_bug_id, 'project_id', $f_project_id ); + file_move_bug_attachments( $t_bug_id, $t_origional_bug_project, $f_project_id ); helper_call_custom_function( 'issue_update_notify', array( $t_bug_id ) ); } else { $t_failed_ids[$t_bug_id] = lang_get( 'bug_actiongroup_access' ); diff --git a/core/file_api.php b/core/file_api.php index 4729d4d..6973245 100644 --- a/core/file_api.php +++ b/core/file_api.php @@ -855,3 +855,82 @@ function file_get_extension( $p_filename ) { } return $t_extension; } + +/** + * Move any attachements as needed when a bug is moved from project to project + * + * @param integer $p_bug_id the bug id + * @param integer $p_project_id_from the project id the bug was in + * @param integer $p_project_id_to the project id the bug was moved to + */ +function file_move_bug_attachments( $p_bug_id, $p_project_id_from, $p_project_id_to ) { + if ( $p_project_id_from == $p_project_id_to ) { + return true; + } + + $t_method = config_get( 'file_upload_method' ); + + # Optimization here, as DB atachments don't need to be moved. + if ( file_bug_has_attachments($p_bug_id) == true && $t_method != DATABASE ){ + $t_path_from = project_get_field( $p_project_id_from, 'file_path' ); + if ( is_blank( $t_path_from ) ) { + $t_path_from = config_get( 'absolute_path_default_upload_folder' ); + } + $t_path_to = project_get_field( $p_project_id_to, 'file_path' ); + if ( is_blank( $t_path_to ) ) { + $t_path_to = config_get( 'absolute_path_default_upload_folder' ); + } + if ( $t_path_from == $t_path_to ) { + return true; + } + + $t_attachment_rows = bug_get_attachments( $p_bug_id ); + $t_attachments_count = count( $t_attachment_rows ); + $t_bug_file_table = db_get_table( 'bug_file' ); + $c_bug_id = db_prepare_int( $p_bug_id ); + + # Initialize the update query to update a single row + $query_disk_attachment_update = "UPDATE $t_bug_file_table + SET folder=" . db_param() . " + WHERE bug_id=" . db_param() . " + AND id =" . db_param(); + + file_ensure_valid_upload_path( $t_path_from ); + file_ensure_valid_upload_path( $t_path_to ); + + for( $i = 0;$i < $t_attachments_count;$i++ ) { + $t_row = $t_attachment_rows[$i]; + $t_basename = basename( $t_row['diskfile'] ); + + $t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename ); + $t_disk_file_name_to = file_path_combine( $t_path_to, $t_basename ); + + switch( $t_method ) { + case FTP: + case DISK: + # In the case of FTP storage, it's my understanding that all the files are stored + # in a single folder, so we don't need to do anything with the remote ftp backup + if( !file_exists( $t_disk_file_name_to ) ) { + chmod( $t_disk_file_name_from, 0775 ); + if ( !rename( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + if ( !copy( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + trigger_error( FILE_MOVE_FAILED, ERROR ); + } + file_delete_local( $t_disk_file_name_from ); + } + chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) ); + db_query_bound( $query_disk_attachment_update, Array( db_prepare_string( $t_path_to ), $c_bug_id, db_prepare_int( $t_row['id'] ) ) ); + } else { + trigger_error( ERROR_FILE_DUPLICATE, ERROR ); + } + break; + case DATABASE: + # Nothing to do with DB storage, but if we needed to update any meta data, we would remove the upper + # optimization, and then update here + break; + default: + trigger_error( ERROR_GENERIC, ERROR ); + } + } + } +} \ No newline at end of file -- 1.7.0.2.msysgit.0 bug_move.php (3,067 bytes)
/** * Move a bug from one project to another. Also move attachments * @param array p_bug_id integer representing bug id * @param int p_target_project_id */ function bug_move( $p_bug_id, $p_target_project_id ) { global $g_db; $t_mantis_bug_file_table = db_get_table( 'mantis_bug_file_table' ); $t_mantis_db = $g_db; $t_bug_id = db_prepare_int( $p_bug_id ); # retrieve the project id associated with the bug, if not found return if(( $p_target_project_id == null ) || is_blank( $p_target_project_id ) ) { return; } $t_target_project_id = db_prepare_int( $p_target_project_id ); # update project_id in the existing bug bug_set_field( $t_bug_id, 'project_id', $t_target_project_id ); helper_call_custom_function( 'issue_update_notify', array( $t_bug_id ) ); # Move attachments $query = 'SELECT * FROM ' . $t_mantis_bug_file_table . ' WHERE bug_id = ' . db_param(); $result = db_query_bound( $query, Array( $t_bug_id ) ); $t_count = db_num_rows( $result ); $t_bug_file = array(); for( $i = 0;$i < $t_count;$i++ ) { $t_bug_file = db_fetch_array( $result ); # prepare the new diskfile name and then copy the file $t_file_path = dirname( $t_bug_file['folder'] ); $t_new_diskfile_name = $t_file_path . file_generate_unique_name( 'bug-' . $t_bug_file['filename'], $t_file_path ); $t_new_file_name = file_get_display_name( $t_bug_file['filename'] ); if(( config_get( 'file_upload_method' ) == DISK ) ) { copy( $t_bug_file['diskfile'], $t_new_diskfile_name ); chmod( $t_new_diskfile_name, config_get( 'attachments_file_permissions' ) ); } $query = "INSERT INTO $t_mantis_bug_file_table ( bug_id, title, description, diskfile, filename, folder, filesize, file_type, date_added, content ) VALUES ( " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ", " . db_param() . ");"; db_query_bound( $query, Array( $t_bug_id, $t_bug_file['title'], $t_bug_file['description'], $t_new_diskfile_name, $t_new_file_name, $t_bug_file['folder'], $t_bug_file['filesize'], $t_bug_file['file_type'], $t_bug_file['date_added'], $t_bug_file['content'] ) ); # delete existing file & reference $old_file = $t_bug_file['diskfile']; // delete reference $query = "DELETE FROM $t_mantis_bug_file_table where diskfile='$old_file' "; db_query_bound($query); // delete physical file $t_method = config_get( 'file_upload_method' ); if(( DISK == $t_method ) || ( FTP == $t_method ) ) { if( FTP == $t_method ) { $ftp = file_ftp_connect(); } $t_local_diskfile = file_normalize_attachment_path( $t_bug_file['diskfile'] ); file_delete_local( $t_local_diskfile ); if( FTP == $t_method ) { file_ftp_delete( $ftp, $t_bug_file['diskfile'] ); } if( FTP == $t_method ) { file_ftp_disconnect( $ftp ); } } } return; } orphans.php (4,075 bytes)
<?php require_once( 'core.php' ); require_once( 'bug_api.php' ); require_once( 'file_api.php' ); /** * Returns a list of all possible bug ID's * @return array() of bug ID's */ function bug_get_bugs( ) { $t_project_id = helper_get_current_project(); $t_bug_table = db_get_table( 'mantis_bug_table' ); $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); if ( $t_project_id == ALL_PROJECTS) { $query = "SELECT bug_id FROM $t_bug_file_table"; $db_result = db_query( $query ); } else { $query = "SELECT distinct F.bug_id FROM $t_bug_file_table F, $t_bug_table B WHERE F.bug_id = B.ID AND B.project_id = " . db_param(); $db_result = db_query_bound( $query , Array( (int) $t_project_id) ); } $num_files = db_num_rows( $db_result ); $t_result = array(); for( $i = 0;$i < $num_files;$i++ ) { $t_result[] = db_fetch_array( $db_result ); } return $t_result; } function bug_get_attachments_withfolder( $p_bug_id ) { if( !file_can_view_bug_attachments( $p_bug_id ) ) { return; } $c_bug_id = db_prepare_int( $p_bug_id ); $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); $query = "SELECT id, title, diskfile, filename, filesize, file_type, date_added, folder FROM $t_bug_file_table WHERE bug_id=" . db_param() . " ORDER BY date_added"; $db_result = db_query_bound( $query, Array( $c_bug_id ) ); $num_files = db_num_rows( $db_result ); $t_result = array(); for( $i = 0;$i < $num_files;$i++ ) { $t_result[] = db_fetch_array( $db_result ); } return $t_result; } /** * Validate any attachments as needed when a bug is moved from project to project. * * @param int $p_bug_id ID of bug containing attachments to be verified * @return null */ function file_verify_bug_attachments( $p_bug_id ) { $t_project_id_from = bug_get_field( $p_bug_id, 'project_id' ); $t_method = config_get( 'file_upload_method' ); if ( $t_method != DISK ) { return; } if ( !file_bug_has_attachments( $p_bug_id ) ) { return; } $t_path_from = project_get_field( $t_project_id_from, 'file_path' ); if ( is_blank( $t_path_from ) ) { $t_path_from = config_get( 'absolute_path_default_upload_folder', null, null, $t_project_id_from ); } file_ensure_valid_upload_path( $t_path_from ); # Initialize the update query to update a single row $c_bug_id = db_prepare_int( $p_bug_id ); $t_attachment_rows = bug_get_attachments_withfolder( $p_bug_id ); $t_attachments_count = count( $t_attachment_rows ); for ( $i = 0; $i < $t_attachments_count; $i++ ) { $t_row = $t_attachment_rows[$i]; $t_basename = basename( $t_row['diskfile'] ); $t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename ); $t_disk_file_name_from_db = file_path_combine( $t_row['folder'], $t_basename ); if ( file_exists( $t_disk_file_name_from ) == false && file_exists( $t_disk_file_name_from_db ) == false) { $filename = $t_row['filename']; $folder = $t_row['folder']; //error_log("Bug: $c_bug_id, File: $t_disk_file_name_from, FileName: $filename, Folder: $folder is orphaned."); echo "<tr bgcolor='#c9ccc4'> <td>"; print_bug_link($c_bug_id); echo "</td><td>$t_disk_file_name_from</td><td>$filename</td><td>$folder</td></tr>"; } } } set_time_limit(60 * 2); $project_ids = bug_get_bugs(); $rowcount = count($project_ids); echo "<table class='width100' cellspacing='1'><tr><td class='form-title'>ID</td><td class='form-title'>File</td><td class='form-title'>FileName</td><td class='form-title'>folder</td></tr>"; for ( $i = 0; $i < $rowcount; $i++ ) { file_verify_bug_attachments( $project_ids[$i]['bug_id'] ); } echo "</table>"; ?> 0001-Patch-for-11687-off-of-the-1.2.4-tag-including-the-m.patch (10,503 bytes)
From d08dbe65f8566b5ef422c3a79bfe1f59564d3d66 Mon Sep 17 00:00:00 2001 From: Jacob Hoover <jacob.hoover@greenheck.com> Date: Tue, 12 Apr 2011 19:56:56 -0500 Subject: [PATCH] Patch for #11687 off of the 1.2.4 tag, including the mod to report orphans when looking at my_view_page. --- bug_actiongroup.php | 8 +++- core/file_api.php | 72 +++++++++++++++++++++++++ my_view_page.php | 1 + orphans.php | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+), 1 deletions(-) create mode 100644 orphans.php diff --git a/bug_actiongroup.php b/bug_actiongroup.php index 7d72793..3068082 100644 --- a/bug_actiongroup.php +++ b/bug_actiongroup.php @@ -28,6 +28,8 @@ require_once( 'bug_api.php' ); + require_once( 'file_api.php' ); + auth_ensure_user_authenticated(); helper_begin_long_process(); @@ -101,7 +103,11 @@ if ( access_has_bug_level( config_get( 'move_bug_threshold' ), $t_bug_id ) ) { /** @todo we need to issue a helper_call_custom_function( 'issue_update_validate', array( $t_bug_id, $t_bug_data, $f_bugnote_text ) ); */ $f_project_id = gpc_get_int( 'project_id' ); - bug_set_field( $t_bug_id, 'project_id', $f_project_id ); + + // Attempt to move disk based attachments to new project file directory. + file_move_bug_attachments( $t_bug_id, $f_project_id ); + + bug_set_field( $t_bug_id, 'project_id', $f_project_id ); helper_call_custom_function( 'issue_update_notify', array( $t_bug_id ) ); } else { $t_failed_ids[$t_bug_id] = lang_get( 'bug_actiongroup_access' ); diff --git a/core/file_api.php b/core/file_api.php index 3c61769..b7dddf9 100644 --- a/core/file_api.php +++ b/core/file_api.php @@ -853,3 +853,75 @@ function file_get_extension( $p_filename ) { } return $t_extension; } + +/** + * Move any attachments as needed when a bug is moved from project to project. + * + * @param int $p_bug_id ID of bug containing attachments to be moved + * @param int $p_project_id_to destination project ID for the bug + * @return null + */ +function file_move_bug_attachments( $p_bug_id, $p_project_id_to ) { + $t_project_id_from = bug_get_field( $p_bug_id, 'project_id' ); + if ( $t_project_id_from == $p_project_id_to ) { + return; + } + + $t_method = config_get( 'file_upload_method' ); + if ( $t_method != DISK ) { + return; + } + + if ( !file_bug_has_attachments( $p_bug_id ) ) { + return; + } + + $t_path_from = project_get_field( $t_project_id_from, 'file_path' ); + if ( is_blank( $t_path_from ) ) { + $t_path_from = config_get( 'absolute_path_default_upload_folder', null, null, $t_project_id_from ); + } + file_ensure_valid_upload_path( $t_path_from ); + $t_path_to = project_get_field( $p_project_id_to, 'file_path' ); + if ( is_blank( $t_path_to ) ) { + $t_path_to = config_get( 'absolute_path_default_upload_folder', null, null, $p_project_id_to ); + } + file_ensure_valid_upload_path( $t_path_to ); + if ( $t_path_from == $t_path_to ) { + return; + } + + # Initialize the update query to update a single row + $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); + $c_bug_id = db_prepare_int( $p_bug_id ); + $query_disk_attachment_update = "UPDATE $t_bug_file_table + SET folder=" . db_param() . " + WHERE bug_id=" . db_param() . " + AND id =" . db_param(); + + $t_attachment_rows = bug_get_attachments( $p_bug_id ); + $t_attachments_count = count( $t_attachment_rows ); + for ( $i = 0; $i < $t_attachments_count; $i++ ) { + $t_row = $t_attachment_rows[$i]; + $t_basename = basename( $t_row['diskfile'] ); + + $t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename ); + $t_disk_file_name_to = file_path_combine( $t_path_to, $t_basename ); + + if ( file_exists($t_disk_file_name_from) ) { + if ( !file_exists( $t_disk_file_name_to ) ) { + chmod( $t_disk_file_name_from, 0775 ); + if ( !rename( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + if ( !copy( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + trigger_error( FILE_MOVE_FAILED, ERROR ); + } + file_delete_local( $t_disk_file_name_from ); + } + chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) ); + db_query_bound( $query_disk_attachment_update, Array( db_prepare_string( $t_path_to ), $c_bug_id, db_prepare_int( $t_row['id'] ) ) ); + } else { + trigger_error( ERROR_FILE_DUPLICATE, ERROR ); + } + } + } +} + diff --git a/my_view_page.php b/my_view_page.php index d03764a..b315165 100644 --- a/my_view_page.php +++ b/my_view_page.php @@ -171,4 +171,5 @@ </div> <?php + require_once( 'orphans.php'); html_page_bottom(); diff --git a/orphans.php b/orphans.php new file mode 100644 index 0000000..a7810e2 --- /dev/null +++ b/orphans.php @@ -0,0 +1,144 @@ +<?php + require_once( 'core.php' ); + + require_once( 'bug_api.php' ); + + require_once( 'file_api.php' ); + +// require_once( 'last_visited_api.php' ); + +//global $g_session_validation; +//$g_session_validation = OFF; +//$tpl_file = __FILE__; +//$tpl_mantis_dir = dirname( __FILE__ ) . DIRECTORY_SEPARATOR; +//$tpl_show_page_header = true; +//$tpl_force_readonly = false; + + //auth_ensure_user_authenticated(); + +/** + * Returns a list of all possible bug ID's + * @return array() of bug ID's + */ +function bug_get_bugs( ) { + $t_project_id = helper_get_current_project(); + $t_bug_table = db_get_table( 'mantis_bug_table' ); + $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); + #$query = "SELECT id FROM $t_bug_table"; + #$query = "SELECT bug_id FROM $t_bug_file_table"; + + if ( $t_project_id == ALL_PROJECTS) { + $query = "SELECT bug_id FROM $t_bug_file_table"; + $db_result = db_query( $query ); + } else { + $query = "SELECT distinct F.bug_id FROM $t_bug_file_table F, $t_bug_table B WHERE F.bug_id = B.ID AND B.project_id = " . db_param(); + $db_result = db_query_bound( $query , Array( (int) $t_project_id) ); + } + # $query = "SELECT F.bug_id FROM $t_bug_file_table F, $t_bug_table B WHERE F.bug_id = B.ID AND B.project_id = " . db_param(); + #$db_result = db_query_bound( $query , Array( (int) $t_project_id) ); + $num_files = db_num_rows( $db_result ); + + $t_result = array(); + + for( $i = 0;$i < $num_files;$i++ ) { + $t_result[] = db_fetch_array( $db_result ); + } + + return $t_result; +} + +function bug_get_attachments_withfolder( $p_bug_id ) { + if( !file_can_view_bug_attachments( $p_bug_id ) ) { + return; + } + + $c_bug_id = db_prepare_int( $p_bug_id ); + + $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); + + $query = "SELECT id, title, diskfile, filename, filesize, file_type, date_added, folder + FROM $t_bug_file_table + WHERE bug_id=" . db_param() . " + ORDER BY date_added"; + $db_result = db_query_bound( $query, Array( $c_bug_id ) ); + $num_files = db_num_rows( $db_result ); + + $t_result = array(); + + for( $i = 0;$i < $num_files;$i++ ) { + $t_result[] = db_fetch_array( $db_result ); + } + + return $t_result; +} + +/** + * Validate any attachments as needed when a bug is moved from project +to project. + * + * @param int $p_bug_id ID of bug containing attachments to be verified + * @return null + */ +function file_verify_bug_attachments( $p_bug_id ) { + $t_project_id_from = bug_get_field( $p_bug_id, 'project_id' ); + $t_method = config_get( 'file_upload_method' ); + + if ( $t_method != DISK ) { + return; + } + + if ( !file_bug_has_attachments( $p_bug_id ) ) { + return; + } + + $t_path_from = project_get_field( $t_project_id_from, 'file_path' ); + + if ( is_blank( $t_path_from ) ) { + $t_path_from = config_get( 'absolute_path_default_upload_folder', null, null, $t_project_id_from ); + } + + file_ensure_valid_upload_path( $t_path_from ); + + # Initialize the update query to update a single row + #$t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); + $c_bug_id = db_prepare_int( $p_bug_id ); + #$query_disk_attachment_update = "UPDATE $t_bug_file_table + # SET folder=" . db_param() . " + # WHERE bug_id=" . db_param() . " + # AND id =" . db_param(); + + $t_attachment_rows = bug_get_attachments_withfolder( $p_bug_id ); + $t_attachments_count = count( $t_attachment_rows ); + for ( $i = 0; $i < $t_attachments_count; $i++ ) { + $t_row = $t_attachment_rows[$i]; + $t_basename = basename( $t_row['diskfile'] ); + + $t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename ); + $t_disk_file_name_from_db = file_path_combine( $t_row['folder'], $t_basename ); + + if ( file_exists( $t_disk_file_name_from ) == false && file_exists( $t_disk_file_name_from_db ) == false) + { + $filename = $t_row['filename']; + $folder = $t_row['folder']; + //error_log("Bug: $c_bug_id, File: $t_disk_file_name_from, FileName: $filename, Folder: $folder is orphaned."); + echo "<tr bgcolor='#c9ccc4'> <td>"; + print_bug_link($c_bug_id); + echo "</td><td>$t_disk_file_name_from</td><td>$filename</td><td>$folder</td></tr>"; + } + } +} + +set_time_limit(60 * 2); +//error_log('calling bug_get_bugs'); +$project_ids = bug_get_bugs(); +$rowcount = count($project_ids); +//error_log("Found $rowcount bugs"); +echo "<table class='width100' cellspacing='1'><tr><td class='form-title'>ID</td><td class='form-title'>File</td><td class='form-title'>FileName</td><td class='form-title'>folder</td></tr>"; +for ( $i = 0; $i < $rowcount; $i++ ) { + file_verify_bug_attachments( $project_ids[$i]['bug_id'] ); + //if ($i % 1000 == 0) { + //error_log("Processing $i of $rowcount"); + //} +} +echo "</table>"; +?> -- 1.7.0.2.msysgit.0 fix-11687-1.2.9.patch (3,793 bytes)
diff --git a/core/bug_api.php b/core/bug_api.php index e43bc05..eaf24a6 100644 --- a/core/bug_api.php +++ b/core/bug_api.php @@ -1075,13 +1075,16 @@ function bug_copy( $p_bug_id, $p_target_project_id = null, $p_copy_custom_fields /** * Moves an issue from a project to another. + * * @todo Validate with sub-project / category inheritance scenarios. - * @todo Fix #11687: Bugs with attachments that are moved will lose attachments. * @param int p_bug_id The bug to be moved. * @param int p_target_project_id The target project to move the bug to. * @access public */ function bug_move( $p_bug_id, $p_target_project_id ) { + // Attempt to move disk based attachments to new project file directory. + file_move_bug_attachments( $p_bug_id, $p_target_project_id ); + // Move the issue to the new project. bug_set_field( $p_bug_id, 'project_id', $p_target_project_id ); diff --git a/core/file_api.php b/core/file_api.php index 1fc416f..10fd088 100644 --- a/core/file_api.php +++ b/core/file_api.php @@ -909,3 +909,72 @@ function file_get_content_type_override( $p_filename ) { return $g_file_download_content_type_overrides[$t_extension]; } + +/** + * Move any attachments as needed when a bug is moved from project to project. + * + * @param int $p_bug_id ID of bug containing attachments to be moved + * @param int $p_project_id_to destination project ID for the bug + * @return null + */ +function file_move_bug_attachments( $p_bug_id, $p_project_id_to ) { + $t_project_id_from = bug_get_field( $p_bug_id, 'project_id' ); + if ( $t_project_id_from == $p_project_id_to ) { + return; + } + + $t_method = config_get( 'file_upload_method' ); + if ( $t_method != DISK ) { + return; + } + + if ( !file_bug_has_attachments( $p_bug_id ) ) { + return; + } + + $t_path_from = project_get_field( $t_project_id_from, 'file_path' ); + if ( is_blank( $t_path_from ) ) { + $t_path_from = config_get( 'absolute_path_default_upload_folder', null, null, $t_project_id_from ); + } + file_ensure_valid_upload_path( $t_path_from ); + $t_path_to = project_get_field( $p_project_id_to, 'file_path' ); + if ( is_blank( $t_path_to ) ) { + $t_path_to = config_get( 'absolute_path_default_upload_folder', null, null, $p_project_id_to ); + } + file_ensure_valid_upload_path( $t_path_to ); + if ( $t_path_from == $t_path_to ) { + return; + } + + # Initialize the update query to update a single row + $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); + $c_bug_id = db_prepare_int( $p_bug_id ); + $query_disk_attachment_update = "UPDATE $t_bug_file_table + SET folder=" . db_param() . " + WHERE bug_id=" . db_param() . " + AND id =" . db_param(); + + $t_attachment_rows = bug_get_attachments( $p_bug_id ); + $t_attachments_count = count( $t_attachment_rows ); + for ( $i = 0; $i < $t_attachments_count; $i++ ) { + $t_row = $t_attachment_rows[$i]; + $t_basename = basename( $t_row['diskfile'] ); + + $t_disk_file_name_from = file_path_combine( $t_path_from, $t_basename ); + $t_disk_file_name_to = file_path_combine( $t_path_to, $t_basename ); + + if ( !file_exists( $t_disk_file_name_to ) ) { + chmod( $t_disk_file_name_from, 0775 ); + if ( !rename( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + if ( !copy( $t_disk_file_name_from, $t_disk_file_name_to ) ) { + trigger_error( FILE_MOVE_FAILED, ERROR ); + } + file_delete_local( $t_disk_file_name_from ); + } + chmod( $t_disk_file_name_to, config_get( 'attachments_file_permissions' ) ); + db_query_bound( $query_disk_attachment_update, Array( db_prepare_string( $t_path_to ), $c_bug_id, db_prepare_int( $t_row['id'] ) ) ); + } else { + trigger_error( ERROR_FILE_DUPLICATE, ERROR ); + } + } +} | ||||
related to | 0015721 | closed | grangeway | Functionality to consider porting to master-2.0.x |
has duplicate | 0012188 | closed | atrol | attachments marked as missing in "view issue" after moving issue from one project to another with different upload file path |
has duplicate | 0012310 | closed | atrol | Attachements are missing when a issue is moved from a domain to anotherone. |
has duplicate | 0014355 | closed | atrol | When moving an issue to another project, attachments where missing/not moved |
related to | 0014796 | closed | atrol | "Attachment missing" while re-copying an issue. |
My suggestion would be either to I would prefer A just so we could maintain "pure" directory tree's. |
|
Reproduced in a clean installation |
|
I've been looking for documentation on what the intent was, but I am not seeing much of anything. Would you agree that it would make the most sense to move disk based attachments of a bug when the bug is moved between projects? Also, I have yet to get my test VM fully setup, but there was an additional field in the DB storing the absolute path to the folder which contains the attachment. Since it didn't seem like this value was used, is this information only for debugging or is it leftovers from a previous version? (If we do end up moving the files, this path should also be updated.) |
|
I've attached a potential fix to the issue. Adding the 2 functions in the text file to file_api.php, and then tweaking bug_actiongroup.php to A) require file_api.php with $t_origional_bug_project = bug_get_field( $t_bug_id, 'project_id' ); |
|
I'm close on the proper formatting and notation, but I wouldn't doubt it if I mucked something up. If one of the existing developers would like to take a look at it and let me know how far off base I am, I'd be up for the comments and critiques. |
|
Thanks for your help jchoover! Just some comments on your patch: No need to check against true (== true)... just leave out the right hand side off those boolean comparisons. I'm not convinced about the need for file_move_bug_attachment() - I think it may be best to just have a single file_move_bug_attachments() function that works with one, ten or more attachments at a time. The SQL query would be better located outside the for loop so that we only need one query for multiple files instead of one query for each file. The approach to moving files with hard links seems a little odd to me. Is there any reason this can't be simplified with a platform-independent call to the PHP rename() function? I understand that rename() will overwrite an existing destination file... is this a situation we have to consider? With a few minor adjustments, are you able to resubmit a patch as outputted from git format-patch? In this form we can commit it directly with credit going to yourself (if you don't want credit, that is fine too). I'm impressed with what you've been able to code here... it follows the MantisBT coding conventions and uses the inbuilt functions correctly. Well done! |
|
My only reasoning around file_move_bug_attachment() was to wrap the file system operations and be entirely certain that the moves are happening properly. The hard links approach was just something that felt cleaner at the time. (Ensuring I could create the file and set the perms before removing the old one.) Hind sight tells me I was probably over thinking the situation, but I did see reports where Windows machines that rename didn't always work as expected (which was the reason for the inner copy). As far as destination file check, I do ensure the destination file exists before trying the rename and I trigger an error if one all ready exists. This is partially why I wanted the SQL update inside the loop, though the initialization of the SQL statement could happen outside the loop and just leave the execution call in the loop. I was trying to cover for a fringe case where a bug with 10 attachments is moved, and the first 5 succeed but the 6th fails due to a duplicate destination name. At first, I had thought we could generate a new hashed file name and update the database accordingly but looking at how the current file names were generated made me wonder if you were embedding some sort of logic inside the name. I did download/build/install git, but I have never used the tool before so it may take a bit of futzing to get to a state where I can use it effectively. As well, if I am submitting a git patch, which branch should the patch be targeted for? |
|
some information about contributing patches |
|
One other thing that was of concern is the fact that my solution doesn't make a single atomic transaction, so the existing bug's project is updated first and then I was moving any disk based attachments. If any part of the moves fail, the bug is left in a partially moved state. |
|
Let's see if that patch file is even remotely correct. Note, I created this based off of the previous suggestions but didn't fire up my Linux VM to test. As such, I am using TortiseGit instead of the command line tools. I'm now going to fire up the linux box and attempt to apply the patch I created in windows land to the 1.2.0 base and see what happens. |
|
I have tested my patch locally and everything appears to function. Has any other developer looked at this, and what are the odds of getting this merged into the current development branch? Has anyone else who is experiencing this issue tried my patch? |
|
Our recently installed version (1.2.1) has this problem, but it appears this patch has been written against the changes made in January, so that it uses versions of bug_actiongroup.php that refers to require_api rather than require_once? As a relative neophyte, how might I use this logic to patch the existing 1.2.1? Or am I missing something more basic? |
|
I did a quick scan and saw that they had cleaned up the require_api calls. Noting the require call they changed it to will include the file_api I was patching in, so that part can be ignored. I did a fast hack and regenerated a 1.2.1 patch by simply replaying my changes (after checking out the 1.2.1 tag). Note I didn't have time to test it, but odds are it should function as expected. As far as how to apply the patch, these are generated by git and are easily applied by git. If you don't want to get git, checkout, and then patch you could manually apply the changes in a test environment. Note, I didn't change any existing lines, but rather added 2 lines in bug_actiongroup and 79 in file_api. |
|
I was pretty sure that was the case (file_api being already included) but still was having some troubles with it. I've got it going good, but had to make a more explicit reference to the table. Line 42 of your latest patch file has: $t_bug_file_table = db_get_table( 'bug_file' ); I had to make that: $t_bug_file_table = db_get_table( 'mantis_bug_file_table' ); Not sure if that is significant to others, but I saw other places in file_api where it was referred to that way, so have (at least in the short term) made the change with no apparent bad results for me anyway. Thank you so very much for your work on this - I had told our developers that moving the attachments out of the database should not impact badly on them - so to get this fixed has been a real priority for me these last few days! |
|
I talked to DHX some and it was stated that this fix was in queue, but I see the target has been changed from 1.2.3 to 1.2.x. Do we have an expected target? |
|
Found my solution on this issue wheer i just added a function to bug_api called bug_move. This function could be simply called directly with 2 parameters. |
|
Apologies for the delay in committing this fix. Thank you Jacob for the patch. I have updated the patch to work with the latest version of MantisBT 1.3.x and have also simplified and cleaned up the new function. Note the use of "guard conditions" on the function instead of massively nested if clauses. I have not properly tested this updated commit and would appreciate it if some people are able to test this and confirm whether things are working as expected. Thanks again for your help :) |
|
Not sure if this is the proper procedure or not, but I had a comment on the commit. Specifically, if there are "disconnected" attachements in an existing instance would we not want to make this code safe to be able to fix them by moving the bug to it's origional project and back again? If so, I think it would be a simple change to the file_api fix. I simply added if ( file_exists($t_disk_file_name_from) ) inside the loop that moves the files. Comments?
|
|
Also, for those wondering how to find borked attachments I have attached my hackish orphans.php. I wrote it against 1.2.4, and I hacked it by adding it to the end of my_view_page.php, via adding require_once( 'orphans.php'); right before html_page_bottom(); |
|
This bug will be "officially" resolved in the 1.2.х branch? I have not found any information in the changelog of 1.2.5 and 1.2.6 (now we use 1.2.4) |
|
Libra, atm the issue has set "Target Version" to 1.3.x and also "Fixed in Version" to 1.3.x |
|
I understand as for version 1.3.x, but there is a bug in 1.2.4 and this bug is very serious hindrance to the work (we have about 20 projects) and we do not want to install 1.3.х version on a production server. Is it possible to fix this problem in 1.2.х? |
|
You can apply the patch for 1.2.4 that jchoover attached to this issue. |
|
If you would prefer the raw files over a patch, let me know and I can provide the patched file_api.php and bug_actiongroup.php that we use on our production instance. My comment (http://www.mantisbt.org/bugs/view.php?id=11687#c28607) was in regards to trying to make this safe to fix broken attachments. If you aren't in a broken state it would make more sense to use dhx's commit rather than my tweaks. My files were changed to allow for our project managers to be able to "fix" borked attachments by pushing them back to the original project(s) and then back to where they should be. The process of moving them around should find the missing files, assuming you haven't changed the storage location of the projects. |
|
atrol and jchoover, thanks for your support! For jchoover - please provide patched files, thanks in advance! |
|
The fixforattachements.tgz is based off of the 1.2.4 code base with the fix implemented in it. As always, make sure you have a backup of the files and data before applying the fix. I would also store a backup copy of the 2 files in case you needed to revert the changes. |
|
jchoover, thanks for patсh - everything works as expected! I upgraded to 1.2.6 and created a patch for it (a bit different from 1.2.4), see Patch-for-11687-1.2.6.zip |
|
I recently upgraded from 1.1.x to 1.2.8 and I see that 'Patch-for-11687-1.2.6.zip' is meant to work for 1.2.6. Can you tell me if it also work for 1.2.8? Thanks in advance. |
|
Unfortunately, can not say anything about version 1.2.8, has not been updated since version 1.2.6 |
|
Thanks for the update. I'll keep checking here to see if someone patches 1.2.8, otherwise will update to 1.3.x when available/stable. |
|
Can anybody confirm that this issues has been fixed in 1.2.9? I'd rather just go from 1.2.8 to 1.2.9 instead of waiting for 1.3.X since this issue still exists for us. Thanks, |
|
It is not fixed in 1.2.9. However, I just checked and dhx's commit for 1.3.x applies cleanly on 1.2.x branch, so it would be easy to back-port it. I uploaded a patch file (fix-11687.patch), which should apply fine on release 1.2.9 and above. If you can spare the time to test and confirm that everything works as it should, I can push the changes to the 1.2.x. |
|
Thanks dregad, you're giving me more credit than I've earned. I have no idea how to apply that patch so I googled some possibilities but ended up just messing up a couple of my files on my test box. The original is working again, but I'll have to spend some more time figuring this out. If there's something you can point me to, to read up on, I'd be happy to learn what I need to otherwise, I'll keep plugging away as time permits. Thanks for the attempt at helping out. |
|
Sorry about that. To apply the patch, assuming you're on linux, the following should do the trick cd /path/to/mantisbt On windows, if you have cygwin the commands above should work too. Otherwise you need to use some utility, e.g. see http://stackoverflow.com/questions/517257/how-do-i-apply-a-diff-patch-on-windows |
|
Thanks for that, I am on linux (Ubuntu). I hadn't yet upgraded to 1.2.9 so I'm still on 1.2.8 and tried the patch and got an error... patching file core/bug_api.php
|
|
Wrong interpretation ;-) - read again:
So you should either upgrade your test env, or try and figure out what the conflict is with 1.2.8 (no time to check myself, sorry) |
|
Gotcha, no worries, I appreciate the help. I don't think I can get to this today, but I'll try the upgrade route and try the patch with that version. |
|
I upgraded to 1.2.9 and installed the patch. I think that part went well, here's what it spit out... patching file core/bug_api.php
|
|
I overlooked the fact that in 1.3 branch, the referencing of DB tables in the code is not the same as for 1.2 - this is probably what is causing the error you get (although I was not able to reproduce it). I'm uploading a new patch (which should be applied on top of unmodified 1.2.9) - alternatively you can manually edit core/file_api.php as follows (your line numbers could be different)
|
|
Thanks, give me a day or two and I'll try this again with a unmodified install of 1.2.9 since I'll be using the patch to update my live site. |
|
OK. Looking forward to your feedback. As a side note, if you're going to upgrade your production site, I would advise you to go for 1.2.11 instead of 1.2.9 (the provided patch applies cleanly on top of that too) to benefit from several security and bug fixes |
|
I didn't realize 1.2.11 was out, so thanks for the info. I upgraded from 1.2.8 to 1.2.11, applied the patch and I'm able to transfer attachments along with the tickets now. It works like a champ, thanks! |
|
Thanks to jthomas' testing efforts, the patch has now been ported to 1.2.x branch so I'm marking this as resolved. |
|
FILE_MOVE_FAILED is not defined, should be ERROR_FILE_MOVE_FAILED |
|
Thanks for checking Roland, I'll fix that shortly |
|
Thanks for the patch, worked perfectly on a long-time running 1.2.10. I'm going to write a script shortly that will find all missing attachments, look within the Mantis installation folder for them, and if found move them to the correct folder for the project. Once it's done I'll share :) |
|
Marking as 'acknowledged' not resolved/closed to track that change gets ported to master-2.0.x branch |
|
MantisBT: master 08c027af 2011-02-26 05:03 Jacob Hoover Committer: dhx Details Diff |
Fix 0011687: Bugs with attachments that are moved will lose attachments When a bug is logged and assigned to a project which has a project path assigned, and later a mantis "administrator" moves the bug from the initial project to a new project, the attachments are lost. Jacob's initial patch from mid 2010 has been updated to work with the latest version of MantisBT 1.3.x. Furthermore the patch has been cleaned up and simplified. Needs testing however! Signed-off-by: David Hicks <hickseydr@optusnet.com.au> |
Affected Issues 0011687 |
|
mod - core/bug_api.php | Diff File | ||
mod - core/file_api.php | Diff File | ||
MantisBT: master-1.2.x cdf383bd 2012-06-27 12:22 Details Diff |
Fix 0011687: Bugs with attachments that are moved will lose attachments Backporting 08c027af59b88a6934377d71d19a86edfd7d12dd to 1.2.x branch. When a bug is logged and assigned to a project which has a project path assigned, and later a mantis "administrator" moves the bug from the initial project to a new project, the attachments are lost. Signed-off-by: Damien Regad <damien.regad@merckgroup.com> |
Affected Issues 0011687 |
|
mod - core/bug_api.php | Diff File | ||
mod - core/file_api.php | Diff File | ||
MantisBT: master-1.2.x 4a6c8456 2012-06-28 01:35 Details Diff |
Fix 0011687: use of incorrect error constant |
Affected Issues 0011687 |
|
mod - core/file_api.php | Diff File | ||
MantisBT: master 21e1a24b 2012-06-28 01:35 Details Diff |
Fix 0011687: use of incorrect error constant |
Affected Issues 0011687 |
|
mod - core/file_api.php | Diff File |