Ejemplo n.º 1
0
        private static void AddScriptResourceFromAssembly(ScriptBuckets scriptBuckets, Assembly assembly)
        {
            object[]         customAttributes = assembly.GetCustomAttributes(typeof(ScriptResourceAttribute), false);
            HashSet <string> hashSet          = new HashSet <string>();

            foreach (CombinableScripts combinableScripts in scriptBuckets)
            {
                hashSet.Add(combinableScripts.Alias.ToLowerInvariant());
            }
            foreach (object obj in customAttributes)
            {
                ScriptResourceAttribute scriptResourceAttribute = (ScriptResourceAttribute)obj;
                string typeName = scriptResourceAttribute.TypeName;
                string item     = typeName.ToLowerInvariant();
                if (!hashSet.Contains(item))
                {
                    hashSet.Add(item);
                    scriptBuckets.Add(new CombinableScripts
                    {
                        Alias   = typeName,
                        Scripts = new ScriptsEntries
                        {
                            new ScriptEntry(assembly.FullName, typeName + ".js", false)
                        }
                    });
                }
            }
        }
Ejemplo n.º 2
0
        internal static CultureInfo DetermineNearestAvailableCulture(
            Assembly assembly,
            string scriptResourceName,
            CultureInfo culture)
        {
            if (String.IsNullOrEmpty(scriptResourceName))
            {
                return(CultureInfo.InvariantCulture);
            }

            Tuple <Assembly, string, CultureInfo> cacheKey = Tuple.Create(assembly, scriptResourceName, culture);
            CultureInfo cachedCulture = (CultureInfo)_cultureCache[cacheKey];

            if (cachedCulture == null)
            {
                string releaseResourceName =
                    scriptResourceName.EndsWith(".debug.js", StringComparison.OrdinalIgnoreCase) ?
                    scriptResourceName.Substring(0, scriptResourceName.Length - 9) + ".js" :
                    null;

                ScriptResourceInfo resourceInfo        = ScriptResourceInfo.GetInstance(assembly, scriptResourceName);
                ScriptResourceInfo releaseResourceInfo = (releaseResourceName != null) ?
                                                         ScriptResourceInfo.GetInstance(assembly, releaseResourceName) : null;

                if (!String.IsNullOrEmpty(resourceInfo.ScriptResourceName) ||
                    ((releaseResourceInfo != null) && !String.IsNullOrEmpty(releaseResourceInfo.ScriptResourceName)))
                {
                    ResourceManager resourceManager =
                        ScriptResourceAttribute.GetResourceManager(resourceInfo.ScriptResourceName, assembly);
                    ResourceManager releaseResourceManager = (releaseResourceInfo != null) ?
                                                             ScriptResourceAttribute.GetResourceManager(releaseResourceInfo.ScriptResourceName, assembly) : null;

                    ResourceSet localizedSet = null;
                    ResourceSet releaseSet   = null;
                    if (resourceManager != null)
                    {
                        resourceManager.GetResourceSet(CultureInfo.InvariantCulture, true, true);
                        // Look for the explicitly localized version of the resources that is nearest the culture.
                        localizedSet = resourceManager.GetResourceSet(culture, true, false);
                    }
                    if (releaseResourceManager != null)
                    {
                        releaseResourceManager.GetResourceSet(CultureInfo.InvariantCulture, true, true);
                        // Look for the explicitly localized version of the resources that is nearest the culture.
                        releaseSet = releaseResourceManager.GetResourceSet(culture, true, false);
                    }
                    if ((resourceManager != null) || (releaseResourceManager != null))
                    {
                        while ((localizedSet == null) && (releaseSet == null))
                        {
                            culture = culture.Parent;
                            if (culture.Equals(CultureInfo.InvariantCulture))
                            {
                                break;
                            }
                            localizedSet = resourceManager.GetResourceSet(culture, true, false);
                            releaseSet   = (releaseResourceManager != null) ?
                                           releaseResourceManager.GetResourceSet(culture, true, false) : null;
                        }
                    }
                    else
                    {
                        culture = CultureInfo.InvariantCulture;
                    }
                }
                else
                {
                    culture = CultureInfo.InvariantCulture;
                }
                // Neutral assembly culture falls back on invariant
                CultureInfo neutralCulture = GetAssemblyNeutralCulture(assembly);
                if ((neutralCulture != null) && neutralCulture.Equals(culture))
                {
                    culture = CultureInfo.InvariantCulture;
                }
                cachedCulture           = culture;
                _cultureCache[cacheKey] = cachedCulture;
            }
            return(cachedCulture);
        }
