Example #1
0
        //
        // Get CachedPathData for a virtual path.
        // The path may be supplied by user code, so check that it is valid.
        //
        static internal CachedPathData GetVirtualPathData(VirtualPath virtualPath, bool permitPathsOutsideApp)
        {
            if (!HostingEnvironment.IsHosted)
            {
                return(GetRootWebPathData());
            }

            // Make sure it's not relative
            if (virtualPath != null)
            {
                virtualPath.FailIfRelativePath();
            }

            // Check if the path is within the application.
            if (virtualPath == null || !virtualPath.IsWithinAppRoot)
            {
                if (permitPathsOutsideApp)
                {
                    return(GetApplicationPathData());
                }
                else
                {
                    throw new ArgumentException(SR.GetString(SR.Cross_app_not_allowed,
                                                             (virtualPath != null) ? virtualPath.VirtualPathString : "null"));
                }
            }

            // Construct a configPath based on the unvalidated virtualPath.
            string configPath = WebConfigurationHost.GetConfigPathFromSiteIDAndVPath(HostingEnvironment.SiteID, virtualPath);

            // Pass the virtualPath to GetConfigPathData to validate in the case where the
            // CachedPathData for the unsafeConfigPath is not found.
            return(GetConfigPathData(configPath));
        }
 internal static CachedPathData GetVirtualPathData(VirtualPath virtualPath, bool permitPathsOutsideApp)
 {
     if (!HostingEnvironment.IsHosted)
     {
         return(GetRootWebPathData());
     }
     if (virtualPath != null)
     {
         virtualPath.FailIfRelativePath();
     }
     if ((virtualPath != null) && virtualPath.IsWithinAppRoot)
     {
         return(GetConfigPathData(WebConfigurationHost.GetConfigPathFromSiteIDAndVPath(HostingEnvironment.SiteID, virtualPath)));
     }
     if (!permitPathsOutsideApp)
     {
         throw new ArgumentException(System.Web.SR.GetString("Cross_app_not_allowed", new object[] { (virtualPath != null) ? virtualPath.VirtualPathString : "null" }));
     }
     return(GetApplicationPathData());
 }
        private static CachedPathData GetConfigPathData(string configPath)
        {
            bool exists      = false;
            bool isDirectory = false;
            bool flag3       = IsCachedPathDataRemovable(configPath);

            if (flag3 && DoNotCacheUrlMetadata)
            {
                string      str          = null;
                VirtualPath path         = null;
                string      physicalPath = null;
                WebConfigurationHost.GetSiteIDAndVPathFromConfigPath(configPath, out str, out path);
                physicalPath = GetPhysicalPath(path);
                CachedPathData configPathData = GetConfigPathData(System.Configuration.ConfigPathUtility.GetParent(configPath));
                if (!string.IsNullOrEmpty(physicalPath))
                {
                    System.Web.Util.FileUtil.PhysicalPathStatus(physicalPath, false, false, out exists, out isDirectory);
                }
                CachedPathData data2 = new CachedPathData(configPath, path, physicalPath, exists);
                data2.Init(configPathData);
                return(data2);
            }
            string         key           = CreateKey(configPath);
            CacheInternal  cacheInternal = HttpRuntime.CacheInternal;
            CachedPathData data3         = (CachedPathData)cacheInternal.Get(key);

            if (data3 != null)
            {
                data3.WaitForInit();
                return(data3);
            }
            bool            flag4        = false;
            string          siteID       = null;
            VirtualPath     vpath        = null;
            CachedPathData  parentData   = null;
            CacheDependency dependencies = null;
            string          str6         = null;

            string[] filenames = null;
            string[] cachekeys = null;
            if (WebConfigurationHost.IsMachineConfigPath(configPath))
            {
                flag4 = true;
            }
            else
            {
                string parent = System.Configuration.ConfigPathUtility.GetParent(configPath);
                parentData = GetConfigPathData(parent);
                string str8 = CreateKey(parent);
                cachekeys = new string[] { str8 };
                if (!WebConfigurationHost.IsVirtualPathConfigPath(configPath))
                {
                    flag4 = true;
                }
                else
                {
                    flag4 = !flag3;
                    WebConfigurationHost.GetSiteIDAndVPathFromConfigPath(configPath, out siteID, out vpath);
                    str6 = GetPhysicalPath(vpath);
                    if (!string.IsNullOrEmpty(str6))
                    {
                        System.Web.Util.FileUtil.PhysicalPathStatus(str6, false, false, out exists, out isDirectory);
                        if (exists && !isDirectory)
                        {
                            filenames = new string[] { str6 };
                        }
                    }
                }
                try
                {
                    dependencies = new CacheDependency(0, filenames, cachekeys);
                }
                catch
                {
                }
            }
            CachedPathData    data5             = null;
            bool              flag5             = false;
            bool              flag6             = false;
            CacheItemPriority priority          = flag4 ? CacheItemPriority.NotRemovable : CacheItemPriority.Normal;
            TimeSpan          slidingExpiration = flag4 ? Cache.NoSlidingExpiration : UrlMetadataSlidingExpiration;

            try
            {
                using (dependencies)
                {
                    data5 = new CachedPathData(configPath, vpath, str6, exists);
                    try
                    {
                    }
                    finally
                    {
                        data3 = (CachedPathData)cacheInternal.UtcAdd(key, data5, dependencies, Cache.NoAbsoluteExpiration, slidingExpiration, priority, s_callback);
                        if (data3 == null)
                        {
                            flag5 = true;
                        }
                    }
                }
                if (!flag5)
                {
                    data3.WaitForInit();
                    return(data3);
                }
                lock (data5)
                {
                    try
                    {
                        data5.Init(parentData);
                        flag6 = true;
                    }
                    finally
                    {
                        data5._flags[1] = true;
                        Monitor.PulseAll(data5);
                        if (data5._flags[0x40])
                        {
                            data5.Close();
                        }
                    }
                    return(data5);
                }
            }
            finally
            {
                if (flag5)
                {
                    if (!data5._flags[1])
                    {
                        lock (data5)
                        {
                            data5._flags[1] = true;
                            Monitor.PulseAll(data5);
                            if (data5._flags[0x40])
                            {
                                data5.Close();
                            }
                        }
                    }
                    if (!flag6 || ((data5.ConfigRecord != null) && data5.ConfigRecord.HasInitErrors))
                    {
                        if (dependencies != null)
                        {
                            if (!flag6)
                            {
                                dependencies = new CacheDependency(0, null, cachekeys);
                            }
                            else
                            {
                                dependencies = new CacheDependency(0, filenames, cachekeys);
                            }
                        }
                        using (dependencies)
                        {
                            cacheInternal.UtcInsert(key, data5, dependencies, DateTime.UtcNow.AddSeconds(5.0), Cache.NoSlidingExpiration, CacheItemPriority.Normal, s_callback);
                        }
                    }
                }
            }
            return(data5);
        }
