Esempio n. 1
0
        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);
        }