// Note attachments are currently saved into the authors file directory private void SaveAttachments(int contentId) { var fileManager = FileManager.Instance; var folderManager = FolderManager.Instance; var adb = new Data.AttachController(); var userFolder = folderManager.GetUserFolder(UserInfo); const string uploadFolderName = "activeforums_Upload"; const string attachmentFolderName = "activeforums_Attach"; const string fileNameTemplate = "__{0}__{1}__{2}"; var attachmentFolder = folderManager.GetFolder(PortalId, attachmentFolderName) ?? folderManager.AddFolder(PortalId, attachmentFolderName); // Read the attachment list sent in the hidden field as json var attachmentsJson = hidAttachments.Value; var serializer = new DataContractJsonSerializer(typeof (List<ClientAttachment>)); var ms = new MemoryStream(Encoding.UTF8.GetBytes(attachmentsJson)); var attachmentsNew = (List<ClientAttachment>)serializer.ReadObject(ms); ms.Close(); // Read the list of existing attachments for the content. Must do this before saving any of the new attachments! // Ignore any legacy inline attachments var attachmentsOld = adb.ListForContent(contentId).Where(o => !o.AllowDownload.HasValue || o.AllowDownload.Value); // Save all of the new attachments foreach(var attachment in attachmentsNew) { // Don't need to do anything with existing attachments if(attachment.AttachmentId.HasValue && attachment.AttachmentId.Value > 0) continue; IFileInfo file = null; var fileId = attachment.FileId.GetValueOrDefault(); if(fileId > 0 && userFolder != null) { // Make sure that the file exists and it actually belongs to the user who is trying to attach it file = fileManager.GetFile(fileId); if(file == null || file.FolderId != userFolder.FolderID) continue; } else if(!string.IsNullOrWhiteSpace(attachment.UploadId) && !string.IsNullOrWhiteSpace(attachment.FileName)) { if (!Regex.IsMatch(attachment.UploadId, @"^[\w\-. ]+$")) // Check for shenanigans. continue; var uploadFilePath = PathUtils.Instance.GetPhysicalPath(PortalId, uploadFolderName + "/" + attachment.UploadId); if (!File.Exists(uploadFilePath)) continue; // Store the files with a filename format that prevents overwrites. var index = 0; var fileName = string.Format(fileNameTemplate, contentId, index, Regex.Replace(attachment.FileName, @"[^\w\-. ]+", string.Empty)); while(fileManager.FileExists(attachmentFolder, fileName)) { index++; fileName = string.Format(fileNameTemplate, contentId, index, Regex.Replace(attachment.FileName, @"[^\w\-. ]+", string.Empty)); } // Copy the file into the attachment folder with the correct name. using (var fileStream = new FileStream(uploadFilePath, FileMode.Open, FileAccess.Read)) { file = fileManager.AddFile(attachmentFolder, fileName, fileStream); } File.Delete(uploadFilePath); } if(file == null) continue; adb.Save(contentId, UserId, file.FileName, file.ContentType, file.Size, file.FileId); } // Remove any attachments that are no longer in the list of attachments var attachmentsToRemove = attachmentsOld.Where(a1 => attachmentsNew.All(a2 => a2.AttachmentId != a1.AttachmentId)); foreach(var attachment in attachmentsToRemove) { adb.Delete(attachment.AttachmentId); var file = attachment.FileId.HasValue ? fileManager.GetFile(attachment.FileId.Value) : fileManager.GetFile(attachmentFolder, attachment.FileName); // Only delete the file if it exists in the attachment folder if(file != null && file.FolderId == attachmentFolder.FolderID) fileManager.DeleteFile(file); } }
private void PrepareAttachments(int? contentId = null) { // Handle the case where we don't yet have a topic id (new posts) if(!contentId.HasValue || contentId.Value <= 0) { hidAttachments.Value = "[]"; // JSON for an empty array return; } var adb = new Data.AttachController(); var attachments = adb.ListForContent(contentId.Value); var clientAttachments = attachments.Select(attachment => new ClientAttachment { AttachmentId = attachment.AttachmentId, ContentType = attachment.ContentType, FileId = attachment.FileId, FileName = Regex.Replace(attachment.FileName.TextOrEmpty(), @"^__\d+__\d+__", string.Empty), // Remove our unique file prefix before sending to the client. FileSize = attachment.FileSize }).ToList(); var serializer = new DataContractJsonSerializer(typeof(List<ClientAttachment>)); using(var ms = new MemoryStream()) { serializer.WriteObject(ms, clientAttachments); ms.Seek(0, 0); using(var sr = new StreamReader(ms, Encoding.UTF8)) { hidAttachments.Value = sr.ReadToEnd(); } } }