public Yield Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result <DreamMessage> response) { // we only support GET as verb DreamMessage reply; if ((verb != Verb.GET) && (verb != Verb.HEAD)) { reply = new DreamMessage(DreamStatus.MethodNotAllowed, null, null); reply.Headers.Allow = Verb.GET + "," + Verb.HEAD; } else { bool head = (verb == Verb.HEAD); // try to load the assembly System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(uri.Host); Version version = assembly.GetName().Version; DateTime timestamp = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2); // check if request is just about re-validation if (!head && request.CheckCacheRevalidation(timestamp)) { reply = DreamMessage.NotModified(); } else { try { System.IO.Stream stream = assembly.GetManifestResourceStream(uri.Path.Substring(1)); if (stream != null) { MimeType mime = MimeType.New(uri.GetParam(DreamOutParam.TYPE, null)) ?? MimeType.BINARY; reply = new DreamMessage(DreamStatus.Ok, null, mime, stream.Length, head ? System.IO.Stream.Null : stream); if (head) { stream.Close(); } else { reply.SetCacheMustRevalidate(timestamp); } } else { reply = DreamMessage.NotFound("could not find resource"); } } catch (System.IO.FileNotFoundException) { reply = DreamMessage.NotFound("could not find resource"); } catch (Exception e) { reply = DreamMessage.InternalError(e); } } } response.Return(reply); yield break; }
public Yield Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) { // we only support GET as verb DreamMessage reply; if((verb != Verb.GET) && (verb != Verb.HEAD)) { reply = new DreamMessage(DreamStatus.MethodNotAllowed, null, null); reply.Headers.Allow = Verb.GET + "," + Verb.HEAD; } else { bool head = (verb == Verb.HEAD); // try to load the assembly System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(uri.Host); Version version = assembly.GetName().Version; DateTime timestamp = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2); // check if request is just about re-validation if(!head && request.CheckCacheRevalidation(timestamp)) { reply = DreamMessage.NotModified(); } else { try { System.IO.Stream stream = assembly.GetManifestResourceStream(uri.Path.Substring(1)); if(stream != null) { MimeType mime = MimeType.New(uri.GetParam(DreamOutParam.TYPE, null)) ?? MimeType.BINARY; reply = new DreamMessage(DreamStatus.Ok, null, mime, stream.Length, head ? System.IO.Stream.Null : stream); if(head) { stream.Close(); } else { reply.SetCacheMustRevalidate(timestamp); } } else { reply = DreamMessage.NotFound("could not find resource"); } } catch(System.IO.FileNotFoundException) { reply = DreamMessage.NotFound("could not find resource"); } catch(Exception e) { reply = DreamMessage.InternalError(e); } } } response.Return(reply); 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 GetFile(DreamContext context, DreamMessage request, Result<DreamMessage> response) { PageBE parentPage = null; DreamMessage responseMsg = null; AttachmentBE fileRevision = GetAttachment(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 DreamBadRequestException(DekiResources.INVALID_FILE_RATIO); } } // check 'size' parameter SizeType size = SizeType.UNDEFINED; if (!string.IsNullOrEmpty(cachedSize) && !SysUtil.TryParseEnum(cachedSize.Trim(), out size)) { throw new DreamAbortException(DreamMessage.BadRequest(DekiResources.INVALID_FILE_SIZE)); } // check 'format' parameter FormatType format = FormatType.UNDEFINED; if(!string.IsNullOrEmpty(sFormat) && !SysUtil.TryParseEnum(sFormat.Trim(), out format)) { throw new DreamBadRequestException(DekiResources.INVALID_FILE_FORMAT); } #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 { file = DekiContext.Current.Instance.Storage.GetFile(fileRevision, SizeType.ORIGINAL, true); } // prepare response if(file == null) { throw new DreamInternalErrorException(string.Format(DekiResources.COULD_NOT_RETRIEVE_FILE, fileRevision.ResourceId, fileRevision.Revision)); } if(file.Uri != null) { responseMsg = DreamMessage.Redirect(file.Uri); } else { bool inline = fileRevision.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<AttachmentBE> revisions = AttachmentBL.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; }