Example #4
0
        // Example of configPath = "machine/webroot/1/fxtest/sub/foo.aspx"
        // The configPath parameter must be lower case.
        static private CachedPathData GetConfigPathData(string configPath)
        {
            Debug.Assert(ConfigPathUtility.IsValid(configPath), "ConfigPathUtility.IsValid(configPath)");
            Debug.Assert(configPath == configPath.ToLower(CultureInfo.InvariantCulture), "configPath == configPath.ToLower(CultureInfo.InvariantCulture)");
            bool exists      = false;
            bool isDirectory = false;
            bool isRemovable = IsCachedPathDataRemovable(configPath);

            // if the sliding expiration is zero, we won't cache it unless it is a configPath for root web.config or above
            if (isRemovable && DoNotCacheUrlMetadata)
            {
                string      pathSiteID       = null;
                VirtualPath virtualFilePath  = null;
                string      physicalFilePath = null;
                WebConfigurationHost.GetSiteIDAndVPathFromConfigPath(configPath, out pathSiteID, out virtualFilePath);
                physicalFilePath = GetPhysicalPath(virtualFilePath);

                string         parentConfigPath = ConfigPathUtility.GetParent(configPath);
                CachedPathData pathParentData   = GetConfigPathData(parentConfigPath);
                if (!String.IsNullOrEmpty(physicalFilePath))
                {
                    FileUtil.PhysicalPathStatus(physicalFilePath, false, false, out exists, out isDirectory);
                }
                CachedPathData pathData = new CachedPathData(configPath, virtualFilePath, physicalFilePath, exists);
                pathData.Init(pathParentData);

                return(pathData);
            }

            //
            // First, see if the CachedPathData is in the cache.
            // we don't use Add for this lookup, as doing so requires
            // creating a CacheDependency, which can be slow as it may hit
            // the filesystem.
            //
            string             key           = CreateKey(configPath);
            CacheStoreProvider cacheInternal = HttpRuntime.Cache.InternalCache;
            CachedPathData     data          = (CachedPathData)cacheInternal.Get(key);

            // if found, return the data
            if (data != null)
            {
                data.WaitForInit();
                return(data);
            }

            // WOS


            bool cacheEntryIsNotRemovable = false;

            // if not found, try to add it
            string          siteID       = null;
            VirtualPath     virtualPath  = null;
            CachedPathData  parentData   = null;
            CacheDependency dependency   = null;
            string          physicalPath = null;

            string[] fileDependencies      = null;
            string[] cacheItemDependencies = null;

            if (WebConfigurationHost.IsMachineConfigPath(configPath))
            {
                cacheEntryIsNotRemovable = true;
            }
            else
            {
                // Make sure we have the parent data so we can create a dependency on the parent.
                // The parent dependency will ensure that configuration data in the parent
                // will be referenced by a cache hit on the child. (see UtcUpdateUsageRecursive in Cache.cs)
                string parentConfigPath = ConfigPathUtility.GetParent(configPath);
                parentData = GetConfigPathData(parentConfigPath);
                string parentKey = CreateKey(parentConfigPath);
                cacheItemDependencies = new string[1] {
                    parentKey
                };

                if (!WebConfigurationHost.IsVirtualPathConfigPath(configPath))
                {
                    // assume hardcoded levels above the path, such as root web.config, exist
                    cacheEntryIsNotRemovable = true;
                }
                else
                {
                    cacheEntryIsNotRemovable = !isRemovable;
                    WebConfigurationHost.GetSiteIDAndVPathFromConfigPath(configPath, out siteID, out virtualPath);
                    physicalPath = GetPhysicalPath(virtualPath);

                    // Add a dependency on the path itself, if it is a file,
                    // to handle the case where a file is deleted and replaced
                    // with a directory of the same name.
                    if (!String.IsNullOrEmpty(physicalPath))
                    {
                        FileUtil.PhysicalPathStatus(physicalPath, false, false, out exists, out isDirectory);
                        if (exists && !isDirectory)
                        {
                            fileDependencies = new string[1] {
                                physicalPath
                            };
                        }
                    }
                }

                try {
                    dependency = new CacheDependency(0, fileDependencies, cacheItemDependencies);
                }
                catch {
                    // CacheDependency ctor could fail because of bogus file path
                    // and it is ok not to watch those
                }
            }

            // Try to add the CachedPathData to the cache.
            CachedPathData    dataAdd           = null;
            bool              isDataCreator     = false;
            bool              initCompleted     = false;
            CacheItemPriority priority          = cacheEntryIsNotRemovable ? CacheItemPriority.NotRemovable : CacheItemPriority.Normal;
            TimeSpan          slidingExpiration = cacheEntryIsNotRemovable ? Cache.NoSlidingExpiration : UrlMetadataSlidingExpiration;

            try {
                using (dependency) {
                    dataAdd = new CachedPathData(configPath, virtualPath, physicalPath, exists);
                    try {
                    }
                    finally {
                        data = (CachedPathData)cacheInternal.Add(key, dataAdd, new CacheInsertOptions()
                        {
                            Dependencies      = dependency,
                            SlidingExpiration = slidingExpiration,
                            Priority          = priority,
                            OnRemovedCallback = s_callback
                        });

                        if (data == null)
                        {
                            isDataCreator = true;
                        }
                    }
                }

                // If another thread added it first, return the data
                if (!isDataCreator)
                {
                    data.WaitForInit();
                    return(data);
                }

                // This thread is the creator of the CachedPathData, initialize it
                lock (dataAdd) {
                    try {
                        dataAdd.Init(parentData);
                        initCompleted = true;
                    }
                    finally {
                        // free waiters
                        dataAdd._flags[FInited] = true;

                        // Wake up waiters.
                        Monitor.PulseAll(dataAdd);

                        if (dataAdd._flags[FCloseNeeded])
                        {
                            // If we have received a call back to close, then lets
                            // make sure that our config object is cleaned up
                            dataAdd.Close();
                        }
                    }
                }
            }
            finally {
                // All the work in this finally block is for the case where we're the
                // creator of the CachedPathData.
                if (isDataCreator)
                {
                    //



                    if (!dataAdd._flags[FInited])
                    {
                        lock (dataAdd) {
                            // free waiters
                            dataAdd._flags[FInited] = true;

                            // Wake up waiters.
                            Monitor.PulseAll(dataAdd);

                            if (dataAdd._flags[FCloseNeeded])
                            {
                                // If we have received a call back to close, then lets
                                // make sure that our config object is cleaned up
                                dataAdd.Close();
                            }
                        }
                    }

                    //
                    // Even though there is a try/catch handler surrounding the call to Init,
                    // a ThreadAbortException can still cause the handler to be bypassed.
                    //
                    // If there is an error, either a thread abort or an error in the config
                    // file itself, we do want to leave the item cached for a short period
                    // so that we do not revisit the error and potentially reparse the config file
                    // on every request.
                    //
                    // The reason we simply do not leave the item in the cache forever is that the
                    // problem that caused the configuration exception may be fixed without touching
                    // the config file in a way that causes a file change notification (for example, an
                    // acl change in a parent directory, or a change of path mapping in the metabase).
                    //
                    // NOTE: It is important to reinsert the item into the cache AFTER dropping
                    // the lock on dataAdd, in order to prevent the possibility of deadlock.
                    //
                    Debug.Assert(dataAdd._flags[FInited], "_flags[FInited]");
                    if (!initCompleted || (dataAdd.ConfigRecord != null && dataAdd.ConfigRecord.HasInitErrors))
                    {
                        //
                        // Create a new dependency object as the old one cannot be reused.
                        // Do not include a file dependency if initialization could not be completed,
                        // as invoking the file system could lead to further errors during a thread abort.
                        //
                        if (dependency != null)
                        {
                            if (!initCompleted)
                            {
                                dependency = new CacheDependency(0, null, cacheItemDependencies);
                            }
                            else
                            {
                                dependency = new CacheDependency(0, fileDependencies, cacheItemDependencies);
                            }
                        }

                        using (dependency) {
                            cacheInternal.Insert(key, dataAdd, new CacheInsertOptions()
                            {
                                Dependencies       = dependency,
                                AbsoluteExpiration = DateTime.UtcNow.AddSeconds(5),
                                OnRemovedCallback  = s_callback
                            });
                        }
                    }
                }
            }

            return(dataAdd);
        }