public virtual ResourceBE Delete(ResourceBE resource, PageBE parentPage, uint changeSetId) { //Build the new revision ResourceBE res = BuildRevForRemove(resource, DateTime.UtcNow, changeSetId); //Update db res = SaveResource(res); //Update indexes and parent page's timestamp //TODO MaxM: Changesink needs to accept a resource if (res.ResourceType == ResourceBE.Type.FILE) { DekiContext.Current.Instance.EventSink.AttachmentDelete(DekiContext.Current.Now, res, DekiContext.Current.User); // Recent changes RecentChangeBL.AddFileRecentChange(DekiContext.Current.Now, parentPage, DekiContext.Current.User, DekiResources.FILE_REMOVED(res.Name), changeSetId); } if (parentPage != null) { PageBL.Touch(parentPage, DateTime.UtcNow); } return(res); }
public void RestoreAttachment(ResourceBE attachmentToRestore, PageBE toPage, DateTime timestamp, uint transactionId) { if (toPage == null || toPage.ID == 0) { ArchiveBE archivesMatchingPageId = _session.Archive_GetPageHeadById(attachmentToRestore.ParentPageId.Value); if (archivesMatchingPageId == null) { throw new AttachmentRestoreFailedNoParentFatalException(); } else { toPage = PageBL.GetPageByTitle(archivesMatchingPageId.Title); if (0 == toPage.ID) { PageBL.Save(toPage, _resources.Localize(DekiResources.RESTORE_ATTACHMENT_NEW_PAGE_TEXT()), DekiMimeType.DEKI_TEXT, null); } } } string filename = attachmentToRestore.Name; //Check for name conflicts on target page ResourceBE conflictingFile = GetPageAttachment(toPage.ID, filename); if (conflictingFile != null) { //rename the restored file filename = string.Format("{0}(restored {1}){2}", attachmentToRestore.FilenameWithoutExtension, DateTime.Now.ToString("g"), string.IsNullOrEmpty(attachmentToRestore.FilenameExtension) ? string.Empty : "." + attachmentToRestore.FilenameExtension); conflictingFile = GetPageAttachment(toPage.ID, filename); if (conflictingFile != null) { throw new AttachmentRestoreNameConflictException(); } } //Build new revision for restored file attachmentToRestore = BuildRevForRestore(attachmentToRestore, toPage, filename, transactionId); //Insert new revision into DB attachmentToRestore = SaveResource(attachmentToRestore); //Recent Changes RecentChangeBL.AddFileRecentChange(_dekiContext.Now, toPage, _dekiContext.User, DekiResources.FILE_RESTORED(attachmentToRestore.Name), transactionId); _dekiContext.Instance.EventSink.AttachmentRestore(_dekiContext.Now, attachmentToRestore, _dekiContext.User); }
/// <summary> /// Move this attachment to the target page. /// </summary> /// <remarks> /// This will fail if destination page has a file with the same name. /// </remarks> /// <param name="sourcePage">Current file location</param> /// <param name="targetPage">Target file location. May be same as sourcepage for rename</param> /// <param name="name">New filename or null for no change</param> /// <returns></returns> public ResourceBE MoveAttachment(ResourceBE attachment, PageBE sourcePage, PageBE targetPage, string name, bool loggingEnabled) { //TODO MaxM: Connect with a changeset uint changeSetId = 0; attachment.AssertHeadRevision(); bool move = targetPage != null && targetPage.ID != sourcePage.ID; bool rename = name != null && !name.EqualsInvariant(attachment.Name); //Just return the current revision if no change is being made if (!move && !rename) { return(attachment); } //validate filename if (rename) { name = ValidateFileName(name); } //Check the resource exists on the target (may be same as source page) with new name (if given) or current name ResourceBE existingAttachment = GetPageAttachment((targetPage ?? sourcePage).ID, name ?? attachment.Name); if (existingAttachment != null) { throw new AttachmentExistsOnPageConflictException(name ?? attachment.Name, (targetPage ?? sourcePage).Title.AsUserFriendlyName()); } //Performing a move? if (move) { _dekiContext.Instance.Storage.MoveFile(attachment, targetPage); //Perform the IStorage move (should be a no-op) } //Build the new revision ResourceBE newRevision = BuildRevForMoveAndRename(attachment, targetPage, name, changeSetId); //Insert new revision into DB try { newRevision = SaveResource(newRevision); } catch { //failed to save the revision, undo the file move with the IStorage. (Should be a no-op) if (move) { _dekiContext.Instance.Storage.MoveFile(attachment, sourcePage); } throw; //NOTE MaxM: file rename does not even touch IStorage. No need to undo it } //Notification for file move if (loggingEnabled) { if (move) { RecentChangeBL.AddFileRecentChange(_dekiContext.Now, sourcePage, _dekiContext.User, DekiResources.FILE_MOVED_TO(attachment.Name, targetPage.Title.AsPrefixedUserFriendlyPath()), changeSetId); RecentChangeBL.AddFileRecentChange(_dekiContext.Now, targetPage, _dekiContext.User, DekiResources.FILE_MOVED_FROM(attachment.Name, sourcePage.Title.AsPrefixedUserFriendlyPath()), changeSetId); } if (rename) { RecentChangeBL.AddFileRecentChange(_dekiContext.Now, sourcePage, _dekiContext.User, DekiResources.FILE_RENAMED_TO(attachment.Name, name), changeSetId); } } //Notification for file rename and move use same event _dekiContext.Instance.EventSink.AttachmentMove(_dekiContext.Now, attachment, sourcePage, _dekiContext.User); return(newRevision); }
public ResourceBE AddAttachment(ResourceBE existingRevision, Stream filestream, long filesize, MimeType mimeType, PageBE targetPage, string userDescription, string fileName, bool isMsWebDav) { if (_dekiContext.Instance.MaxFileSize < filesize) { throw new AttachmentMaxFileSizeAllowedInvalidArgumentException(_dekiContext.Instance.MaxFileSize); } var saveFileName = ValidateFileName(fileName); if (existingRevision != null) { if (!saveFileName.EqualsInvariant(existingRevision.Name)) { // An existing file is getting renamed. Make sure no file exists with the new name var existingAttachment = GetPageAttachment(targetPage.ID, saveFileName); if (existingAttachment != null) { throw new AttachmentExistsOnPageConflictException(saveFileName, targetPage.Title.AsUserFriendlyName()); } } } // If file is found but has been deleted, create a new file. if (existingRevision != null && existingRevision.ResourceIsDeleted) { existingRevision = null; } if (isMsWebDav) { _log.DebugFormat("Upload client is MD WebDAV, provided mimetype is: {0}", mimeType); var extensionFileType = MimeType.FromFileExtension(Path.GetExtension(saveFileName)); if (!extensionFileType.Match(mimeType) || extensionFileType == MimeType.DefaultMimeType) { mimeType = existingRevision == null ? extensionFileType : existingRevision.MimeType; _log.DebugFormat("using mimetype '{0}' instead", mimeType); } } ResourceBE attachment; var resourceContents = new ResourceContentBE((uint)filesize, mimeType); var isUpdate = false; if (existingRevision == null) { attachment = _resourceBL.BuildRevForNewResource((uint)targetPage.ID, ResourceBE.ParentType.PAGE, saveFileName, mimeType, (uint)filesize, null, ResourceBE.Type.FILE, _dekiContext.User.ID, resourceContents); } else { isUpdate = true; attachment = BuildRevForContentUpdate(existingRevision, mimeType, (uint)filesize, null, saveFileName, resourceContents); } // rewrite mimetype to text/plain for certain extensions string extension = attachment.FilenameExtension; if (_dekiContext.Instance.FileExtensionForceAsTextList.Any(forcedExtensions => extension == forcedExtensions)) { attachment.MimeType = MimeType.TEXT; } // Insert the attachment into the DB attachment = SaveResource(attachment); try { // Save file to storage provider _dekiContext.Instance.Storage.PutFile(attachment, SizeType.ORIGINAL, new StreamInfo(filestream, filesize, mimeType)); } catch (Exception x) { _dekiContext.Instance.Log.WarnExceptionFormat(x, "Failed to save attachment to storage provider"); // Upon save failure, delete the record from the db. _session.Resources_DeleteRevision(attachment.ResourceId, attachment.Revision); throw; } // Set description property if (!string.IsNullOrEmpty(userDescription)) { attachment = SetDescription(attachment, userDescription); } // For images resolve width/height (if not in imagemagick's blacklist) attachment = IdentifyUnknownImage(attachment); // Pre render thumbnails of images AttachmentPreviewBL.PreSaveAllPreviews(attachment); PageBL.Touch(targetPage, DateTime.UtcNow); //TODO MaxM: Connect with transaction RecentChangeBL.AddFileRecentChange(targetPage.Touched, targetPage, _dekiContext.User, DekiResources.FILE_ADDED(attachment.Name), 0); if (isUpdate) { _dekiContext.Instance.EventSink.AttachmentUpdate(_dekiContext.Now, attachment, _dekiContext.User); } else { _dekiContext.Instance.EventSink.AttachmentCreate(_dekiContext.Now, attachment, _dekiContext.User); } return(attachment); }