Ejemplo n.º 3
0
        private static void ProcessRequestInternal(
            HttpResponseBase response,
            string decryptedString,
            VirtualFileReader fileReader)
        {
            if (String.IsNullOrEmpty(decryptedString))
            {
                Throw404();
            }
            bool zip;
            bool singleAssemblyReference;

            // See GetScriptResourceUrl comment below for first character meanings.
            switch (decryptedString[0])
            {
            case 'Z':
            case 'z':
                singleAssemblyReference = true;
                zip = true;
                break;

            case 'U':
            case 'u':
                singleAssemblyReference = true;
                zip = false;
                break;

            case 'Q':
            case 'q':
                singleAssemblyReference = false;
                zip = true;
                break;

            case 'R':
            case 'r':
                singleAssemblyReference = false;
                zip = false;
                break;

            case 'T':
                OutputEmptyPage(response, decryptedString.Substring(1));
                return;

            default:
                Throw404();
                return;
            }

            decryptedString = decryptedString.Substring(1);
            if (String.IsNullOrEmpty(decryptedString))
            {
                Throw404();
            }
            string[] decryptedData = decryptedString.Split('|');

            if (singleAssemblyReference)
            {
                // expected: <assembly>|<resource>|<culture>[|#|<hash>]
                if (decryptedData.Length != 3 && decryptedData.Length != 5)
                {
                    // The decrypted data must have 3 parts plus an optional 2 part hash code separated by pipes.
                    Throw404();
                }
            }
            else
            {
                // expected: <assembly1>|<resource1a>,<culture1a>,<resource1b>,<culture1b>,...|<assembly2>|<resource2a>,<culture2a>,<resource2b>,<culture2b>,...|#|<hash>
                if (decryptedData.Length % 2 != 0)
                {
                    // The decrypted data must have an even number of parts separated by pipes.
                    Throw404();
                }
            }

            StringBuilder script = new StringBuilder();

            string firstContentType = null;

            if (singleAssemblyReference)
            {
                // single assembly reference, format is
                // <assembly>|<resource>|<culture>
                string assemblyName = decryptedData[0];
                string resourceName = decryptedData[1];
                string cultureName  = decryptedData[2];

                Assembly assembly = GetAssembly(assemblyName);
                if (assembly == null)
                {
                    Throw404();
                }

                script.Append(ScriptResourceAttribute.GetScriptFromWebResourceInternal(
                                  assembly,
                                  resourceName,
                                  String.IsNullOrEmpty(cultureName) ? CultureInfo.InvariantCulture : new CultureInfo(cultureName),
                                  zip,
                                  out firstContentType
                                  ));
            }
            else
            {
                // composite script reference, format is:
                // <assembly1>|<resource1a>,<culture1a>,<resource1b>,<culture1b>,...|<assembly2>|<resource2a>,<culture2a>,<resource2b>,<culture2b>,...
                // Assembly is empty for path based scripts, and their resource/culture list is <path1>,<path2>,...

                // If an assembly starts with "#", the segment is ignored (expected that this includes a hash to ensure
                // url uniqueness when resources are changed). Also, for forward compatibility '#' segments may contain
                // other data.

                bool needsNewline = false;

                for (int i = 0; i < decryptedData.Length; i += 2)
                {
                    string assemblyName = decryptedData[i];
                    bool   hasAssembly  = !String.IsNullOrEmpty(assemblyName);
                    if (hasAssembly && assemblyName[0] == '#')
                    {
                        // hash segments are ignored, it contains a hash code for url uniqueness
                        continue;
                    }
                    Debug.Assert(!String.IsNullOrEmpty(decryptedData[i + 1]));
                    string[] resourcesAndCultures = decryptedData[i + 1].Split(',');

                    if (resourcesAndCultures.Length == 0)
                    {
                        Throw404();
                    }

                    Assembly assembly = hasAssembly ? GetAssembly(assemblyName) : null;

                    if (assembly == null)
                    {
                        // The scripts are path-based
                        if (firstContentType == null)
                        {
                            firstContentType = "text/javascript";
                        }
                        for (int j = 0; j < resourcesAndCultures.Length; j++)
                        {
                            Encoding encoding;
                            // DevDiv Bugs 197242
                            // path will either be absolute, as in "/app/foo/bar.js" or app relative, as in "~/foo/bar.js"
                            // ToAbsolute() ensures it is in the form /app/foo/bar.js
                            // This conversion was not done when the url was created to conserve url length.
                            string path = _bypassVirtualPathResolution ?
                                          resourcesAndCultures[j] :
                                          VirtualPathUtility.ToAbsolute(resourcesAndCultures[j]);
                            string fileContents = fileReader(path, out encoding);

                            if (needsNewline)
                            {
                                // Output an additional newline between resources but not for the last one
                                script.Append('\n');
                            }
                            needsNewline = true;

                            script.Append(fileContents);
                        }
                    }
                    else
                    {
                        Debug.Assert(resourcesAndCultures.Length % 2 == 0, "The list of resource names and cultures must have an even number of parts separated by commas.");

                        for (int j = 0; j < resourcesAndCultures.Length; j += 2)
                        {
                            try {
                                string contentType;
                                string resourceName = resourcesAndCultures[j];
                                string cultureName  = resourcesAndCultures[j + 1];

                                if (needsNewline)
                                {
                                    // Output an additional newline between resources but not for the last one
                                    script.Append('\n');
                                }
                                needsNewline = true;

                                script.Append(ScriptResourceAttribute.GetScriptFromWebResourceInternal(
                                                  assembly,
                                                  resourceName,
                                                  String.IsNullOrEmpty(cultureName) ? CultureInfo.InvariantCulture : new CultureInfo(cultureName),
                                                  zip,
                                                  out contentType
                                                  ));

                                if (firstContentType == null)
                                {
                                    firstContentType = contentType;
                                }
                            }
                            catch (MissingManifestResourceException ex) {
                                throw Create404(ex);
                            }
                            catch (HttpException ex) {
                                throw Create404(ex);
                            }
                        }
                    }
                }
            }

            if (ScriptingScriptResourceHandlerSection.ApplicationSettings.EnableCaching)
            {
                PrepareResponseCache(response);
            }
            else
            {
                PrepareResponseNoCache(response);
            }

            response.ContentType = firstContentType;

            if (zip)
            {
                using (MemoryStream zipped = new MemoryStream()) {
                    using (Stream outputStream = new GZipStream(zipped, CompressionMode.Compress)) {
                        // The choice of an encoding matters little here.
                        // Input streams being of potentially different encodings, UTF-8 is the better
                        // choice as it's the natural encoding for JavaScript.
                        using (StreamWriter writer = new StreamWriter(outputStream, Encoding.UTF8)) {
                            writer.Write(script.ToString());
                        }
                    }
                    byte[] zippedBytes = zipped.ToArray();
                    response.AddHeader("Content-encoding", "gzip");
                    response.OutputStream.Write(zippedBytes, 0, zippedBytes.Length);
                }
            }
            else
            {
                // Bug DevDiv #175061, we don't want to force any encoding here and let the default
                // encoding apply no matter what the incoming scripts might have been encoded with.
                response.Write(script.ToString());
            }
        }