diff --git a/src/Libraries/Nop.Services/Helpers/BrowscapXmlParser.cs b/src/Libraries/Nop.Services/Helpers/BrowscapXmlParser.cs index 82f7c6490b2..da66f079772 100644 --- a/src/Libraries/Nop.Services/Helpers/BrowscapXmlParser.cs +++ b/src/Libraries/Nop.Services/Helpers/BrowscapXmlParser.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; using Nop.Core; @@ -14,7 +15,7 @@ namespace Nop.Services.Helpers public class BrowscapXmlHelper { private readonly List _crawlerUserAgentsRegexp; - + public BrowscapXmlHelper(string filePath) { _crawlerUserAgentsRegexp = new List(); @@ -26,9 +27,7 @@ private void Initialize(string filePath) { using (var sr = new StreamReader(filePath)) { - var text = sr.ReadToEnd().Replace("&", "&"); - - var browsercapItems = XDocument.Parse(text).Root.Return(x => x.Element("browsercapitems"), null); + var browsercapItems = XDocument.Load(sr).Root.Return(x => x.Element("browsercapitems"), null); if (browsercapItems == null) throw new Exception("Incorrect file format"); @@ -37,8 +36,9 @@ private void Initialize(string filePath) //only crawlers .Where(IsBrowscapItemIsCrawler) //get only user agent names - .Select(e => e.Attribute("name").Return(a => a.Value.Replace("&", "&"), "")) - .Where(s => !string.IsNullOrEmpty(s)) + .Select(e => e.Attribute("name")) + .Where(e => e != null && !string.IsNullOrEmpty(e.Value)) + .Select(e => e.Value) .Select(ToRegexp)); } } @@ -47,13 +47,14 @@ private static bool IsBrowscapItemIsCrawler(XElement browscapItem) { var el = browscapItem.Elements("item").FirstOrDefault(e => e.Attribute("name").Return(a => a.Value, "") == "Crawler"); - return el == null ? false : el.Attribute("value").Return(a => a.Value.ToLower() == "true", false); + return el != null && el.Attribute("value").Return(a => a.Value.ToLower() == "true", false); } - private string ToRegexp(string str) + private static string ToRegexp(string str) { - str = String.Format("^{0}$", Regex.Escape(str)); - return str.Replace("\\?", ".").Replace("\\*", ".*?"); + var sb = new StringBuilder(Regex.Escape(str)); + sb.Replace("&", "&").Replace("\\?", ".").Replace("\\*", ".*?"); + return string.Format("^{0}$", sb); } /// diff --git a/src/Libraries/Nop.Services/Helpers/UserAgentHelper.cs b/src/Libraries/Nop.Services/Helpers/UserAgentHelper.cs index c96776ce2a9..dd006a75802 100644 --- a/src/Libraries/Nop.Services/Helpers/UserAgentHelper.cs +++ b/src/Libraries/Nop.Services/Helpers/UserAgentHelper.cs @@ -15,6 +15,7 @@ public partial class UserAgentHelper : IUserAgentHelper { private readonly NopConfig _config; private readonly HttpContextBase _httpContext; + private static readonly object _locker = new object(); /// /// Ctor @@ -37,11 +38,19 @@ protected virtual BrowscapXmlHelper GetBrowscapXmlHelper() if (String.IsNullOrEmpty(_config.UserAgentStringsPath)) return null; - var filePath = CommonHelper.MapPath(_config.UserAgentStringsPath); - var bowscapXmlHelper = new BrowscapXmlHelper(filePath); - - Singleton.Instance = bowscapXmlHelper; - return Singleton.Instance; + //prevent multi loading data + lock (_locker) + { + //data can be loaded while we waited + if (Singleton.Instance != null) + return Singleton.Instance; + + var filePath = CommonHelper.MapPath(_config.UserAgentStringsPath); + var browscapXmlHelper = new BrowscapXmlHelper(filePath); + Singleton.Instance = browscapXmlHelper; + + return Singleton.Instance; + } } ///