<commit_before>﻿using System;
using System.IO;
using System.Text;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.UI.WebControls;
using Talifun.Web.Crusher.Config;

namespace Talifun.Web.Crusher
{
    public class CrusherHelper
    {
        protected WebControl Control = new WebControl(HtmlTextWriterTag.Object);
        protected readonly ICacheManager CacheManager;
        protected readonly string QuerystringKeyName;
        protected readonly CssGroupElementCollection CssGroups;
        protected readonly JsGroupElementCollection JsGroups;
        protected readonly IRetryableFileOpener RetryableFileOpener;
        protected readonly IHasher Hasher;
        private static string CrusherHelperType = typeof(CrusherHelper).ToString();
        private static string CssType = "css";
        private static string JsType = "js";

        private CrusherHelper()
        {
            CacheManager = new HttpCacheManager();
            QuerystringKeyName = CurrentCrusherConfiguration.Current.QuerystringKeyName;
            CssGroups = CurrentCrusherConfiguration.Current.CssGroups;
            JsGroups = CurrentCrusherConfiguration.Current.JsGroups;
            RetryableFileOpener = new RetryableFileOpener();
            Hasher = new Hasher(RetryableFileOpener);
        }

        private static CrusherHelper Instance
        {
            get
            {
                return Nested.Instance;
            }
        }

        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }

            internal static readonly CrusherHelper Instance = new CrusherHelper();
        }

        public static string Css(string groupName)
        {
            return Instance.CssInternal(groupName);
        }

        public static string Js(string groupName)
        {
            return Instance.JsInternal(groupName);
        }

        public string CssInternal(string groupName)
        {
            var cssGroup = CssGroups[groupName];
            var outputFilePath = cssGroup.OutputFilePath;
            var scriptLinks = string.Empty;
            var cacheKey = GetKey(CssType, outputFilePath);

            var cachedValue = CacheManager.Get<string>(cacheKey);
            if (cachedValue != null)
            {
                scriptLinks = cachedValue;
            }
            else
            {
                if (!cssGroup.Debug)
                {
                    var fileInfo = new FileInfo(MapPath(outputFilePath));
                    var etag = Hasher.CalculateMd5Etag(fileInfo);
                    var url = string.IsNullOrEmpty(cssGroup.Url) ? this.ResolveUrl(outputFilePath) : cssGroup.Url;

                    scriptLinks = "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\" media=\"" + cssGroup.Media + "\" />";
                }
                else
                {
                    var scriptLinksBuilder = new StringBuilder();
                    foreach (CssFileElement file in cssGroup.Files)
                    {
                        var fileInfo = new FileInfo(MapPath(file.FilePath));
                        var etag = Hasher.CalculateMd5Etag(fileInfo);
                        var url = this.ResolveUrl(file.FilePath);

                        var fileName = fileInfo.Name.ToLower();

                        if (fileName.EndsWith(".less") || fileName.EndsWith(".less.css"))
                        {
                            etag = "'" + etag + "'";
                        }

                        scriptLinksBuilder.Append("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\" media=\"" + cssGroup.Media + "\" />");
                    }
                    scriptLinks = scriptLinksBuilder.ToString();
                }
                AddToCache(CssType, outputFilePath, scriptLinks);
            }

            return scriptLinks;
        }

        public string JsInternal(string groupName)
        {
            var jsGroup = JsGroups[groupName];
            var outputFilePath = jsGroup.OutputFilePath;
            var scriptLinks = string.Empty;

            var cacheKey = GetKey(JsType, outputFilePath);

            var cachedValue = CacheManager.Get<string>(cacheKey);
            if (cachedValue != null)
            {
                scriptLinks = cachedValue;
            }
            else
            {
                if (!jsGroup.Debug)
                {
                    var fileInfo = new FileInfo(MapPath(outputFilePath));
                    var etag = Hasher.CalculateMd5Etag(fileInfo);
                    var url = string.IsNullOrEmpty(jsGroup.Url) ? this.ResolveUrl(outputFilePath) : jsGroup.Url;

                    scriptLinks = "<script language=\"javascript\" type=\"text/javascript\" src=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\"></script>";
                }
                else
                {
                    var scriptLinksBuilder = new StringBuilder();
                    foreach (JsFileElement file in jsGroup.Files)
                    {
                        var fileInfo = new FileInfo(MapPath(file.FilePath));
                        var etag = Hasher.CalculateMd5Etag(fileInfo);
                        var url = this.ResolveUrl(file.FilePath);

                        scriptLinksBuilder.Append("<script language=\"javascript\" type=\"text/javascript\" src=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\"></script>");
                    }
                    scriptLinks = scriptLinksBuilder.ToString();
                }
                AddToCache(JsType, outputFilePath, scriptLinks);
            }

            return scriptLinks;
        }

        /// <summary>
        /// Get the cache key to use for caching.<commit_msg>When using an external CDN we want to be able to use https and http depending on which scheme the host is on<commit_after>﻿using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.UI.WebControls;
using Talifun.Web.Crusher.Config;

namespace Talifun.Web.Crusher
{
    public class CrusherHelper
    {
        protected WebControl Control = new WebControl(HtmlTextWriterTag.Object);
        protected readonly ICacheManager CacheManager;
        protected readonly string QuerystringKeyName;
        protected readonly CssGroupElementCollection CssGroups;
        protected readonly JsGroupElementCollection JsGroups;
        protected readonly IRetryableFileOpener RetryableFileOpener;
        protected readonly IHasher Hasher;
        private static string CrusherHelperType = typeof(CrusherHelper).ToString();
        private static string CssType = "css";
        private static string JsType = "js";

