Exemplo n.º 1
0
        public void ProcessRequest(HttpContext context)
        {
            var request  = context.Request;
            var response = context.Response;

            VirtualFile vf       = null;
            var         filePath = request.FilePath;

            // Cross-Origin Resource Sharing (CORS)
            if (!HttpHeaderTools.IsOriginHeaderAllowed())
            {
                AuthenticationHelper.ThrowForbidden(filePath);
            }

            if (HostingEnvironment.VirtualPathProvider.FileExists(filePath))
            {
                vf = HostingEnvironment.VirtualPathProvider.GetFile(filePath);
            }

            if (vf == null)
            {
                throw new HttpException(404, "File does not exist");
            }

            response.ClearContent();

            // Set content type only if this is not a RepositoryFile, because the
            // Open method of RepositoryFile will set the content type itself.
            if (!(vf is RepositoryFile))
            {
                var extension = System.IO.Path.GetExtension(filePath);
                context.Response.ContentType = MimeTable.GetMimeType(extension);

                // add the necessary header for the css font-face rule
                if (MimeTable.IsFontType(extension))
                {
                    HttpHeaderTools.SetAccessControlHeaders();
                }
            }

            // The bytes we write into the output stream will NOT be buffered and will be sent
            // to the client immediately. This makes sure that the whole (potentially large)
            // file is not loaded into the memory on the server.
            response.BufferOutput = false;

            using (var stream = vf.Open())
            {
                response.AppendHeader("Content-Length", stream.Length.ToString());
                response.Clear();

                // Let ASP.NET handle sending bytes to the client (avoid Flush).
                stream.CopyTo(response.OutputStream);
            }
        }
Exemplo n.º 2
0
        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;
                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);
        }