public override Stream Open() { if (_node == null) { try { var allowCompiledContent = AllowCompiledContent(_repositoryPath); // http://localhost/TestDoc.docx?action=RestoreVersion&version=2.0A // When there are 'action' and 'version' parameters in the requested URL the portal is trying to load the desired version of the node of the requested action. // This leads to an exception when the action doesn't have that version. // _repositoryPath will point to the node of action and ContextNode will be the document // if paths are not equal then we will return the last version of the requested action if (PortalContext.Current == null || string.IsNullOrEmpty(PortalContext.Current.VersionRequest) || _repositoryPath != PortalContext.Current.ContextNodePath) { if (allowCompiledContent) { // elevated mode: pages, ascx files, etc. using (new SystemAccount()) { _node = Node.LoadNode(_repositoryPath, VersionNumber.LastFinalized); } } else { _node = Node.LoadNode(_repositoryPath, VersionNumber.LastFinalized); } } else { VersionNumber version; if (VersionNumber.TryParse(PortalContext.Current.VersionRequest, out version)) { Node node; if (allowCompiledContent) { // elevated mode: pages, ascx files, etc. using (new SystemAccount()) { node = Node.LoadNode(_repositoryPath, version); } } else { node = Node.LoadNode(_repositoryPath, version); } if (node != null && node.SavingState == ContentSavingState.Finalized) { _node = node; } } } // we cannot serve the binary if the user has only See or Preview permissions for the content if (_node != null && (_node.IsHeadOnly || _node.IsPreviewOnly) && HttpContext.Current != null) { AuthenticationHelper.ThrowForbidden(_node.Name); } } catch (SenseNetSecurityException ex) //logged { Logger.WriteException(ex); if (HttpContext.Current == null || (_repositoryPath != null && _repositoryPath.ToLower().EndsWith(".ascx"))) { throw; } AuthenticationHelper.DenyAccess(HttpContext.Current.ApplicationInstance); } } if (_node == null) { throw new ApplicationException(string.Format("{0} not found. RepositoryFile cannot be served.", _repositoryPath)); } string propertyName = string.Empty; if (PortalContext.Current != null) { propertyName = PortalContext.Current.QueryStringNodePropertyName; } if (string.IsNullOrEmpty(propertyName)) { propertyName = PortalContext.DefaultNodePropertyName; } var propType = _node.PropertyTypes[propertyName]; if (propType == null) { throw new ApplicationException("Property not found: " + propertyName); } ////<only_for_test> //if(propType == null) //{ // StringBuilder sb = new StringBuilder(); // sb.AppendFormat("Property {0} not found.", propertyName); // sb.AppendLine(); // foreach (var pt in _node.PropertyTypes) // { // sb.AppendFormat("PropertyName='{0}' - DataType='{1}'", pt.Name, pt.DataType); // sb.AppendLine(); // } // return new MemoryStream(System.Text.Encoding.UTF8.GetBytes(sb.ToString())); //} ////</only_for_test> var propertyDataType = propType.DataType; Stream stream; switch (propertyDataType) { case DataType.Binary: string contentType; BinaryFileName fileName; stream = DocumentBinaryProvider.Current.GetStream(_node, propertyName, out contentType, out fileName); if (stream == null) { throw new ApplicationException(string.Format("BinaryProperty.Value.GetStream() returned null. RepositoryPath={0}, OriginalUri={1}, AppDomainFriendlyName={2} ", this._repositoryPath, ((PortalContext.Current != null) ? PortalContext.Current.OriginalUri.ToString() : "PortalContext.Current is null"), AppDomain.CurrentDomain.FriendlyName)); } //Set MIME type only if this is the main content (skip asp controls and pages, //page templates and other repository files opened during the request). //We need this in case of special images, fonts, etc, and handle the variable //at the end of the request (PortalContextModule.EndRequest method). if (HttpContext.Current != null && PortalContext.Current != null && PortalContext.Current.RepositoryPath == _repositoryPath && (string.IsNullOrEmpty(PortalContext.Current.ActionName) || PortalContext.Current.ActionName == "Browse") && !string.IsNullOrEmpty(contentType) && contentType != "text/asp") { if (!HttpContext.Current.Items.Contains(RESPONSECONTENTTYPEKEY)) { HttpContext.Current.Items.Add(RESPONSECONTENTTYPEKEY, contentType); } //set the value anyway as it may be useful in case of our custom file handler (SenseNetStaticFileHandler) HttpContext.Current.Response.ContentType = contentType; //add the necessary header for the css font-face rule if (MimeTable.IsFontType(fileName.Extension)) { HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", HttpContext.Current.Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped)); } } //set compressed encoding if necessary if (HttpContext.Current != null && MimeTable.IsCompressedType(fileName.Extension)) { HttpContext.Current.Response.Headers.Add("Content-Encoding", "gzip"); } //let the client code log file downloads var file = _node as ContentRepository.File; if (file != null) { ContentRepository.File.Downloaded(file.Id); } break; case DataType.String: case DataType.Text: case DataType.Int: case DataType.DateTime: stream = new MemoryStream(Encoding.UTF8.GetBytes(_node[propertyName].ToString())); break; default: throw new NotSupportedException(string.Format("The {0} property cannot be served because that's datatype is {1}.", propertyName, propertyDataType)); } return(stream); }
void IHttpHandler.ProcessRequest(HttpContext context) { Stream imageStream; BinaryData binaryData; var propNameParam = context.Request.QueryString["NodeProperty"]; var propertyName = string.Empty; var widthParam = context.Request.QueryString["width"]; var heightParam = context.Request.QueryString["height"]; if (!string.IsNullOrEmpty(propNameParam)) { propertyName = propNameParam.Replace("$", "#"); binaryData = this.GetBinary(propertyName); } else { binaryData = this.Binary; } if (DocumentPreviewProvider.Current != null && DocumentPreviewProvider.Current.IsPreviewOrThumbnailImage(NodeHead.Get(this.Id))) { // get preview image with watermark or redaction if necessary imageStream = string.IsNullOrEmpty(propertyName) ? DocumentPreviewProvider.Current.GetRestrictedImage(this) : DocumentPreviewProvider.Current.GetRestrictedImage(this, propertyName); } else { imageStream = binaryData.GetStream(); } //set compressed encoding if necessary if (MimeTable.IsCompressedType(this.Extension)) { context.Response.Headers.Add("Content-Encoding", "gzip"); } context.Response.ContentType = binaryData.ContentType; imageStream.Position = 0; if (!string.IsNullOrEmpty(widthParam) && !string.IsNullOrEmpty(heightParam)) { int width; int height; if (!int.TryParse(widthParam, out width)) { width = 200; } if (!int.TryParse(heightParam, out height)) { height = 200; } // compute a new, resized stream on-the-fly using (var resizedStream = ImageResizer.CreateResizedImageFile(imageStream, width, height, 80, getImageFormat(binaryData.ContentType))) { resizedStream.CopyTo(context.Response.OutputStream); } } else { imageStream.CopyTo(context.Response.OutputStream); } imageStream.Close(); }
public override Stream Open() { if (_node == null) { try { var allowCompiledContent = AllowCompiledContent(_repositoryPath); // http://localhost/TestDoc.docx?action=RestoreVersion&version=2.0A // When there are 'action' and 'version' parameters in the requested URL the portal is trying to load the desired version of the node of the requested action. // This leads to an exception when the action doesn't have that version. // _repositoryPath will point to the node of action and ContextNode will be the document // if paths are not equal then we will return the last version of the requested action. // We also have to ignore the version request parameter in case of binary handler, because that // ashx must not have multiple versions. if (PortalContext.Current == null || PortalContext.Current.BinaryHandlerRequestedNodeHead != null || string.IsNullOrEmpty(PortalContext.Current.VersionRequest) || _repositoryPath != PortalContext.Current.ContextNodePath) { if (allowCompiledContent) { // elevated mode: pages, ascx files, etc. using (new SystemAccount()) { _node = Node.LoadNode(_repositoryPath, VersionNumber.LastFinalized); } } else { _node = Node.LoadNode(_repositoryPath, VersionNumber.LastFinalized); } } else { VersionNumber version; if (VersionNumber.TryParse(PortalContext.Current.VersionRequest, out version)) { Node node; if (allowCompiledContent) { // elevated mode: pages, ascx files, etc. using (new SystemAccount()) { node = Node.LoadNode(_repositoryPath, version); } } else { node = Node.LoadNode(_repositoryPath, version); } if (node != null && node.SavingState == ContentSavingState.Finalized) { _node = node; } } } // we cannot serve the binary if the user has only See or Preview permissions for the content if (_node != null && (_node.IsHeadOnly || _node.IsPreviewOnly) && HttpContext.Current != null) { AuthenticationHelper.ThrowForbidden(_node.Name); } } catch (SenseNetSecurityException ex) // logged { SnLog.WriteException(ex); if (HttpContext.Current == null || (_repositoryPath != null && _repositoryPath.ToLower().EndsWith(".ascx"))) { throw; } AuthenticationHelper.DenyAccess(HttpContext.Current.ApplicationInstance); } } if (_node == null) { throw new ApplicationException(string.Format("{0} not found. RepositoryFile cannot be served.", _repositoryPath)); } string propertyName = string.Empty; if (PortalContext.Current != null) { propertyName = PortalContext.Current.QueryStringNodePropertyName; } if (string.IsNullOrEmpty(propertyName)) { propertyName = PortalContext.DefaultNodePropertyName; } var propType = _node.PropertyTypes[propertyName]; if (propType == null) { throw new ApplicationException("Property not found: " + propertyName); } var propertyDataType = propType.DataType; Stream stream; switch (propertyDataType) { case DataType.Binary: string contentType; BinaryFileName fileName; // Images need to be handled differently, because of these reasons: // - dimensions may be changed dynamically, based on request parameters // - preview images may be restricted (redacted) based on permissions if (_node is Image img) { var parameters = HttpContext.Current?.Request.QueryString; stream = img.GetImageStream(propertyName, parameters?.AllKeys.ToDictionary(k => k ?? string.Empty, k => (object)parameters[k]), out contentType, out fileName); } else { stream = DocumentBinaryProvider.Current.GetStream(_node, propertyName, out contentType, out fileName); } if (stream == null) { throw new ApplicationException(string.Format("BinaryProperty.Value.GetStream() returned null. RepositoryPath={0}, OriginalUri={1}, AppDomainFriendlyName={2} ", this._repositoryPath, ((PortalContext.Current != null) ? PortalContext.Current.RequestedUri.ToString() : "PortalContext.Current is null"), AppDomain.CurrentDomain.FriendlyName)); } // Set MIME type only if this is the main content (skip asp controls and pages, // page templates and other repository files opened during the request). // We need this in case of special images, fonts, etc, and handle the variable // at the end of the request (PortalContextModule.EndRequest method). if (HttpContext.Current != null && PortalContext.Current != null && string.Equals(PortalContext.Current.RepositoryPath, _repositoryPath, StringComparison.InvariantCultureIgnoreCase) && (string.IsNullOrEmpty(PortalContext.Current.ActionName) || string.Equals(PortalContext.Current.ActionName, "Browse", StringComparison.InvariantCultureIgnoreCase)) && !string.IsNullOrEmpty(contentType) && contentType != "text/asp") { if (!HttpContext.Current.Items.Contains(RESPONSECONTENTTYPEKEY)) { HttpContext.Current.Items.Add(RESPONSECONTENTTYPEKEY, contentType); } // set the value anyway as it may be useful in case of our custom file handler (SenseNetStaticFileHandler) HttpContext.Current.Response.ContentType = contentType; // add the necessary header for the css font-face rule if (MimeTable.IsFontType(fileName.Extension)) { HttpHeaderTools.SetAccessControlHeaders(); } } // set compressed encoding if necessary if (HttpContext.Current != null && MimeTable.IsCompressedType(fileName.Extension)) { HttpContext.Current.Response.Headers.Add("Content-Encoding", "gzip"); } // let the client code log file downloads var file = _node as ContentRepository.File; if (file != null) { ContentRepository.File.Downloaded(file.Id); } break; case DataType.String: case DataType.Text: case DataType.Int: case DataType.DateTime: stream = new MemoryStream(Encoding.UTF8.GetBytes(_node[propertyName].ToString())); break; default: throw new NotSupportedException(string.Format("The {0} property cannot be served because that's datatype is {1}.", propertyName, propertyDataType)); } return(stream); }