Beispiel #1
0
        public static string GetFilePath(string relPath, ThemeManifest defaultTheme, ThemeManifest currentTheme, bool checkExistance = true)
        {
            var relativePath = Paths.FixSeparators(relPath).TrimStart(new char[] { Path.DirectorySeparatorChar });

            if (currentTheme != null)
            {
                var themePath = Path.Combine(currentTheme.DirectoryPath, relativePath);
                if (File.Exists(themePath) && checkExistance)
                {
                    return(themePath);
                }
                else if (!checkExistance)
                {
                    return(themePath);
                }
            }

            if (defaultTheme != null)
            {
                var defaultPath = Path.Combine(defaultTheme.DirectoryPath, relativePath);
                if (File.Exists(defaultPath) && checkExistance)
                {
                    return(defaultPath);
                }
                else if (!checkExistance)
                {
                    return(defaultPath);
                }
            }

            return(null);
        }
        public void AddThemeManifest(ThemeManifest manifest)
        {
            Guard.ArgumentNotNull(() => manifest);

            TryRemoveManifest(manifest.ThemeName);
            _themes.TryAdd(manifest.ThemeName, manifest);
        }
Beispiel #3
0
 protected override void OnDispose(bool disposing)
 {
     if (disposing)
     {
         this.Manifest = null;
     }
 }
Beispiel #4
0
        public static void SetThemeInformation(IPlayniteAPI PlayniteApi)
        {
            string        defaultThemeName = "Default";
            ThemeManifest defaultTheme     = new ThemeManifest()
            {
                DirectoryName = defaultThemeName,
                DirectoryPath = Path.Combine(PlaynitePaths.ThemesProgramPath, ThemeManager.GetThemeRootDir(ApplicationMode.Desktop), defaultThemeName),
                Name          = defaultThemeName
            };

            ThemeManager.SetDefaultTheme(defaultTheme);

            ThemeManifest customTheme = null;
            var           theme       = PlayniteApi.ApplicationSettings.DesktopTheme;

            if (theme != ThemeManager.DefaultTheme.Name)
            {
                customTheme = ThemeManager.GetAvailableThemes(ApplicationMode.Desktop).SingleOrDefault(a => a.DirectoryName == theme);
                if (customTheme == null)
                {
                    ThemeManager.SetCurrentTheme(defaultTheme);
                }
                else
                {
                    ThemeManager.SetCurrentTheme(customTheme);
                }
            }
        }
Beispiel #5
0
        public static string GenerateNewTheme(ApplicationMode mode, string themeName)
        {
            var themeDirName    = Common.Paths.GetSafePathName(themeName).Replace(" ", string.Empty);
            var defaultThemeDir = Path.Combine(Paths.GetThemesPath(mode), "Default");
            var outDir          = Path.Combine(PlaynitePaths.ThemesProgramPath, mode.GetDescription(), themeDirName);

            if (Directory.Exists(outDir))
            {
                throw new Exception($"Theme directory \"{outDir}\" already exists.");
            }

            FileSystem.CreateDirectory(outDir);
            var defaultThemeXamlFiles = GenerateCommonThemeFiles(mode, outDir);

            CopyThemeDirectory(defaultThemeDir, outDir, defaultThemeXamlFiles.Select(a => Path.Combine(defaultThemeDir, a)).ToList());

            var themeDesc = new ThemeManifest()
            {
                Id              = themeName + "_" + Guid.NewGuid().ToString(),
                Author          = "Your Name Here",
                Name            = themeName,
                Version         = "1.0",
                Mode            = mode,
                ThemeApiVersion = ThemeManager.GetApiVersion(mode).ToString()
            };

            File.WriteAllText(Path.Combine(outDir, PlaynitePaths.ThemeManifestFileName), Serialization.ToYaml(themeDesc));
            Explorer.NavigateToFileSystemEntry(Path.Combine(outDir, PlaynitePaths.ThemeSlnFileName));
            return(outDir);
        }
        public void AddThemeManifest(ThemeManifest manifest)
        {
            Guard.ArgumentNotNull(() => manifest);

            TryRemoveManifest(manifest.ThemeName);
            _themes.TryAdd(manifest.ThemeName, manifest);
        }
Beispiel #7
0
        protected virtual ThemeManifestModel PrepareThemeManifestModel(ThemeManifest manifest, ThemeSettings themeSettings)
        {
            var model = new ThemeManifestModel
            {
                Name            = manifest.ThemeName,
                BaseTheme       = manifest.BaseThemeName,
                Title           = manifest.ThemeTitle,
                Description     = manifest.PreviewText,
                Author          = manifest.Author,
                Url             = manifest.Url,
                Version         = manifest.Version,
                IsMobileTheme   = manifest.MobileTheme,
                SupportsRtl     = manifest.SupportRtl,
                PreviewImageUrl = manifest.PreviewImageUrl.HasValue() ? manifest.PreviewImageUrl : "{0}/{1}/preview.png".FormatInvariant(manifest.Location, manifest.ThemeName),
                IsActive        = manifest.MobileTheme ? themeSettings.DefaultMobileTheme == manifest.ThemeName : themeSettings.DefaultDesktopTheme == manifest.ThemeName,
                State           = manifest.State
            };

            if (HostingEnvironment.VirtualPathProvider.FileExists("{0}/{1}/Views/Shared/ConfigureTheme.cshtml".FormatInvariant(manifest.Location, manifest.ThemeName)))
            {
                model.IsConfigurable = true;
            }

            return(model);
        }
 protected override void OnDispose(bool disposing)
 {
     if (disposing)
     {
         this.Manifest = null;
     }
 }
