public ResourceBE[] IdentifyUnknownImages(IEnumerable <ResourceBE> attachments) { List <ResourceBE> ret = new List <ResourceBE>(); foreach (ResourceBE file in attachments) { ResourceBE updatedFile = file; if (file != null && IsAllowedForImageMagickPreview(file) && (file.MetaXml.ImageHeight == null || file.MetaXml.ImageWidth == null)) { StreamInfo fileInfo = _dekiContext.Instance.Storage.GetFile(file, SizeType.ORIGINAL, false); if (file != null) { int width; int height; int frames; if (AttachmentPreviewBL.RetrieveImageDimensions(fileInfo, out width, out height, out frames)) { file.MetaXml.ImageWidth = width; file.MetaXml.ImageHeight = height; // check if we need to store the number of frames (default is 1) if (frames > 1) { file.MetaXml.ImageFrames = frames; } updatedFile = _resourceBL.UpdateResourceRevision(file); } } } ret.Add(updatedFile); } return(ret.ToArray()); }
private XDoc AppendFileXml(XDoc doc, ResourceBE file, string fileSuffix, bool?explicitRevisionInfo, UserBE updatedByUser, PageBE parentPage) { bool requiresEnd = false; string fileElement = string.IsNullOrEmpty(fileSuffix) ? "file" : "file." + fileSuffix; if (doc == null || doc.IsEmpty) { doc = new XDoc(fileElement); } else { doc.Start(fileElement); requiresEnd = true; } doc.Attr("id", file.MetaXml.FileId ?? 0); doc.Attr("revision", file.Revision); doc.Attr("res-id", file.ResourceId); if (file.IsHidden) { doc.Attr("hidden", true); } doc.Attr("href", GetUriInfo(file, explicitRevisionInfo)); doc.Start("filename").Value(file.Name).End(); //Description comes from a property string description = string.Empty; if (!ArrayUtil.IsNullOrEmpty(file.ChildResources)) { ResourceBE descProp = Array.Find(file.ChildResources, p => p != null && p.ResourceType == ResourceBE.Type.PROPERTY && p.Name.EqualsInvariantIgnoreCase(PropertyBL.PROP_DESC)); if (descProp != null) { description = descProp.Content.ToText(); } } doc.Start("description").Value(description).End(); doc.Start("contents") .Attr("type", file.MimeType == null ? null : file.MimeType.ToString()) .Attr("size", file.Size); if ((file.MetaXml.ImageHeight ?? 0) > 0 && (file.MetaXml.ImageWidth ?? 0) > 0) { doc.Attr("width", file.MetaXml.ImageWidth.Value); doc.Attr("height", file.MetaXml.ImageHeight.Value); } doc.Attr("href", GetUriContent(file, explicitRevisionInfo)); doc.End(); //contents if ((file.MetaXml.ImageWidth ?? 0) > 0 && (file.MetaXml.ImageHeight ?? 0) > 0) { string previewMime = AttachmentPreviewBL.ResolvePreviewMime(file.MimeType).ToString(); doc.Start("contents.preview") .Attr("rel", "thumb") .Attr("type", previewMime) .Attr("maxwidth", _dekiContext.Instance.ImageThumbPixels) .Attr("maxheight", _dekiContext.Instance.ImageThumbPixels) .Attr("href", GetUriContent(file, explicitRevisionInfo).With("size", "thumb")); if (!file.IsHeadRevision() || (explicitRevisionInfo ?? false)) { doc.Attr("revision", file.Revision); } doc.End(); //contents.preview: thumb doc.Start("contents.preview") .Attr("rel", "webview") .Attr("type", previewMime) .Attr("maxwidth", _dekiContext.Instance.ImageWebviewPixels) .Attr("maxheight", _dekiContext.Instance.ImageWebviewPixels) .Attr("href", GetUriContent(file, explicitRevisionInfo).With("size", "webview")); if (!file.IsHeadRevision() || (explicitRevisionInfo ?? false)) { doc.Attr("revision", file.Revision); } doc.End(); //contents.preview: webview } doc.Start("date.created").Value(file.Timestamp).End(); if (updatedByUser != null) { doc.Add(UserBL.GetUserXml(updatedByUser, "createdby", Utils.ShowPrivateUserInfo(updatedByUser))); } if (file.ResourceIsDeleted && ((file.ChangeMask & ResourceBE.ChangeOperations.DELETEFLAG) == ResourceBE.ChangeOperations.DELETEFLAG)) { if (updatedByUser != null) { doc.Add(UserBL.GetUserXml(updatedByUser, "deletedby", Utils.ShowPrivateUserInfo(updatedByUser))); } doc.Start("date.deleted").Value(file.Timestamp).End(); } if (file.IsHeadRevision() && !(explicitRevisionInfo ?? false) && !file.ResourceIsDeleted) { uint filteredCount = _session.Resources_GetRevisionCount(file.ResourceId, DEFAULT_REVISION_FILTER); doc.Start("revisions"); doc.Attr("count", filteredCount); doc.Attr("totalcount", file.Revision); doc.Attr("href", GetUri(file).At("revisions")); doc.End(); } else { if (file.ChangeMask != ResourceBE.ChangeOperations.UNDEFINED) { doc.Start("user-action").Attr("type", file.ChangeMask.ToString().ToLowerInvariant()).End(); } } //parent page is passed in for verbose output only if (parentPage != null) { doc.Add(PageBL.GetPageXml(parentPage, "parent")); } if (file.ChildResources != null) { List <ResourceBE> properties = new List <ResourceBE>(); foreach (ResourceBE p in file.ChildResources) { properties.Add(p); } doc = PropertyBL.Instance.GetPropertyXml(properties.ToArray(), GetUri(file), null, null, doc); } if (file.IsHidden) { uint?userIdHiddenBy = file.MetaXml.RevisionHiddenUserId; if (userIdHiddenBy != null) { UserBE userHiddenBy = UserBL.GetUserById(userIdHiddenBy.Value); if (userHiddenBy != null) { doc.Add(UserBL.GetUserXml(userHiddenBy, "hiddenby", Utils.ShowPrivateUserInfo(userHiddenBy))); } } doc.Elem("date.hidden", file.MetaXml.RevisionHiddenTimestamp ?? DateTime.MinValue); doc.Elem("description.hidden", file.MetaXml.RevisionHiddenComment ?? string.Empty); } if (requiresEnd) { doc.End(); //file } return(doc); }
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); }