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; }
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; }
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; }
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; }
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; }
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; }