コード例 #1
0
ファイル: S3StorageService.cs プロジェクト: yonglehou/DReAM
        public Yield GetFileOrFolderListing(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            var          head = "HEAD".EqualsInvariant(context.Verb);
            var          path = GetPath(context);
            var          data = _s3Client.GetDataInfo(path, head);
            DreamMessage result;

            if (data == null)
            {
                response.Return(DreamMessage.NotFound("no such file or folder"));
                yield break;
            }
            if (data.IsDirectory)
            {
                // Note (arnec): HEAD for a directory doesn't really mean anything, so we just return ok, to indicate that it exists
                result = head ? DreamMessage.Ok() : DreamMessage.Ok(data.AsDirectoryDocument());
            }
            else
            {
                // dealing with a file request
                var filehandle = data.AsFileHandle();

                // check if request contains a 'if-modified-since' header
                if (request.CheckCacheRevalidation(filehandle.Modified) && (filehandle.Modified.Year >= 1900))
                {
                    response.Return(DreamMessage.NotModified());
                    yield break;
                }
                result = head
                             ? new DreamMessage(DreamStatus.Ok, null, filehandle.MimeType, filehandle.Size, Stream.Null)
                             : DreamMessage.Ok(filehandle.MimeType, filehandle.Size, filehandle.Stream);

                // add caching headers if file was found
                if (!head && result.IsSuccessful)
                {
                    // add caching information; this will avoid unnecessary data transfers by user-agents with caches
                    result.SetCacheMustRevalidate(filehandle.Modified);
                }
            }
            response.Return(result);
            yield break;
        }
コード例 #2
0
        public Yield GetSiteLogo(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            DreamMessage responseMsg = null;
            DateTime     modified    = DekiContext.Current.Instance.Storage.GetSiteFileTimestamp(LOGO_LABEL);

            try {
                if (modified != DateTime.MinValue)
                {
                    if (request.CheckCacheRevalidation(modified))
                    {
                        responseMsg = DreamMessage.NotModified();
                    }
                }

                if (responseMsg == null)
                {
                    StreamInfo file = DekiContext.Current.Instance.Storage.GetSiteFile(LOGO_LABEL, false);
                    if (file != null)
                    {
                        responseMsg = DreamMessage.Ok(MimeType.PNG, file.Length, file.Stream);

                        //Build the content disposition headers
                        responseMsg.Headers.ContentDisposition = new ContentDisposition(true, file.Modified ?? DateTime.UtcNow, null, null, "logo.png", file.Length);

                        //Set caching headers
                        responseMsg.SetCacheMustRevalidate(modified);
                    }
                    else
                    {
                        responseMsg = DreamMessage.NotFound("Logo has not been uploaded");
                    }
                }
            } catch {
                if (responseMsg != null)
                {
                    responseMsg.Close();
                }
                throw;
            }
            response.Return(responseMsg);
            yield break;
        }
コード例 #3
0
        public Yield GetFileOrFolderListing(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            bool   head = StringUtil.EqualsInvariant(context.Verb, "HEAD");
            string path = GetPath(context);

            DreamMessage result;

            if (File.Exists(path))
            {
                // dealing with a file request
                TouchMeta(path);

                // check if request contains a 'if-modified-since' header
                var lastmodified = File.GetLastWriteTime(path);
                if (request.CheckCacheRevalidation(lastmodified) && (lastmodified.Year >= 1900))
                {
                    response.Return(DreamMessage.NotModified());
                    yield break;
                }

                // retrieve file
                try {
                    result = DreamMessage.FromFile(path, head);
                } catch (FileNotFoundException) {
                    result = DreamMessage.NotFound("file not found");
                } catch (Exception) {
                    result = DreamMessage.BadRequest("invalid path");
                }

                // add caching headers if file was found
                if (!head && result.IsSuccessful)
                {
                    // add caching information; this will avoid unnecessary data transfers by user-agents with caches
                    result.SetCacheMustRevalidate(lastmodified);
                }
            }
            else if (Directory.Exists(path))
            {
                // dealing with a directory request
                if (head)
                {
                    // HEAD for a directory doesn't really mean anything, so we just return ok, to indicate that it exists
                    result = DreamMessage.Ok();
                }
                else
                {
                    var doc = new XDoc("files");

                    // list directory contents
                    var directories = Directory.GetDirectories(path);
                    foreach (var dir in directories)
                    {
                        if (dir.EndsWithInvariantIgnoreCase(META))
                        {
                            continue;
                        }
                        doc.Start("folder")
                        .Elem("name", Path.GetFileName(dir))
                        .End();
                    }
                    foreach (var filepath in Directory.GetFiles(path))
                    {
                        var file = new FileInfo(filepath);
                        doc.Start("file")
                        .Elem("name", file.Name)
                        .Elem("size", file.Length)
                        .Elem("date.created", file.CreationTimeUtc)
                        .Elem("date.modified", file.LastWriteTimeUtc);
                        var entry = SyncMeta(filepath);
                        if (entry != null)
                        {
                            doc.Elem("date.expire", entry.When);
                            doc.Elem("date.ttl", entry.TTL);
                        }
                        doc.End();
                    }
                    result = DreamMessage.Ok(doc);
                }
            }
            else
            {
                // nothin here
                result = DreamMessage.NotFound("no such file or folder");
            }

            response.Return(result);
            yield break;
        }
