/////////////////////////////////////////////////////////////////////// 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 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)); }
/////////////////////////////////////////////////////////////////////// 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(); } } }