        private CrusherHelper()
        {
            CacheManager = new HttpCacheManager();
            QuerystringKeyName = CurrentCrusherConfiguration.Current.QuerystringKeyName;
            CssGroups = CurrentCrusherConfiguration.Current.CssGroups;
            JsGroups = CurrentCrusherConfiguration.Current.JsGroups;
            RetryableFileOpener = new RetryableFileOpener();
            Hasher = new Hasher(RetryableFileOpener);
        }

        private static CrusherHelper Instance
        {
            get
            {
                return Nested.Instance;
            }
        }

        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }

            internal static readonly CrusherHelper Instance = new CrusherHelper();
        }

        public static string Css(string groupName)
        {
            return Instance.CssInternal(groupName);
        }

        public static string Js(string groupName)
        {
            return Instance.JsInternal(groupName);
        }

        public string CssInternal(string groupName)
        {
            var cssGroup = CssGroups[groupName];
            var outputFilePath = cssGroup.OutputFilePath;
            var scriptLinks = string.Empty;
            var cacheKey = GetKey(CssType, outputFilePath);

            var cachedValue = CacheManager.Get<string>(cacheKey);
            if (cachedValue != null)
            {
                scriptLinks = cachedValue;
            }
            else
            {
                if (!cssGroup.Debug)
                {
                    var fileInfo = new FileInfo(MapPath(outputFilePath));
                    var etag = Hasher.CalculateMd5Etag(fileInfo);
					var url = cssGroup.Url;

					if (string.IsNullOrEmpty(url))
					{
						url = this.ResolveUrl(outputFilePath);
					}
					else
					{
						if (HttpContext.Current != null && url.StartsWith("//", StringComparison.InvariantCultureIgnoreCase))
						{
							url = HttpContext.Current.Request.Url.Scheme + ":" + url;
						}
					}

                    scriptLinks = "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\" media=\"" + cssGroup.Media + "\" />";
                }
                else
                {
                    var scriptLinksBuilder = new StringBuilder();
                    foreach (CssFileElement file in cssGroup.Files)
                    {
                        var fileInfo = new FileInfo(MapPath(file.FilePath));
                        var etag = Hasher.CalculateMd5Etag(fileInfo);
                        var url = this.ResolveUrl(file.FilePath);

                        var fileName = fileInfo.Name.ToLower();

                        if (fileName.EndsWith(".less") || fileName.EndsWith(".less.css"))
                        {
                            etag = "'" + etag + "'";
                        }

                        scriptLinksBuilder.Append("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\" media=\"" + cssGroup.Media + "\" />");
                    }
                    scriptLinks = scriptLinksBuilder.ToString();
                }
                AddToCache(CssType, outputFilePath, scriptLinks);
            }

            return scriptLinks;
        }

        public string JsInternal(string groupName)
        {
            var jsGroup = JsGroups[groupName];
            var outputFilePath = jsGroup.OutputFilePath;
            var scriptLinks = string.Empty;

            var cacheKey = GetKey(JsType, outputFilePath);

            var cachedValue = CacheManager.Get<string>(cacheKey);
            if (cachedValue != null)
            {
                scriptLinks = cachedValue;
            }
            else
            {
                if (!jsGroup.Debug)
                {
                    var fileInfo = new FileInfo(MapPath(outputFilePath));
                    var etag = Hasher.CalculateMd5Etag(fileInfo);
                    var url = string.IsNullOrEmpty(jsGroup.Url) ? this.ResolveUrl(outputFilePath) : jsGroup.Url;

					if (string.IsNullOrEmpty(url))
					{
						url = this.ResolveUrl(outputFilePath);
					}
					else
					{
						if (HttpContext.Current != null && url.StartsWith("//", StringComparison.InvariantCultureIgnoreCase))
						{
							url = HttpContext.Current.Request.Url.Scheme + ":" + url;
						}
					}

                    scriptLinks = "<script language=\"javascript\" type=\"text/javascript\" src=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\"></script>";
                }
                else
                {
                    var scriptLinksBuilder = new StringBuilder();
                    foreach (JsFileElement file in jsGroup.Files)
                    {
                        var fileInfo = new FileInfo(MapPath(file.FilePath));
                        var etag = Hasher.CalculateMd5Etag(fileInfo);
                        var url = this.ResolveUrl(file.FilePath);

                        scriptLinksBuilder.Append("<script language=\"javascript\" type=\"text/javascript\" src=\"" + url + "?" + QuerystringKeyName + "=" + etag + "\"></script>");
                    }
                    scriptLinks = scriptLinksBuilder.ToString();
                }
                AddToCache(JsType, outputFilePath, scriptLinks);
            }

            return scriptLinks;
        }

        /// <summary>
        /// Get the cache key to use for caching.
{'fraction_non_alphanumeric': 0.09381205814600048, 'fraction_numerical': 0.0006354754150448804, 'mean_word_length': 1.6174636174636174, 'pattern_counts': {'":': 2, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3617602', 'n_tokens_mistral': 3239, 'n_tokens_neox': 3019, 'n_words': 677}