Beispiel #9
0
 public void SetPreviewTheme(string theme)
 {
     try
     {
         _httpContext.SetPreviewModeValue(OverriddenThemeNameKey, theme);
         _currentTheme = null;
     }
     catch { }
 }
		public FileInfo CreateThemePackage(ThemeManifest manifest)
		{
			var result = new PackagingResult
			{
				ExtensionType = "Theme",
				PackageName = manifest.ThemeName,
				PackageVersion = manifest.Version,
				PackageStream = _packageBuilder.BuildPackage(manifest)
			};

			return SavePackageFile(result);
		}
Beispiel #11
0
        public FileInfo CreateThemePackage(ThemeManifest manifest)
        {
            var result = new PackagingResult
            {
                ExtensionType  = "Theme",
                PackageName    = manifest.ThemeName,
                PackageVersion = manifest.Version,
                PackageStream  = _packageBuilder.BuildPackage(manifest)
            };

            return(SavePackageFile(result));
        }
        public ThemeManifestMaterializer(ThemeFolderData folderData)
        {
			Guard.ArgumentNotNull(() => folderData);

            _manifest = new ThemeManifest();

			_manifest.ThemeName = folderData.FolderName;
			_manifest.BaseThemeName = folderData.BaseTheme;
            _manifest.Location = folderData.VirtualBasePath;
            _manifest.Path = folderData.FullPath;
            _manifest.ConfigurationNode = folderData.Configuration.DocumentElement;
        }
