Пример #1
0
        public override VirtualFile GetFile(string virtualPath)
        {
            var currentPortalContext = PortalContext.Current;

            // office protocol: instruct microsoft office to open the document without further webdav requests when simply downloading the file
            // webdav requests would cause an authentication window to pop up when downloading a docx
            if (HttpContext.Current != null && HttpContext.Current.Response != null)
            {
                if (Repository.DownloadExtensions.Any(extension => virtualPath.EndsWith(extension)))
                {
                    //we need to do it this way to support a 'download' query parameter with or without a value
                    var queryParams = HttpContext.Current.Request.QueryString.GetValues(null);
                    var download    = HttpContext.Current.Request.QueryString.AllKeys.Contains("download") || (queryParams != null && queryParams.Contains("download"));

                    if (download)
                    {
                        var fName = string.Empty;

                        if (currentPortalContext != null && currentPortalContext.IsRequestedResourceExistInRepository)
                        {
                            // look for a content
                            var node = Node.LoadNode(virtualPath);
                            if (node != null)
                            {
                                fName = DocumentBinaryProvider.Current.GetFileName(node);
                            }
                        }
                        else
                        {
                            // look for a file in the file system
                            fName = Path.GetFileName(virtualPath);
                        }

                        HttpHeaderTools.SetContentDispositionHeader(fName);
                    }
                }
            }

            if (DiskFSSupportMode == DiskFSSupportMode.Prefer && base.FileExists(virtualPath))
            {
                var result = base.GetFile(virtualPath);

                //let the client code log file downloads
                if (PortalContext.Current != null && PortalContext.Current.ContextNodePath != null &&
                    string.Compare(virtualPath, PortalContext.Current.ContextNodePath, StringComparison.Ordinal) == 0)
                {
                    File.Downloaded(virtualPath);
                }

                return(result);
            }

            // Indicates that the VirtualFile is requested by a HttpRequest (a Page.LoadControl also can be a caller, or an aspx for its codebehind file...)
            var isRequestedByHttpRequest =
                (HttpContext.Current != null) && (string.Compare(virtualPath, HttpContext.Current.Request.Url.LocalPath, StringComparison.InvariantCultureIgnoreCase) == 0);

            if (isRequestedByHttpRequest && currentPortalContext.IsRequestedResourceExistInRepository)
            {
                return(new RepositoryFile(virtualPath, currentPortalContext.RepositoryPath));
            }
            else if (IsFileExistsInRepository(virtualPath)) //OPT: nem kéne még egyszer megnézni, hogy bent van-e...
            {
                return(new RepositoryFile(virtualPath, virtualPath));
            }
            else if (IsFileExistsInAssembly(virtualPath))
            {
                return(new EmbeddedFile(virtualPath));
            }
            else
            {
                // Otherwise it may exist in the filesystem - call the base
                return(base.GetFile(virtualPath));
            }
        }