コード例 #4
0
        public Yield GetFile(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PageBE       parentPage   = null;
            DreamMessage responseMsg  = null;
            ResourceBE   fileRevision = GetAttachment(context, request, Permissions.READ, true, false, out parentPage);

            if (fileRevision.IsHidden)
            {
                PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            }

            // check if only file information is requested
            if (context.Verb == Verb.HEAD)
            {
                response.Return(new DreamMessage(DreamStatus.Ok, null, fileRevision.MimeType, (long)fileRevision.Size, Stream.Null));
                yield break;
            }
            try {
                if (request.CheckCacheRevalidation(fileRevision.Timestamp))
                {
                    responseMsg = DreamMessage.NotModified();
                }
                if (responseMsg == null)
                {
                    #region Preview related parameter parsing
                    string sFormat    = context.GetParam("format", string.Empty);
                    string sRatio     = context.GetParam("ratio", string.Empty);
                    uint   height     = context.GetParam <uint>("height", 0);
                    uint   width      = context.GetParam <uint>("width", 0);
                    string cachedSize = context.GetParam("size", string.Empty);

                    // check 'ratio' parameter
                    RatioType ratio = RatioType.UNDEFINED;
                    if (!string.IsNullOrEmpty(sRatio))
                    {
                        switch (sRatio.ToLowerInvariant().Trim())
                        {
                        case "var":
                        case "variable":
                            ratio = RatioType.VARIABLE;
                            break;

                        case "fixed":
                            ratio = RatioType.FIXED;
                            break;

                        default:
                            throw new AttachmentFileRatioInvalidArgumentException();
                        }
                    }

                    // check 'size' parameter
                    SizeType size = SizeType.UNDEFINED;
                    if (!string.IsNullOrEmpty(cachedSize) && !SysUtil.TryParseEnum(cachedSize.Trim(), out size))
                    {
                        throw new AttachmentFilesizeInvalidArgumentException();
                    }

                    // check 'format' parameter
                    FormatType format = FormatType.UNDEFINED;
                    if (!string.IsNullOrEmpty(sFormat) && !SysUtil.TryParseEnum(sFormat.Trim(), out format))
                    {
                        throw new AttachmentFileFormatInvalidArgumentException();
                    }
                    #endregion

                    //if any preview related parameters are set, do preview logic. Otherwise return the file
                    StreamInfo file = null;
                    if ((size != SizeType.UNDEFINED && size != SizeType.ORIGINAL) ||
                        ratio != RatioType.UNDEFINED ||
                        format != FormatType.UNDEFINED ||
                        height != 0 ||
                        width != 0
                        )
                    {
                        file = AttachmentPreviewBL.RetrievePreview(fileRevision, height, width, ratio, size, format);
                    }
                    else
                    {
                        var isMSWebDAV = MSWEBDAV_USER_AGENT_REGEX.IsMatch(request.Headers.UserAgent ?? string.Empty);
                        file = DekiContext.Current.Instance.Storage.GetFile(fileRevision, SizeType.ORIGINAL, !isMSWebDAV);
                    }

                    // prepare response
                    if (file == null)
                    {
                        throw new AttachmentDoesNotExistFatalException(fileRevision.ResourceId, fileRevision.Revision);
                    }

                    if (file.Uri != null)
                    {
                        responseMsg = DreamMessage.Redirect(file.Uri);
                    }
                    else
                    {
                        bool inline = fileRevision.MetaXml.ImageHeight.HasValue;

                        // see if we can use the MimeType map for allowing inlining
                        if (!inline)
                        {
                            // if IE inline security is not disabled
                            bool isIE = false;
                            if (!DekiContext.Current.Instance.EnableUnsafeIEContentInlining)
                            {
                                // check the user agent to see if we're dealing with IE
                                isIE = MSIE_USER_AGENT_REGEX.IsMatch(request.Headers.UserAgent ?? string.Empty);
                            }

                            // see if the mime-type could allow inlining
                            inline = DekiContext.Current.Instance.MimeTypeCanBeInlined(fileRevision.MimeType);
                            if (inline && isIE)
                            {
                                // check whether the creator of the file had unsafecontent permission, to override IE security
                                IList <ResourceBE> revisions         = ResourceBL.Instance.GetResourceRevisions(fileRevision.ResourceId, ResourceBE.ChangeOperations.CONTENT, SortDirection.DESC, 1);
                                UserBE             lastContentEditor = UserBL.GetUserById(revisions[0].UserId);
                                inline = PermissionsBL.IsUserAllowed(lastContentEditor, parentPage, Permissions.UNSAFECONTENT);
                            }
                        }
                        responseMsg = DreamMessage.Ok(fileRevision.MimeType, file.Length, file.Stream);
                        responseMsg.Headers["X-Content-Type-Options"] = "nosniff";
                        responseMsg.Headers.ContentDisposition        = new ContentDisposition(inline, fileRevision.Timestamp, null, null, fileRevision.Name, file.Length, request.Headers.UserAgent);

                        // MSIE6 will delete a downloaded file before the helper app trying to use it can get to it so we
                        //have to do custom cache control headers for MSIE6 so that the file can actually be opened
                        if (MSIE6_USER_AGENT_REGEX.IsMatch(request.Headers.UserAgent ?? string.Empty))
                        {
                            responseMsg.Headers["Expires"]   = "0";
                            responseMsg.Headers.Pragma       = "cache";
                            responseMsg.Headers.CacheControl = "private";
                        }
                        else
                        {
                            responseMsg.SetCacheMustRevalidate(fileRevision.Timestamp);
                        }
                    }
                }
            } catch {
                if (responseMsg != null)
                {
                    responseMsg.Close();
                }
                throw;
            }
            response.Return(responseMsg);
            yield break;
        }