Beispiel #13
0
        public FileInfo CreateThemePackage(string virtualPath)
        {
            //string virtualPath = "~/Themes/{0}".FormatInvariant(themeName);

            var manifest = ThemeManifest.Create(_vpp.MapPath(virtualPath));

            if (manifest != null)
            {
                return(CreateThemePackage(manifest));
            }

            return(null);
        }
        public ThemeManifestMaterializer(string themeName, string virtualPath, string path, XmlDocument doc)
        {
            Guard.ArgumentNotEmpty(() => themeName);
            Guard.ArgumentNotEmpty(() => path);
            Guard.ArgumentNotNull(() => doc);
            Guard.Against<SmartException>(doc.DocumentElement == null, "The provided theme configuration document must have a root element.");

            _manifest = new ThemeManifest();

            _manifest.ThemeName = themeName;
            _manifest.Location = virtualPath;
            _manifest.Path = path;
            _manifest.ConfigurationNode = doc.DocumentElement;
        }
        /// <summary>
        /// Validates the result LESS file by calling it's url.
        /// </summary>
        /// <param name="theme">Theme name</param>
        /// <param name="storeId">Stored Id</param>
        /// <returns>The error message when a parsing error occured, <c>null</c> otherwise</returns>
        private async Task <string> ValidateLess(ThemeManifest manifest, int storeId)
        {
            string error = string.Empty;
            var    url   = "{0}Themes/{1}/Content/theme.less?storeId={2}&theme={1}".FormatInvariant(
                _services.WebHelper.GetStoreLocation().EnsureEndsWith("/"),
                manifest.ThemeName,
                storeId);

            HttpWebRequest request  = WebRequest.CreateHttp(url);
            WebResponse    response = null;

            try
            {
                response = await request.GetResponseAsync();
            }
            catch (WebException ex)
            {
                if (ex.Response is HttpWebResponse)
                {
                    var webResponse = (HttpWebResponse)ex.Response;

                    var statusCode = webResponse.StatusCode;

                    if (statusCode == HttpStatusCode.InternalServerError)
                    {
                        // catch only 500, as this indicates a parsing error.
                        var stream = webResponse.GetResponseStream();

                        using (var streamReader = new StreamReader(stream))
                        {
                            // read the content (the error message has been put there)
                            error = streamReader.ReadToEnd();
                            streamReader.Close();
                            stream.Close();
                        }
                    }
                }
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return(error);
        }
        public static string ThemeAwareContent(this UrlHelper url, ThemeManifest manifest, string path)
        {
            path = EnsurePath(path);

            string fullPath = Path.Combine(manifest.Path, path);
            if (File.Exists(fullPath))
            {
                return url.Content(manifest.Location + "/" + Path.Combine(manifest.ThemeName, path));
            }

            fullPath = url.RequestContext.HttpContext.Server.MapPath("~/" + path);
            if (File.Exists(fullPath))
            {
                return url.Content("~/" + path);
            }

            return string.Empty;
        }
Beispiel #17
0
        internal static ExtensionDescriptor ConvertToExtensionDescriptor(this ThemeManifest themeManifest)
        {
            var descriptor = new ExtensionDescriptor
            {
                ExtensionType = "Theme",
                Location      = "~/Themes",
                Id            = themeManifest.ThemeName,
                Author        = themeManifest.Author.HasValue() ? themeManifest.Author : "[Unknown]",
                MinAppVersion = SmartStoreVersion.FullVersion,                 // TODO: (pkg) Add SupportedVersion to theme manifests
                Version       = new Version(themeManifest.Version),
                Name          = themeManifest.ThemeTitle,
                Description   = string.Empty,       // TODO: (pkg) Add description to theme manifests
                WebSite       = string.Empty,       // TODO: (pkg) Add author url to theme manifests,
                Tags          = string.Empty        // TODO: (pkg) Add tags to theme manifests
            };

            return(descriptor);
        }
Beispiel #18
0
        public void SetRequestTheme(string theme)
        {
            try
            {
                var dataTokens = _httpContext.Request.RequestContext.RouteData.DataTokens;
                if (theme.HasValue())
                {
                    dataTokens[OverriddenThemeNameKey] = theme;
                }
                else if (dataTokens.ContainsKey(OverriddenThemeNameKey))
                {
                    dataTokens.Remove(OverriddenThemeNameKey);
                }

                _currentTheme = null;
            }
            catch { }
        }
        public static string ThemeAwareContent(this UrlHelper url, ThemeManifest manifest, string path)
        {
            path = EnsurePath(path);

            string fullPath = Path.Combine(manifest.Path, path);

            if (File.Exists(fullPath))
            {
                return(url.Content(manifest.Location + "/" + Path.Combine(manifest.ThemeName, path)));
            }

            fullPath = url.RequestContext.HttpContext.Server.MapPath("~/" + path);
            if (File.Exists(fullPath))
            {
                return(url.Content("~/" + path));
            }

            return(string.Empty);
        }
        private void ThemeFolderRenamed(string name, string fullPath, string oldName, string oldFullPath)
        {
            TryRemoveManifest(oldName);

            var di = new DirectoryInfo(fullPath);

            try
            {
                var newManifest = ThemeManifest.Create(di.FullName);
                if (newManifest != null)
                {
                    this.AddThemeManifest(newManifest);
                    Debug.WriteLine("Changed theme manifest for '{0}'".FormatCurrent(name));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("ERR - Could not touch theme manifest '{0}': {1}".FormatCurrent(name, ex.Message));
            }
        }
Beispiel #21
0
        protected virtual ThemeManifestModel PrepareThemeManifestModel(ThemeManifest manifest, ThemeSettings themeSettings)
        {
            var model = new ThemeManifestModel
            {
                Name            = manifest.ThemeName,
                BaseTheme       = manifest.BaseThemeName,
                Title           = manifest.ThemeTitle,
                Description     = manifest.PreviewText,
                Author          = manifest.Author,
                Url             = manifest.Url,
                Version         = manifest.Version,
                PreviewImageUrl = manifest.PreviewImageUrl.HasValue() ? manifest.PreviewImageUrl : "{0}{1}/preview.png".FormatInvariant(manifest.Location.EnsureEndsWith("/"), manifest.ThemeName),
                IsActive        = themeSettings.DefaultTheme == manifest.ThemeName,
                State           = manifest.State,
            };

            model.IsConfigurable = HostingEnvironment.VirtualPathProvider.FileExists("{0}{1}/Views/Shared/ConfigureTheme.cshtml".FormatInvariant(manifest.Location.EnsureEndsWith("/"), manifest.ThemeName));

            return(model);
        }
        private void LoadThemes()
        {
            var folder          = EngineContext.Current.Resolve <IWebSiteFolder>();
            var virtualBasePath = _cfg.ThemeBasePath;

            foreach (var path in folder.ListDirectories(virtualBasePath))
            {
                try
                {
                    var manifest = ThemeManifest.Create(CommonHelper.MapPath(path), virtualBasePath);
                    if (manifest != null)
                    {
                        _themes.TryAdd(manifest.ThemeName, manifest);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("ERR - unable to create manifest for theme '{0}': {1}".FormatCurrent(path, ex.Message));
                }
            }
        }
        protected virtual ThemeManifestModel PrepareThemeManifestModel(ThemeManifest manifest, ThemeSettings themeSettings)
        {
            var model = new ThemeManifestModel
            {
                Name            = manifest.ThemeName,
                Title           = manifest.ThemeTitle,
                Description     = manifest.PreviewText,
                Author          = manifest.Author,
                Version         = manifest.Version,
                IsMobileTheme   = manifest.MobileTheme,
                SupportsRtl     = manifest.SupportRtl,
                PreviewImageUrl = manifest.PreviewImageUrl.HasValue() ? manifest.PreviewImageUrl : "{0}/{1}/preview.png".FormatInvariant(manifest.Location, manifest.ThemeName),
                IsActive        = manifest.MobileTheme ? themeSettings.DefaultMobileTheme == manifest.ThemeName : themeSettings.DefaultDesktopTheme == manifest.ThemeName
            };

            if (System.IO.File.Exists(System.IO.Path.Combine(manifest.Path, "Views\\Shared\\ConfigureTheme.cshtml")))
            {
                model.IsConfigurable = true;
            }

            return(model);
        }
Beispiel #24
0
        internal static ExtensionDescriptor GetExtensionDescriptor(this IPackage package, string extensionType)
        {
            bool isTheme = extensionType.IsCaseInsensitiveEqual("Theme");

            IPackageFile packageFile = package.GetFiles().FirstOrDefault(file =>
            {
                var fileName = Path.GetFileName(file.Path);
                return(fileName != null && fileName.Equals(isTheme ? "theme.config" : "Description.txt", StringComparison.OrdinalIgnoreCase));
            });

            ExtensionDescriptor descriptor = null;

            if (packageFile != null)
            {
                var filePath = packageFile.EffectivePath;
                if (filePath.HasValue())
                {
                    filePath = Path.Combine(HostingEnvironment.MapPath("~/"), filePath);
                    if (isTheme)
                    {
                        var themeManifest = ThemeManifest.Create(Path.GetDirectoryName(filePath));
                        if (themeManifest != null)
                        {
                            descriptor = themeManifest.ConvertToExtensionDescriptor();
                        }
                    }
                    else                     // is a Plugin
                    {
                        var pluginDescriptor = PluginFileParser.ParsePluginDescriptionFile(filePath);
                        if (pluginDescriptor != null)
                        {
                            descriptor = pluginDescriptor.ConvertToExtensionDescriptor();
                        }
                    }
                }
            }

            return(descriptor);
        }
        private void ThemeConfigChanged(string name, string fullPath)
        {
            var di = new DirectoryInfo(Path.GetDirectoryName(fullPath));

            try
            {
                var newManifest = ThemeManifest.Create(di.FullName);
                if (newManifest != null)
                {
                    this.AddThemeManifest(newManifest);
                    Debug.WriteLine("Changed theme manifest for '{0}'".FormatCurrent(name));
                }
                else
                {
                    // something went wrong (most probably no 'theme.config'): remove the manifest
                    TryRemoveManifest(di.Name);
                }
            }
            catch (Exception ex)
            {
                TryRemoveManifest(di.Name);
                Debug.WriteLine("ERR - Could not touch theme manifest '{0}': {1}".FormatCurrent(name, ex.Message));
            }
        }
		public void SetRequestTheme(string theme)
		{
			try
			{
				var dataTokens = _httpContext.Request.RequestContext.RouteData.DataTokens;
				if (theme.HasValue())
				{
					dataTokens[OverriddenThemeNameKey] = theme;
				}
				else if (dataTokens.ContainsKey(OverriddenThemeNameKey))
				{
					dataTokens.Remove(OverriddenThemeNameKey);
				}

				_currentTheme = null;
			}
			catch { }
		}
 public Stream BuildPackage(ThemeManifest themeManifest)
 {
     return BuildPackage(themeManifest.ConvertToExtensionDescriptor());
 }
		public void SetPreviewTheme(string theme)
		{
			try
			{
				_httpContext.SetPreviewModeValue(OverriddenThemeNameKey, theme);
				_currentTheme = null;
			}
			catch { }
		}
Beispiel #29
0
        private void ReadPackages(IVirtualPathProvider vpp)
        {
            if (!ValidatePaths())
            {
                return;
            }

            lstPlugins.DisplayMember = "Name";
            lstPlugins.ValueMember   = "Path";
            lstThemes.DisplayMember  = "Name";
            lstThemes.ValueMember    = "Path";

            lstPlugins.Items.Clear();
            lstThemes.Items.Clear();

            IEnumerable <string> dirs = Enumerable.Empty <string>();

            if (vpp.DirectoryExists("~/Plugins") || vpp.DirectoryExists("~/Themes"))
            {
                if (vpp.DirectoryExists("~/Plugins"))
                {
                    dirs = dirs.Concat(vpp.ListDirectories("~/Plugins"));
                }
                if (vpp.DirectoryExists("~/Themes"))
                {
                    dirs = dirs.Concat(vpp.ListDirectories("~/Themes"));
                }
            }
            else
            {
                dirs = vpp.ListDirectories("~/");
            }

            foreach (var dir in dirs)
            {
                bool isTheme = false;

                // is it a plugin?
                var filePath = vpp.Combine(dir, "Description.txt");
                if (!vpp.FileExists(filePath))
                {
                    // ...no! is it a theme?
                    filePath = vpp.Combine(dir, "theme.config");
                    if (!vpp.FileExists(filePath))
                    {
                        continue;
                    }

                    isTheme = true;
                }

                try
                {
                    if (isTheme)
                    {
                        var manifest = ThemeManifest.Create(vpp.MapPath(dir));
                        lstThemes.Items.Add(new ExtensionInfo(dir, manifest.ThemeName));
                    }
                    else
                    {
                        var descriptor = PluginFileParser.ParsePluginDescriptionFile(vpp.MapPath(filePath));
                        if (descriptor != null)
                        {
                            lstPlugins.Items.Add(new ExtensionInfo(dir, descriptor.FolderName));
                        }
                    }
                }
                catch
                {
                    continue;
                }
            }

            if (lstPlugins.Items.Count > 0)
            {
                tabMain.SelectedIndex = 0;
            }
            else if (lstThemes.Items.Count > 0)
            {
                tabMain.SelectedIndex = 1;
            }
        }
Beispiel #30
0
        /// <summary>
        /// Validates the result LESS file by calling it's url.
        /// </summary>
        /// <param name="theme">Theme name</param>
        /// <param name="siteId">Sited Id</param>
        /// <returns>The error message when a parsing error occured, <c>null</c> otherwise</returns>
        private string ValidateLess(ThemeManifest manifest, int siteId)
        {
            string error = string.Empty;

            var virtualPath = "~/Themes/{0}/Content/theme.less".FormatCurrent(manifest.ThemeName);
            var resolver    = this._themeFileResolver.Value;
            var file        = resolver.Resolve(virtualPath);

            if (file != null)
            {
                virtualPath = file.ResultVirtualPath;
            }

            var url = "{0}{1}?siteId={2}&theme={3}".FormatInvariant(
                _services.WebHelper.GetSiteLocation().EnsureEndsWith("/"),
                VirtualPathUtility.ToAbsolute(virtualPath).TrimStart('/'),
                siteId,
                manifest.ThemeName);

            HttpWebRequest request  = WebRequest.CreateHttp(url);
            WebResponse    response = null;

            try
            {
                response = request.GetResponse();
            }
            catch (WebException ex)
            {
                if (ex.Response is HttpWebResponse)
                {
                    var webResponse = (HttpWebResponse)ex.Response;

                    var statusCode = webResponse.StatusCode;

                    if (statusCode == HttpStatusCode.InternalServerError)
                    {
                        // catch only 500, as this indicates a parsing error.
                        var stream = webResponse.GetResponseStream();

                        using (var streamReader = new StreamReader(stream))
                        {
                            // read the content (the error message has been put there)
                            error = streamReader.ReadToEnd();
                            streamReader.Close();
                            stream.Close();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                var x = ex.Message;
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return(error);
        }
        public ActionResult UploadPackage(FormCollection form, string returnUrl = "")
        {
            if (returnUrl.IsEmpty())
            {
                returnUrl = _services.WebHelper.GetUrlReferrer();
            }

            bool isTheme = false;

            try
            {
                var file = Request.Files["packagefile"];
                if (file != null && file.ContentLength > 0)
                {
                    var requiredPermission = (isTheme = PackagingUtils.IsTheme(file.FileName))
                                                ? StandardPermissionProvider.ManageThemes
                                                : StandardPermissionProvider.ManagePlugins;

                    if (!_services.Permissions.Authorize(requiredPermission))
                    {
                        return(AccessDeniedView());
                    }

                    if (!Path.GetExtension(file.FileName).IsCaseInsensitiveEqual(".nupkg"))
                    {
                        NotifyError(T("Admin.Packaging.NotAPackage"));
                        return(Redirect(returnUrl));
                    }

                    var location = CommonHelper.MapPath("~/App_Data");
                    var appPath  = CommonHelper.MapPath("~/");

                    if (isTheme)
                    {
                        // avoid getting terrorized by IO events
                        _themeRegistry.Value.StopMonitoring();
                    }

                    var packageInfo = _packageManager.Install(file.InputStream, location, appPath);

                    if (isTheme)
                    {
                        // create manifest
                        if (packageInfo != null)
                        {
                            var manifest = ThemeManifest.Create(packageInfo.ExtensionDescriptor.Path);
                            if (manifest != null)
                            {
                                _themeRegistry.Value.AddThemeManifest(manifest);
                            }
                        }

                        // SOFT start IO events again
                        _themeRegistry.Value.StartMonitoring(false);
                    }
                }
                else
                {
                    NotifyError(T("Admin.Common.UploadFile"));
                    return(Redirect(returnUrl));
                }

                if (!isTheme)
                {
                    _services.WebHelper.RestartAppDomain();
                }
                NotifySuccess(T("Admin.Packaging.InstallSuccess"));
                return(Redirect(returnUrl));
            }
            catch (Exception exc)
            {
                NotifyError(exc);
                return(Redirect(returnUrl));
            }
        }
 public static string GetFilePath(string relPath, ThemeManifest defaultTheme)
 {
     return(GetFilePath(relPath, defaultTheme, ThemeManager.CurrentTheme));
 }
Beispiel #33
0
        /// <summary>
        /// Tries to resolve a file up in the current theme's hierarchy chain.
        /// </summary>
        /// <param name="virtualPath">The original virtual path of the theme file</param>
        /// <returns>
        /// If the current working themme is based on another theme AND the requested file
        /// was physically found in the theme's hierarchy chain, an instance of <see cref="InheritedThemeFileResult" /> will be returned.
        /// In any other case the return value is <c>null</c>.
        /// </returns>
        public InheritedThemeFileResult Resolve(string virtualPath)
        {
            Guard.NotEmpty(virtualPath, nameof(virtualPath));

            if (virtualPath[0] != '~')
            {
                virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
            }

            if (!ThemeHelper.PathIsInheritableThemeFile(virtualPath))
            {
                return(null);
            }

            bool isExplicit = false;

            virtualPath = ThemeHelper.TokenizePath(virtualPath, out var requestedThemeName, out var relativePath, out var query);

            Func <InheritedThemeFileResult> nullOrFile = () =>
            {
                return(isExplicit
                                        ? new InheritedThemeFileResult {
                    IsExplicit = true, OriginalVirtualPath = virtualPath, Query = query
                }
                                        : null);
            };

            ThemeManifest currentTheme = ResolveTheme(requestedThemeName, relativePath, query, out isExplicit);

            if (currentTheme?.BaseTheme == null)
            {
                // dont't bother resolving files: the current theme is not inherited.
                // Let the current VPP do the work.
                return(nullOrFile());
            }

            if (!currentTheme.ThemeName.Equals(requestedThemeName, StringComparison.OrdinalIgnoreCase))
            {
                if (!_themeRegistry.IsChildThemeOf(currentTheme.ThemeName, requestedThemeName))
                {
                    return(nullOrFile());
                }
            }
            else if (isExplicit && currentTheme.BaseTheme != null)
            {
                // A file from the base theme has been requested
                currentTheme = currentTheme.BaseTheme;
            }

            var fileKey = new FileKey(currentTheme.ThemeName, relativePath, query);
            InheritedThemeFileResult result;

            using (_rwLock.GetUpgradeableReadLock())
            {
                if (!_files.TryGetValue(fileKey, out result))
                {
                    using (_rwLock.GetWriteLock())
                    {
                        // ALWAYS begin the search with the current working theme's location!
                        string actualLocation = LocateFile(currentTheme.ThemeName, relativePath, out var resultVirtualPath, out var resultPhysicalPath);

                        if (actualLocation != null)
                        {
                            result = new InheritedThemeFileResult
                            {
                                RelativePath        = relativePath,
                                OriginalVirtualPath = virtualPath,
                                ResultVirtualPath   = resultVirtualPath,
                                ResultPhysicalPath  = resultPhysicalPath,
                                OriginalThemeName   = requestedThemeName,
                                ResultThemeName     = actualLocation,
                                IsExplicit          = isExplicit,
                                Query = query
                            };
                        }

                        _files[fileKey] = result;
                    }
                }
            }

            if (result == null)
            {
                return(nullOrFile());
            }

            return(result);
        }
Beispiel #34
0
        /// <summary>
        /// Validates the result LESS file by calling it's url.
        /// </summary>
        /// <param name="theme">Theme name</param>
        /// <param name="storeId">Stored Id</param>
        /// <returns>The error message when a parsing error occured, <c>null</c> otherwise</returns>
        private string ValidateLess(ThemeManifest manifest, int storeId)
        {
            string error = string.Empty;

            var virtualPath = "~/Themes/{0}/Content/theme.less".FormatCurrent(manifest.ThemeName);
            var resolver    = this._themeFileResolver.Value;
            var file        = resolver.Resolve(virtualPath);

            if (file != null)
            {
                virtualPath = file.ResultVirtualPath;
            }

            var url = "{0}?storeId={1}&theme={2}".FormatInvariant(
                WebHelper.GetAbsoluteUrl(virtualPath, this.Request),
                storeId,
                manifest.ThemeName);

            HttpWebRequest request = WebRequest.CreateHttp(url);

            request.UserAgent = "SmartStore.NET {0}".FormatInvariant(SmartStoreVersion.CurrentFullVersion);
            WebResponse response = null;

            try
            {
                response = request.GetResponse();
            }
            catch (WebException ex)
            {
                if (ex.Response is HttpWebResponse)
                {
                    var webResponse = (HttpWebResponse)ex.Response;

                    var statusCode = webResponse.StatusCode;

                    if (statusCode == HttpStatusCode.InternalServerError)
                    {
                        // catch only 500, as this indicates a parsing error.
                        var stream = webResponse.GetResponseStream();

                        using (var streamReader = new StreamReader(stream))
                        {
                            // read the content (the error message has been put there)
                            error = streamReader.ReadToEnd();
                            streamReader.Close();
                            stream.Close();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                var x = ex.Message;
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return(error);
        }
        public ActionResult UploadPackage(string returnUrl = "")
        {
            var    isTheme  = false;
            var    success  = false;
            string message  = null;
            string tempFile = "";

            try
            {
                var file = Request.ToPostedFileResult();
                if (file != null)
                {
                    var requiredPermission = (isTheme = PackagingUtils.IsTheme(file.FileName))
                        ? Permissions.Configuration.Theme.Upload
                        : Permissions.Configuration.Plugin.Upload;

                    if (!Services.Permissions.Authorize(requiredPermission))
                    {
                        message = T("Admin.AccessDenied.Description");
                        return(Json(new { success, file.FileName, message }));
                    }

                    if (!file.FileExtension.IsCaseInsensitiveEqual(".nupkg"))
                    {
                        return(Json(new { success, file.FileName, T("Admin.Packaging.NotAPackage").Text, returnUrl }));
                    }

                    var location = CommonHelper.MapPath("~/App_Data");
                    var appPath  = CommonHelper.MapPath("~/");

                    if (isTheme)
                    {
                        // Avoid getting terrorized by IO events.
                        _themeRegistry.Value.StopMonitoring();
                    }

                    var packageInfo = _packageManager.Install(file.Stream, location, appPath);

                    if (isTheme)
                    {
                        // Create manifest.
                        if (packageInfo != null)
                        {
                            var manifest = ThemeManifest.Create(packageInfo.ExtensionDescriptor.Path);
                            if (manifest != null)
                            {
                                _themeRegistry.Value.AddThemeManifest(manifest);
                            }
                        }

                        // SOFT start IO events again.
                        _themeRegistry.Value.StartMonitoring(false);
                    }
                }
                else
                {
                    return(Json(new { success, file.FileName, T("Admin.Common.UploadFile").Text, returnUrl }));
                }

                if (!isTheme)
                {
                    message = T("Admin.Packaging.InstallSuccess").Text;
                    Services.WebHelper.RestartAppDomain();
                }
                else
                {
                    message = T("Admin.Packaging.InstallSuccess.Theme").Text;
                }

                success = true;
            }
            catch (Exception ex)
            {
                message = ex.Message;
                Logger.Error(ex);
            }

            return(Json(new { success, tempFile, message, returnUrl }));
        }
 public static string ThemePath(this HtmlHelper html, ThemeManifest manifest, string path)
 {
     path = EnsurePath(path);
     return("{0}{1}/{2}".FormatCurrent(manifest.Location, manifest.ThemeName, path));
 }
		/// <summary>
		/// Validates the result LESS file by calling it's url.
		/// </summary>
		/// <param name="theme">Theme name</param>
		/// <param name="storeId">Stored Id</param>
		/// <returns>The error message when a parsing error occured, <c>null</c> otherwise</returns>
		private async Task<string> ValidateLess(ThemeManifest manifest, int storeId)
		{
			string error = string.Empty;
			var url = "{0}Themes/{1}/Content/theme.less?storeId={2}&theme={1}".FormatInvariant(
				_services.WebHelper.GetStoreLocation().EnsureEndsWith("/"), 
				manifest.ThemeName,
				storeId);

			HttpWebRequest request = WebRequest.CreateHttp(url);
			WebResponse response = null;

			try
			{
				response = await request.GetResponseAsync();
			}
			catch (WebException ex)
			{
				if (ex.Response is HttpWebResponse)
				{
					var webResponse = (HttpWebResponse)ex.Response;

					var statusCode = webResponse.StatusCode;

					if (statusCode == HttpStatusCode.InternalServerError)
					{
						// catch only 500, as this indicates a parsing error.
						var stream = webResponse.GetResponseStream();

						using (var streamReader = new StreamReader(stream))
						{
							// read the content (the error message has been put there)
							error = streamReader.ReadToEnd();
							streamReader.Close();
							stream.Close();
						}
					}
				}
			}
			finally
			{
				if (response != null)
					response.Close();
			}

			return error;
		}
 public static string ThemePath(this HtmlHelper html, ThemeManifest manifest, string path)
 {
     path = EnsurePath(path);
     return "{0}{1}/{2}".FormatCurrent(manifest.Location, manifest.ThemeName, path);
 }
		/// <summary>
		/// Validates the result LESS file by calling it's url.
		/// </summary>
		/// <param name="theme">Theme name</param>
		/// <param name="storeId">Stored Id</param>
		/// <returns>The error message when a parsing error occured, <c>null</c> otherwise</returns>
		private string ValidateLess(ThemeManifest manifest, int storeId)
		{
			
			string error = string.Empty;

			var virtualPath = "~/Themes/{0}/Content/theme.less".FormatCurrent(manifest.ThemeName);
			var resolver = this._themeFileResolver.Value;
			var file = resolver.Resolve(virtualPath);
			if (file != null)
			{
				virtualPath = file.ResultVirtualPath;
			}

			var url = "{0}?storeId={1}&theme={2}".FormatInvariant(
				WebHelper.GetAbsoluteUrl(virtualPath, this.Request),
				storeId,
				manifest.ThemeName);

			HttpWebRequest request = WebRequest.CreateHttp(url);
			request.UserAgent = "SmartStore.NET {0}".FormatInvariant(SmartStoreVersion.CurrentFullVersion);
			WebResponse response = null;

			try
			{
				response = request.GetResponse();
			}
			catch (WebException ex)
			{
				if (ex.Response is HttpWebResponse)
				{
					var webResponse = (HttpWebResponse)ex.Response;

					var statusCode = webResponse.StatusCode;

					if (statusCode == HttpStatusCode.InternalServerError)
					{
						// catch only 500, as this indicates a parsing error.
						var stream = webResponse.GetResponseStream();

						using (var streamReader = new StreamReader(stream))
						{
							// read the content (the error message has been put there)
							error = streamReader.ReadToEnd();
							streamReader.Close();
							stream.Close();
						}
					}
				}
			}
			catch (Exception ex)
			{
				var x = ex.Message;
			}
			finally
			{
				if (response != null)
					response.Close();
			}

			return error;
		}
Beispiel #40
0
 public Stream BuildPackage(ThemeManifest themeManifest)
 {
     return(BuildPackage(PackagingUtils.ConvertToExtensionDescriptor(themeManifest)));
 }
		protected virtual ThemeManifestModel PrepareThemeManifestModel(ThemeManifest manifest, ThemeSettings themeSettings)
        {
            var model = new ThemeManifestModel
                {
                    Name = manifest.ThemeName,
					BaseTheme = manifest.BaseThemeName,
                    Title = manifest.ThemeTitle,
                    Description = manifest.PreviewText,
                    Author = manifest.Author,
					Url = manifest.Url,
                    Version = manifest.Version,
                    IsMobileTheme = manifest.MobileTheme,
                    SupportsRtl = manifest.SupportRtl,
                    PreviewImageUrl = manifest.PreviewImageUrl.HasValue() ? manifest.PreviewImageUrl : "{0}/{1}/preview.png".FormatInvariant(manifest.Location, manifest.ThemeName),
                    IsActive = manifest.MobileTheme ? themeSettings.DefaultMobileTheme == manifest.ThemeName : themeSettings.DefaultDesktopTheme == manifest.ThemeName,
					State = manifest.State
                };

			if (HostingEnvironment.VirtualPathProvider.FileExists("{0}/{1}/Views/Shared/ConfigureTheme.cshtml".FormatInvariant(manifest.Location, manifest.ThemeName)))
			{
				model.IsConfigurable = true;
			}
            
            return model;
        }
        private void CreateThemeFromTemplates(TextWriter output, string themeName, string baseTheme, Guid? projectGuid, bool includeInSolution)
        {
            var themePath = HostingEnvironment.MapPath("~/Themes/" + themeName + "/");
            var createdFiles = new HashSet<string>();
            var createdFolders = new HashSet<string>();

            // create directories
            foreach (var folderName in _themeDirectories) {
                var folder = themePath + folderName;
                Directory.CreateDirectory(folder);
                if (!String.IsNullOrEmpty(folderName)) {
                    createdFolders.Add(folder);
                }
            }

            File.WriteAllText(themePath + "Web.config", File.ReadAllText(_codeGenTemplatePath + "ModuleRootWebConfig.txt"));
            createdFiles.Add(themePath + "Web.config");
            File.WriteAllText(themePath + "Scripts\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
            createdFiles.Add(themePath + "Scripts\\Web.config");
            File.WriteAllText(themePath + "Styles\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
            createdFiles.Add(themePath + "Styles\\Web.config");
            File.WriteAllText(themePath + "Content\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
            createdFiles.Add(themePath + "Content\\Web.config");

            var themeTemplate = new ThemeManifest() {Session = new Dictionary<string, object>()};
            themeTemplate.Session["ThemeName"] = themeName;
            themeTemplate.Session["BaseTheme"] = baseTheme;
            themeTemplate.Initialize();
            var templateText = themeTemplate.TransformText();

            File.WriteAllText(themePath + "Theme.txt", templateText);
            createdFiles.Add(themePath + "Theme.txt");

            File.WriteAllBytes(themePath + "Theme.png", File.ReadAllBytes(_codeGenTemplatePath + "Theme.png"));
            createdFiles.Add(themePath + "Theme.png");

            File.WriteAllText(themePath + "Placement.info", File.ReadAllText(_codeGenTemplatePath + "Placement.info"));
            createdFiles.Add(themePath + "Placement.info");

            // create new csproj for the theme
            if (projectGuid != null) {
                var itemGroup = CreateProjectItemGroup(themePath, createdFiles, createdFolders);
                string projectText = CreateCsProject(themeName, projectGuid, itemGroup);
                File.WriteAllText(themePath + "\\" + themeName + ".csproj", projectText);
            }

            if (includeInSolution) {
                if (projectGuid == null) {
                    // include in solution but dont create a project: just add the references to Coevery.Themes project
                    var itemGroup = CreateProjectItemGroup(HostingEnvironment.MapPath("~/Themes/"), createdFiles, createdFolders);
                    AddFilesToCoeveryThemesProject(output, itemGroup);
                    TouchSolution(output);
                }
                else {
                    // create a project (already done) and add it to the solution
                    AddToSolution(output, themeName, projectGuid, "Themes", SolutionDirectoryThemes);
                }
            }
        }
        private SaveThemeVariablesResult SaveThemeVariablesInternal(ThemeManifest manifest, int storeId, IDictionary <string, object> variables)
        {
            var result = new SaveThemeVariablesResult();
            var infos  = manifest.Variables;

            using (var scope = new DbContextScope(ctx: _rsVariables.Context, autoCommit: false))
            {
                var unsavedVars    = new List <string>();
                var savedThemeVars = _rsVariables.Table
                                     .Where(v => v.StoreId == storeId && v.Theme == manifest.ThemeName)
                                     .ToDictionary(x => x.Name);

                bool touched = false;

                foreach (var v in variables)
                {
                    ThemeVariableInfo info;
                    if (!infos.TryGetValue(v.Key, out info))
                    {
                        // var not specified in metadata so don't save
                        // TODO: (MC) delete from db also if it exists
                        continue;
                    }

                    var value = v.Value == null ? string.Empty : v.Value.ToString();

                    var savedThemeVar = savedThemeVars.Get(v.Key);
                    if (savedThemeVar != null)
                    {
                        if (value.IsEmpty() || String.Equals(info.DefaultValue, value, StringComparison.CurrentCultureIgnoreCase))
                        {
                            // it's either null or the default value, so delete
                            _rsVariables.Delete(savedThemeVar);
                            result.Deleted.Add(savedThemeVar);
                            touched = true;
                        }
                        else
                        {
                            // update entity
                            if (!savedThemeVar.Value.Equals(value, StringComparison.OrdinalIgnoreCase))
                            {
                                savedThemeVar.Value = value;
                                result.Updated.Add(savedThemeVar);
                                touched = true;
                            }
                        }
                    }
                    else
                    {
                        if (value.HasValue() && !String.Equals(info.DefaultValue, value, StringComparison.CurrentCultureIgnoreCase))
                        {
                            // insert entity (only when not default value)
                            unsavedVars.Add(v.Key);
                            savedThemeVar = new ThemeVariable
                            {
                                Theme   = manifest.ThemeName,
                                Name    = v.Key,
                                Value   = value,
                                StoreId = storeId
                            };
                            _rsVariables.Insert(savedThemeVar);
                            result.Inserted.Add(savedThemeVar);
                            touched = true;
                        }
                    }
                }

                if (touched)
                {
                    _rsVariables.Context.SaveChanges();
                }
            }

            return(result);
        }
		protected virtual ThemeManifestModel PrepareThemeManifestModel(ThemeManifest manifest, ThemeSettings themeSettings)
        {
            var model = new ThemeManifestModel
                {
                    Name = manifest.ThemeName,
                    Title = manifest.ThemeTitle,
                    Description = manifest.PreviewText,
                    Author = manifest.Author,
                    Version = manifest.Version,
                    IsMobileTheme = manifest.MobileTheme,
                    SupportsRtl = manifest.SupportRtl,
                    PreviewImageUrl = manifest.PreviewImageUrl.HasValue() ? manifest.PreviewImageUrl : "{0}/{1}/preview.png".FormatInvariant(manifest.Location, manifest.ThemeName),
                    IsActive = manifest.MobileTheme ? themeSettings.DefaultMobileTheme == manifest.ThemeName : themeSettings.DefaultDesktopTheme == manifest.ThemeName
                };

            if (System.IO.File.Exists(System.IO.Path.Combine(manifest.Path, "Views\\Shared\\ConfigureTheme.cshtml")))
            {
                model.IsConfigurable = true;
            }
            
            return model;
        }
        private void CreateThemeFromTemplates(TextWriter output, string themeName, string baseTheme, Guid?projectGuid, bool includeInSolution)
        {
            var themePath      = HostingEnvironment.MapPath("~/Themes/" + themeName + "/");
            var createdFiles   = new HashSet <string>();
            var createdFolders = new HashSet <string>();

            // create directories
            foreach (var folderName in _themeDirectories)
            {
                var folder = themePath + folderName;
                Directory.CreateDirectory(folder);
                if (!String.IsNullOrEmpty(folderName))
                {
                    createdFolders.Add(folder);
                }
            }

            File.WriteAllText(themePath + "Web.config", File.ReadAllText(_codeGenTemplatePath + "ModuleRootWebConfig.txt"));
            createdFiles.Add(themePath + "Web.config");
            File.WriteAllText(themePath + "Scripts\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
            createdFiles.Add(themePath + "Scripts\\Web.config");
            File.WriteAllText(themePath + "Styles\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
            createdFiles.Add(themePath + "Styles\\Web.config");
            File.WriteAllText(themePath + "Content\\Web.config", File.ReadAllText(_codeGenTemplatePath + "StaticFilesWebConfig.txt"));
            createdFiles.Add(themePath + "Content\\Web.config");

            var themeTemplate = new ThemeManifest()
            {
                Session = new Dictionary <string, object>()
            };

            themeTemplate.Session["ThemeName"] = themeName;
            themeTemplate.Session["BaseTheme"] = baseTheme;
            themeTemplate.Initialize();
            var templateText = themeTemplate.TransformText();

            File.WriteAllText(themePath + "Theme.txt", templateText);
            createdFiles.Add(themePath + "Theme.txt");

            File.WriteAllBytes(themePath + "Theme.png", File.ReadAllBytes(_codeGenTemplatePath + "Theme.png"));
            createdFiles.Add(themePath + "Theme.png");

            File.WriteAllText(themePath + "Placement.info", File.ReadAllText(_codeGenTemplatePath + "Placement.info"));
            createdFiles.Add(themePath + "Placement.info");

            // create new csproj for the theme
            if (projectGuid != null)
            {
                var    itemGroup   = CreateProjectItemGroup(themePath, createdFiles, createdFolders);
                string projectText = CreateCsProject(themeName, projectGuid, itemGroup);
                File.WriteAllText(themePath + "\\" + themeName + ".csproj", projectText);
            }

            if (includeInSolution)
            {
                if (projectGuid == null)
                {
                    // include in solution but dont create a project: just add the references to Coevery.Themes project
                    var itemGroup = CreateProjectItemGroup(HostingEnvironment.MapPath("~/Themes/"), createdFiles, createdFolders);
                    AddFilesToCoeveryThemesProject(output, itemGroup);
                    TouchSolution(output);
                }
                else
                {
                    // create a project (already done) and add it to the solution
                    AddToSolution(output, themeName, projectGuid, "Themes", SolutionDirectoryThemes);
                }
            }
        }