/////////////////////////////////////////////////////////////////////// private static int insert_post_attachment_impl( btnet.Security security, int bugid, Stream content, int content_length, int copy_bpid, string file, string comment, string content_type, int parent, bool hidden_from_external_users, bool send_notifications) { // Note that this method does not perform any security check nor does // it check that content_length is less than MaxUploadSize. // These are left up to the caller. string upload_folder = Util.get_upload_folder(); string sql; bool store_attachments_in_database = (Util.get_setting("StoreAttachmentsInDatabase", "0") == "1"); string effective_file = file; int effective_content_length = content_length; string effective_content_type = content_type; Stream effective_content = null; try { // Determine the content. We may be instructed to copy an existing // attachment via copy_bpid, or a Stream may be provided as the content parameter. if (copy_bpid != -1) { BugPostAttachment bpa = get_bug_post_attachment(copy_bpid); effective_content = bpa.content; effective_file = bpa.file; effective_content_length = bpa.content_length; effective_content_type = bpa.content_type; } else { effective_content = content; effective_file = file; effective_content_length = content_length; effective_content_type = content_type; } // Insert a new post into bug_posts. sql = @" declare @now datetime set @now = getdate() update bugs set bg_last_updated_date = @now, bg_last_updated_user = $us where bg_id = $bg insert into bug_posts (bp_type, bp_bug, bp_file, bp_comment, bp_size, bp_date, bp_user, bp_content_type, bp_parent, bp_hidden_from_external_users) values ('file', $bg, N'$fi', N'$de', $si, @now, $us, N'$ct', $pa, $internal) select scope_identity()"; sql = sql.Replace("$bg", Convert.ToString(bugid)); sql = sql.Replace("$fi", effective_file.Replace("'", "''")); sql = sql.Replace("$de", comment.Replace("'", "''")); sql = sql.Replace("$si", Convert.ToString(effective_content_length)); sql = sql.Replace("$us", Convert.ToString(security.user.usid)); // Sometimes, somehow, content type is null. Not sure how. sql = sql.Replace("$ct", effective_content_type != null ? effective_content_type.Replace("'", "''") : string.Empty); if (parent == -1) { sql = sql.Replace("$pa", "null"); } else { sql = sql.Replace("$pa", Convert.ToString(parent)); } sql = sql.Replace("$internal", btnet.Util.bool_to_string(hidden_from_external_users)); int bp_id = Convert.ToInt32(btnet.DbUtil.execute_scalar(sql)); try { // Store attachment in bug_post_attachments table. if (store_attachments_in_database) { byte[] data = new byte[effective_content_length]; int bytes_read = 0; while (bytes_read < effective_content_length) { int bytes_read_this_iteration = effective_content.Read(data, bytes_read, effective_content_length - bytes_read); if (bytes_read_this_iteration == 0) { throw new Exception("Unexpectedly reached the end of the stream before all data was read."); } bytes_read += bytes_read_this_iteration; } sql = @"insert into bug_post_attachments (bpa_post, bpa_content) values (@bp, @bc)"; using (SqlCommand cmd = new SqlCommand(sql)) { cmd.Parameters.AddWithValue("@bp", bp_id); cmd.Parameters.Add("@bc", SqlDbType.Image).Value = data; btnet.DbUtil.execute_nonquery(cmd); } } else { // Store attachment in UploadFolder. if (upload_folder == null) { throw new Exception("StoreAttachmentsInDatabase is false and UploadFolder is not set in web.config."); } // Copy the content Stream to a file in the upload_folder. byte[] buffer = new byte[16384]; int bytes_read = 0; using (FileStream fs = new FileStream(upload_folder + "\\" + bugid + "_" + bp_id + "_" + effective_file, FileMode.CreateNew, FileAccess.Write)) { while (bytes_read < effective_content_length) { int bytes_read_this_iteration = effective_content.Read(buffer, 0, buffer.Length); if (bytes_read_this_iteration == 0) { throw new Exception("Unexpectedly reached the end of the stream before all data was read."); } fs.Write(buffer, 0, bytes_read_this_iteration); bytes_read += bytes_read_this_iteration; } } } } catch { // clean up sql = @"delete from bug_posts where bp_id = $bp"; sql = sql.Replace("$bp", Convert.ToString(bp_id)); btnet.DbUtil.execute_nonquery(sql); throw; } if (send_notifications) { btnet.Bug.send_notifications(btnet.Bug.UPDATE, bugid, security); } return bp_id; } finally { // If this procedure "owns" the content (instead of our caller owning it), dispose it. if (effective_content != null && effective_content != content) { effective_content.Dispose(); } } }
/////////////////////////////////////////////////////////////////////// public static int insert_post_attachment_copy( btnet.Security security, int bugid, int copy_bpid, string comment, int parent, bool hidden_from_external_users, bool send_notifications) { return insert_post_attachment_impl( security, bugid, null, -1, copy_bpid, null, comment, null, parent, hidden_from_external_users, send_notifications); }
/////////////////////////////////////////////////////////////////////// public static int insert_post_attachment( btnet.Security security, int bugid, Stream content, int content_length, string file, string comment, string content_type, int parent, bool hidden_from_external_users, bool send_notifications) { return insert_post_attachment_impl( security, bugid, content, content_length, -1, // copy_bpid file, comment, content_type, parent, hidden_from_external_users, send_notifications); }
/////////////////////////////////////////////////////////////////////// public static int write_posts( DataSet ds_posts, HttpResponse Response, int bugid, int permission_level, bool write_links, bool images_inline, bool history_inline, bool internal_posts, btnet.User user) { if (Util.get_setting("ForceBordersInEmails","0") == "1") { Response.Write ("\n<table id='posts_table' border=1 cellpadding=0 cellspacing=3>"); } else { Response.Write ("\n<table id='posts_table' border=0 cellpadding=0 cellspacing=3>"); } int post_cnt = ds_posts.Tables[0].Rows.Count; int bp_id; int prev_bp_id = -1; foreach (DataRow dr in ds_posts.Tables[0].Rows) { if (!internal_posts) { if ((int)dr["bp_hidden_from_external_users"] == 1) { continue; } } bp_id = (int) dr["bp_id"]; if ((string)dr["bp_type"] == "update") { string comment = (string) dr["bp_comment"]; if (user.tags_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed tags from")) continue; if (user.project_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed project from")) continue; if (user.org_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed organization from")) continue; if (user.category_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed category from")) continue; if (user.priority_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed priority from")) continue; if (user.assigned_to_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed assigned_to from")) continue; if (user.status_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed status from")) continue; if (user.udf_field_permission_level == Security.PERMISSION_NONE && comment.StartsWith("changed " + Util.get_setting("UserDefinedBugAttributeName","YOUR ATTRIBUTE") + " from")) continue; bool bSkip = false; foreach (string key in user.dict_custom_field_permission_level.Keys) { int field_permission_level = user.dict_custom_field_permission_level[key]; if (field_permission_level == Security.PERMISSION_NONE) { if (comment.StartsWith("changed " + key + " from")) { bSkip = true; } } } if (bSkip) { continue; } } if (bp_id == prev_bp_id) { // show another attachment write_email_attachment(Response, bugid, dr, write_links, images_inline); } else { // show the comment and maybe an attachment if (prev_bp_id != -1) { Response.Write ("\n</table>"); // end the previous table } write_post(Response, bugid, permission_level, dr, bp_id, write_links, images_inline, user.is_admin, user.can_edit_and_delete_posts, user.external_user); if (Convert.ToString(dr["ba_file"]) != "") // intentially "ba" { write_email_attachment(Response, bugid, dr, write_links, images_inline); } prev_bp_id = bp_id; } } if (prev_bp_id != -1) { Response.Write ("\n</table>"); // end the previous table } Response.Write ("\n</table>"); return post_cnt; }