Пример #2
0
        private void HandleResponseForClientCache(PortalContextInitInfo initInfo)
        {
            // binaryhandler
            if (initInfo.BinaryHandlerRequestedNodeHead != null)
            {
                var bhMaxAge = Settings.GetValue(PortalSettings.SETTINGSNAME, PortalSettings.SETTINGS_BINARYHANDLER_MAXAGE, initInfo.RepositoryPath, 0);
                if (bhMaxAge > 0)
                {
                    HttpHeaderTools.SetCacheControlHeaders(bhMaxAge);

                    // We're only handling these if the visitor has permissions to the node
                    if (CheckVisitorPermissions(initInfo.RequestedNodeHead))
                    {
                        // handle If-Modified-Since and Last-Modified headers
                        HttpHeaderTools.EndResponseForClientCache(initInfo.BinaryHandlerRequestedNodeHead.ModificationDate);
                    }
                    else
                    {
                        //otherwise store the value for later use
                        initInfo.ModificationDateForClient = initInfo.BinaryHandlerRequestedNodeHead.ModificationDate;
                    }

                    return;
                }
            }

            if (initInfo.IsWebdavRequest || initInfo.IsOfficeProtocolRequest)
            {
                //HttpHeaderTools.SetCacheControlHeaders(0, HttpCacheability.NoCache);
                //HttpContext.Current.Response.Headers.Add("Cache-Control", "no-store, no-cache, private");
                HttpContext.Current.Response.Headers.Add("Pragma", "no-cache");                       //HTTP 1.0
                HttpContext.Current.Response.Headers.Add("Expires", "Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
                return;
            }

            // get requested nodehead
            if (initInfo.RequestedNodeHead == null)
            {
                return;
            }

            // if action name is given, do not do shortcircuit (eg. myscript.js?action=Edit should be a server-rendered page)
            if (!string.IsNullOrEmpty(initInfo.ActionName))
            {
                return;
            }

            // **********************************************************
            // Image content check is moved to OnAuthorize event handler, because it needs the
            // fully loaded node. Here we handle only other content - e.g. js/css files.
            // **********************************************************

            if (!initInfo.RequestedNodeHead.GetNodeType().IsInstaceOfOrDerivedFrom(typeof(Image).Name))
            {
                var cacheSetting = GetCacheHeaderSetting(initInfo.RequestUri, initInfo.RequestedNodeHead);
                if (cacheSetting.HasValue)
                {
                    HttpHeaderTools.SetCacheControlHeaders(cacheSetting.Value);

                    // We're only handling these if the visitor has permissions to the node
                    if (CheckVisitorPermissions(initInfo.RequestedNodeHead))
                    {
                        // handle If-Modified-Since and Last-Modified headers
                        HttpHeaderTools.EndResponseForClientCache(initInfo.RequestedNodeHead.ModificationDate);
                    }
                    else
                    {
                        //otherwise store the value for later use
                        initInfo.ModificationDateForClient = initInfo.RequestedNodeHead.ModificationDate;
                    }

                    return;
                }
            }

            // applications
            Application app;

            // elevate to sysadmin, as we are startupuser here, and group 'everyone' should have permissions to application without elevation
            using (new SystemAccount())
            {
                //load the application, or the node itself if it is an application
                if (initInfo.RequestedNodeHead.GetNodeType().IsInstaceOfOrDerivedFrom("Application"))
                {
                    app = Node.LoadNode(initInfo.RequestedNodeHead) as Application;
                }
                else
                {
                    app = ApplicationStorage.Instance.GetApplication(initInfo.ActionName, initInfo.RequestedNodeHead, initInfo.DeviceName);
                }
            }

            if (app == null)
            {
                return;
            }

            var maxAge       = app.NumericMaxAge;
            var cacheControl = app.CacheControlEnumValue;

            if (cacheControl.HasValue && maxAge.HasValue)
            {
                HttpHeaderTools.SetCacheControlHeaders(maxAge.Value, cacheControl.Value);

                // We're only handling these if the visitor has permissions to the node
                if (CheckVisitorPermissions(initInfo.RequestedNodeHead))
                {
                    // handle If-Modified-Since and Last-Modified headers
                    HttpHeaderTools.EndResponseForClientCache(initInfo.RequestedNodeHead.ModificationDate);
                }
                else
                {
                    //otherwise store the value for later use
                    initInfo.ModificationDateForClient = initInfo.RequestedNodeHead.ModificationDate;
                }
            }
        }
Пример #3
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 (SecurityException 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 (StaticFileHandler)
                    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);
        }
Пример #4
0
        void OnAuthorize(object sender, EventArgs e)
        {
            //At this point the user has at least some permissions for the requested content. This means
            //we can respond with a 304 status if the content has not changed, without opening a security hole.

            //This value could be set earlier by the HandleResponseForClientCache method
            //(e.g. because of binaryhandler or application client cache values).
            if (PortalContext.Current.ModificationDateForClient.HasValue)
            {
                HttpHeaderTools.EndResponseForClientCache(PortalContext.Current.ModificationDateForClient.Value);
            }

            //check requested nodehead
            if (PortalContext.Current.ContextNodeHead == null)
            {
                return;
            }

            // Check if the requested content is executable (e.g. an aspx file) and has the correct file type. We must
            // call this here instead of OnEnter because the user must be authenticated for the check algorithm to work.
            CheckExecutableType(PortalContext.Current.ContextNodeHead, PortalContext.Current.ActionName);

            var modificationDate = PortalContext.Current.ContextNodeHead.ModificationDate;

            //If action name is given, do not do shortcircuit (eg. myimage.jpg?action=Edit
            //should be a server-rendered page) - except if this is an image resizer application.
            if (!string.IsNullOrEmpty(PortalContext.Current.ActionName))
            {
                var remapAction = PortalContext.Current.CurrentAction as RemapHttpAction;
                if (remapAction == null || remapAction.HttpHandlerNode == null)
                {
                    return;
                }

                if (!remapAction.HttpHandlerNode.GetNodeType().IsInstaceOfOrDerivedFrom(typeof(ImgResizeApplication).Name))
                {
                    return;
                }

                //check if the image resizer app was modified since the last request
                if (remapAction.HttpHandlerNode.ModificationDate > modificationDate)
                {
                    modificationDate = remapAction.HttpHandlerNode.ModificationDate;
                }
            }

            //set cache values for images, js/css files
            var cacheSetting = GetCacheHeaderSetting(PortalContext.Current.RequestedUri, PortalContext.Current.ContextNodeHead);

            if (cacheSetting.HasValue)
            {
                HttpHeaderTools.SetCacheControlHeaders(cacheSetting.Value);

                //in case of preview images do NOT return 304, because _undetectable_ permission changes
                //(on the image or on one of its parents) may change the preview image (e.g. display redaction or not).
                if (DocumentPreviewProvider.Current == null || !DocumentPreviewProvider.Current.IsPreviewOrThumbnailImage(PortalContext.Current.ContextNodeHead))
                {
                    //end response, if the content has not changed since the value posted by the client
                    HttpHeaderTools.EndResponseForClientCache(modificationDate);
                }
            }
        }