コード例 #5
0
ファイル: StorageService.cs プロジェクト: heran/DReAM
        public Yield GetFileOrFolderListing(DreamContext context, DreamMessage request, Result<DreamMessage> response)
        {
            bool head = StringUtil.EqualsInvariant(context.Verb, "HEAD");
            string path = GetPath(context);

            DreamMessage result;
            if(File.Exists(path)) {

                // dealing with a file request
                TouchMeta(path);

                // check if request contains a 'if-modified-since' header
                var lastmodified = File.GetLastWriteTime(path);
                if(request.CheckCacheRevalidation(lastmodified) && (lastmodified.Year >= 1900)) {
                    response.Return(DreamMessage.NotModified());
                    yield break;
                }

                // retrieve file
                try {
                    result = DreamMessage.FromFile(path, head);
                } catch(FileNotFoundException) {
                    result = DreamMessage.NotFound("file not found");
                } catch(Exception) {
                    result = DreamMessage.BadRequest("invalid path");
                }

                // add caching headers if file was found
                if(!head && result.IsSuccessful) {

                    // add caching information; this will avoid unnecessary data transfers by user-agents with caches
                    result.SetCacheMustRevalidate(lastmodified);
                }
            } else if(Directory.Exists(path)) {

                // dealing with a directory request
                if(head) {

                    // HEAD for a directory doesn't really mean anything, so we just return ok, to indicate that it exists
                    result = DreamMessage.Ok();
                } else {
                    var doc = new XDoc("files");

                    // list directory contents
                    var directories = Directory.GetDirectories(path);
                    foreach(var dir in directories) {
                        if(dir.EndsWithInvariantIgnoreCase(META)) {
                            continue;
                        }
                        doc.Start("folder")
                            .Elem("name", Path.GetFileName(dir))
                            .End();
                    }
                    foreach(var filepath in Directory.GetFiles(path)) {
                        var file = new FileInfo(filepath);
                        doc.Start("file")
                            .Elem("name", file.Name)
                            .Elem("size", file.Length)
                            .Elem("date.created", file.CreationTimeUtc)
                            .Elem("date.modified", file.LastWriteTimeUtc);
                        var entry = SyncMeta(filepath);
                        if(entry != null) {
                            doc.Elem("date.expire", entry.When);
                            doc.Elem("date.ttl", entry.TTL);
                        }
                        doc.End();
                    }
                    result = DreamMessage.Ok(doc);
                }
            } else {

                // nothin here
                result = DreamMessage.NotFound("no such file or folder");
            }

            response.Return(result);
            yield break;
        }
コード例 #6
0
ファイル: S3StorageService.cs プロジェクト: danice/DReAM
        public Yield GetFileOrFolderListing(DreamContext context, DreamMessage request, Result<DreamMessage> response)
        {
            var head = "HEAD".EqualsInvariant(context.Verb);
            var path = GetPath(context);
            var data = _s3Client.GetDataInfo(path, head);
            DreamMessage result;
            if(data == null) {
                response.Return(DreamMessage.NotFound("no such file or folder"));
                yield break;
            }
            if(data.IsDirectory) {

                // Note (arnec): HEAD for a directory doesn't really mean anything, so we just return ok, to indicate that it exists
                result = head ? DreamMessage.Ok() : DreamMessage.Ok(data.AsDirectoryDocument());
            } else {

                // dealing with a file request
                var filehandle = data.AsFileHandle();

                // check if request contains a 'if-modified-since' header
                if(request.CheckCacheRevalidation(filehandle.Modified) && (filehandle.Modified.Year >= 1900)) {
                    response.Return(DreamMessage.NotModified());
                    yield break;
                }
                result = head
                             ? new DreamMessage(DreamStatus.Ok, null, filehandle.MimeType, filehandle.Size, Stream.Null)
                             : DreamMessage.Ok(filehandle.MimeType, filehandle.Size, filehandle.Stream);

                // add caching headers if file was found
                if(!head && result.IsSuccessful) {

                    // add caching information; this will avoid unnecessary data transfers by user-agents with caches
                    result.SetCacheMustRevalidate(filehandle.Modified);
                }
            }
            response.Return(result);
            yield break;
        }